test_agent_hooks_run_once_with_multiple_model_calls() — langchain Function Reference
Architecture documentation for the test_agent_hooks_run_once_with_multiple_model_calls() function in test_framework.py from the langchain codebase.
Entity Profile
Dependency Diagram
graph TD f9cd3634_d4af_0a56_9d92_0c457772b3a1["test_agent_hooks_run_once_with_multiple_model_calls()"] 7756726f_6234_5476_ab8e_0716a0d87ec6["TestAgentHooksCombined"] f9cd3634_d4af_0a56_9d92_0c457772b3a1 -->|defined in| 7756726f_6234_5476_ab8e_0716a0d87ec6 style f9cd3634_d4af_0a56_9d92_0c457772b3a1 fill:#6366f1,stroke:#818cf8,color:#fff
Relationship Graph
Source Code
libs/langchain_v1/tests/unit_tests/agents/middleware/core/test_framework.py lines 958–1041
def test_agent_hooks_run_once_with_multiple_model_calls(self) -> None:
"""Test that before_agent and after_agent run only once per thread.
This test verifies that agent-level hooks (before_agent, after_agent) execute
exactly once per agent invocation, regardless of how many tool calling loops occur.
This is different from model-level hooks (before_model, after_model) which run
on every model invocation within the tool calling loop.
"""
execution_log = []
@tool
def sample_tool_agent(query: str) -> str:
"""A sample tool for testing."""
return f"Result for: {query}"
@before_agent
def log_before_agent(*_args: Any, **_kwargs: Any) -> None:
execution_log.append("before_agent")
@before_model
def log_before_model(*_args: Any, **_kwargs: Any) -> None:
execution_log.append("before_model")
@after_agent
def log_after_agent(*_args: Any, **_kwargs: Any) -> None:
execution_log.append("after_agent")
@after_model
def log_after_model(*_args: Any, **_kwargs: Any) -> None:
execution_log.append("after_model")
# Model will call a tool twice, then respond with final answer
# This creates 3 model invocations total, but agent hooks should still run once
model = FakeToolCallingModel(
tool_calls=[
[{"name": "sample_tool_agent", "args": {"query": "first"}, "id": "1"}],
[{"name": "sample_tool_agent", "args": {"query": "second"}, "id": "2"}],
[], # Third call returns no tool calls (final answer)
]
)
agent = create_agent(
model=model,
tools=[sample_tool_agent],
middleware=[log_before_agent, log_before_model, log_after_model, log_after_agent],
)
agent.invoke(
{"messages": [HumanMessage("Test")]}, config={"configurable": {"thread_id": "abc"}}
)
assert execution_log == [
"before_agent",
"before_model",
"after_model",
"before_model",
"after_model",
"before_model",
"after_model",
"after_agent",
]
agent.invoke(
{"messages": [HumanMessage("Test")]}, config={"configurable": {"thread_id": "abc"}}
)
assert execution_log == [
"before_agent",
"before_model",
"after_model",
"before_model",
"after_model",
"before_model",
"after_model",
"after_agent",
"before_agent",
"before_model",
"after_model",
"before_model",
"after_model",
"before_model",
Domain
Subdomains
Source
Frequently Asked Questions
What does test_agent_hooks_run_once_with_multiple_model_calls() do?
test_agent_hooks_run_once_with_multiple_model_calls() is a function in the langchain codebase, defined in libs/langchain_v1/tests/unit_tests/agents/middleware/core/test_framework.py.
Where is test_agent_hooks_run_once_with_multiple_model_calls() defined?
test_agent_hooks_run_once_with_multiple_model_calls() is defined in libs/langchain_v1/tests/unit_tests/agents/middleware/core/test_framework.py at line 958.
Analyze Your Own Codebase
Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.
Try Supermodel Free