after_model() — langchain Function Reference
Architecture documentation for the after_model() function in tool_call_limit.py from the langchain codebase.
Entity Profile
Dependency Diagram
graph TD 2d4474df_60a6_0dd0_a7de_afbe664f4896["after_model()"] 68f7858b_b207_3223_e360_e5e5b35adf21["ToolCallLimitMiddleware"] 2d4474df_60a6_0dd0_a7de_afbe664f4896 -->|defined in| 68f7858b_b207_3223_e360_e5e5b35adf21 b3442318_f785_696a_62ca_a4ede582e8fd["aafter_model()"] b3442318_f785_696a_62ca_a4ede582e8fd -->|calls| 2d4474df_60a6_0dd0_a7de_afbe664f4896 6385d4be_67e3_d055_9df4_4d5383df6d8d["_separate_tool_calls()"] 2d4474df_60a6_0dd0_a7de_afbe664f4896 -->|calls| 6385d4be_67e3_d055_9df4_4d5383df6d8d 5f1bf505_60e2_b89c_ee3a_094cab95139a["_build_tool_message_content()"] 2d4474df_60a6_0dd0_a7de_afbe664f4896 -->|calls| 5f1bf505_60e2_b89c_ee3a_094cab95139a 5ac56516_2d78_c12c_204e_15f599bbc7f4["_build_final_ai_message_content()"] 2d4474df_60a6_0dd0_a7de_afbe664f4896 -->|calls| 5ac56516_2d78_c12c_204e_15f599bbc7f4 style 2d4474df_60a6_0dd0_a7de_afbe664f4896 fill:#6366f1,stroke:#818cf8,color:#fff
Relationship Graph
Source Code
libs/langchain_v1/langchain/agents/middleware/tool_call_limit.py lines 326–463
def after_model(
self,
state: ToolCallLimitState[ResponseT],
runtime: Runtime[ContextT],
) -> dict[str, Any] | None:
"""Increment tool call counts after a model call and check limits.
Args:
state: The current agent state.
runtime: The langgraph runtime.
Returns:
State updates with incremented tool call counts. If limits are exceeded
and exit_behavior is `'end'`, also includes a jump to end with a
`ToolMessage` and AI message for the single exceeded tool call.
Raises:
ToolCallLimitExceededError: If limits are exceeded and `exit_behavior`
is `'error'`.
NotImplementedError: If limits are exceeded, `exit_behavior` is `'end'`,
and there are multiple tool calls.
"""
# Get the last AIMessage to check for tool calls
messages = state.get("messages", [])
if not messages:
return None
# Find the last AIMessage
last_ai_message = None
for message in reversed(messages):
if isinstance(message, AIMessage):
last_ai_message = message
break
if not last_ai_message or not last_ai_message.tool_calls:
return None
# Get the count key for this middleware instance
count_key = self.tool_name or "__all__"
# Get current counts
thread_counts = state.get("thread_tool_call_count", {}).copy()
run_counts = state.get("run_tool_call_count", {}).copy()
current_thread_count = thread_counts.get(count_key, 0)
current_run_count = run_counts.get(count_key, 0)
# Separate tool calls into allowed and blocked
allowed_calls, blocked_calls, new_thread_count, new_run_count = self._separate_tool_calls(
last_ai_message.tool_calls, current_thread_count, current_run_count
)
# Update counts to include only allowed calls for thread count
# (blocked calls don't count towards thread-level tracking)
# But run count includes blocked calls since they were attempted in this run
thread_counts[count_key] = new_thread_count
run_counts[count_key] = new_run_count + len(blocked_calls)
# If no tool calls are blocked, just update counts
if not blocked_calls:
if allowed_calls:
return {
"thread_tool_call_count": thread_counts,
"run_tool_call_count": run_counts,
}
return None
# Get final counts for building messages
final_thread_count = thread_counts[count_key]
final_run_count = run_counts[count_key]
# Handle different exit behaviors
if self.exit_behavior == "error":
# Use hypothetical thread count to show which limit was exceeded
hypothetical_thread_count = final_thread_count + len(blocked_calls)
raise ToolCallLimitExceededError(
thread_count=hypothetical_thread_count,
run_count=final_run_count,
thread_limit=self.thread_limit,
run_limit=self.run_limit,
tool_name=self.tool_name,
)
Domain
Subdomains
Called By
Source
Frequently Asked Questions
What does after_model() do?
after_model() is a function in the langchain codebase, defined in libs/langchain_v1/langchain/agents/middleware/tool_call_limit.py.
Where is after_model() defined?
after_model() is defined in libs/langchain_v1/langchain/agents/middleware/tool_call_limit.py at line 326.
What does after_model() call?
after_model() calls 3 function(s): _build_final_ai_message_content, _build_tool_message_content, _separate_tool_calls.
What calls after_model()?
after_model() is called by 1 function(s): aafter_model.
Analyze Your Own Codebase
Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.
Try Supermodel Free