Home / Function/ after_model() — langchain Function Reference

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

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