How to cap tool and sub-agent calls in DeepAgents?

In DeepAgents, when I register multiple tools and sub-agents, I want to prevent the loop from running indefinitely. How can I enforce hard limits—e.g., maximum tool calls, maximum sub-agent invocations, or a recursion/depth cap—similar to how Create React Agent lets you configure recursion limits? Pointers to config flags, code samples, or best practices for step/token budgeting would be great.

Thanks!
V

Hi @valtahomes

good to see your engagement here! :rocket: Sorry you’ve been waiting a few days for an answer :pensive_face:
Let me think a bit and I will reply to your post.

Hi @valtahomes

Sorry for the long wait.

I have investigated a little and:

  • DeepAgents’ README states that the agent created with create_deep_agent “is just a LangGraph graph,” which means you can use LangGraph’s run configuration and graph controls to bound execution (including recursion/step limits) and to add termination logic. DeepAgents README
  • Also, when LangGraph exceeds its configured recursion limit, you’ll see an error similar to “Recursion limit reached without hitting a stop condition,” which you can catch or avoid by setting an appropriate limit. LangChain discussion

Example 1 - Hard cap with recursion limit (Python)

Use a hard global cap via the run config. If the limit is hit, LangGraph will raise a recursion error.

from deepagents import create_deep_agent
# from langgraph.errors import GraphRecursionError  # optional: catch explicitly if available in your version

agent = create_deep_agent(tools=[...], instructions="...")

try:
    # Hard cap for the entire run
    result = agent.invoke({"messages": [{"role": "user", "content": "..."}]}, config={"recursion_limit": 12})
except Exception as e:
    # Handle recursion-limit error (e.g., GraphRecursionError) gracefully
    result = {"error": str(e)}

Notes:

  • The recursion_limit in the run config caps total super-steps across the graph (parent + any subgraphs).

  • When exceeded, LangGraph raises an error (see discussion). Discussion

  • DeepAgents’ agent being a LangGraph graph makes this directly applicable. DeepAgents README

Example 2 - Cap tool/sub-agent counts with explicit counters (LangGraph)

In addition to a global recursion cap, add explicit counters in graph state and terminate early via conditional edges.

class State(TypedDict):
    messages: Annotated[list[AnyMessage], add_messages]
    tool_calls: int
    subagent_calls: int
    max_tool_calls: int
    max_subagent_calls: int

def check_budgets(state: State):
    if state["tool_calls"] >= state["max_tool_calls"]:
        return END
    if state["subagent_calls"] >= state["max_subagent_calls"]:
        return END
    return "work"

def work(state: State) -> State:
    # ... perform one unit of work
    # increment either tool_calls or subagent_calls when you execute them
    return state

builder = StateGraph(State)
builder.add_node("work", work)
builder.add_conditional_edges(START, check_budgets, {END: END, "work": "work"})
builder.add_conditional_edges("work", check_budgets, {END: END, "work": "work"})
graph = builder.compile()

out = graph.invoke({
    "messages": [],
    "tool_calls": 0,
    "subagent_calls": 0,
    "max_tool_calls": 5,
    "max_subagent_calls": 2,
}, config={"recursion_limit": 20})

This gives you belt-and-suspenders: a global recursion cap plus explicit limits on tools and sub-agents.

References: DeepAgents README, LangChain discussion.

Example 3 - Cap sub-agent invocations locally and globally

If a sub-agent is itself a graph (common with DeepAgents), you can:

  • Set a lower recursion_limit when calling the sub-agent.
  • Increment a parent-level subagent_calls counter to enforce a global ceiling.
def call_subagent(parent_state: State, subagent_graph):
    if parent_state["subagent_calls"] >= parent_state["max_subagent_calls"]:
        return parent_state  # refuse to delegate
    parent_state["subagent_calls"] += 1
    sub_out = subagent_graph.invoke(parent_state, config={"recursion_limit": 6})
    # merge results as needed
    return {**parent_state, **sub_out}

References: DeepAgents README.

Example 4 - Classic LangChain agent loop cap (if applicable)

If you’re using a classic LangChain ReAct-style agent loop instead of a LangGraph graph, set a max-iteration cap so the tool-calling loop can’t run indefinitely.

from langchain.agents import AgentExecutor

executor = AgentExecutor(
    agent=agent,
    tools=tools,
    max_iterations=3,  # stop after N tool iterations
)

Docs: AgentExecutor.

Practical budgeting tips (steps, tokens, time)

  • Use a hard global cap: Always set recursion_limit/recursionLimit on runs, especially when sub-agents are involved.
  • Counters + stop edges: Keep tool_calls/subagent_calls in state. End early using conditional edges.
  • Model-level caps: Configure reasonable max_tokens for generations and timeouts per call.
  • Trim context: Summarize/trim messages to stay within context limits and reduce step pressure.
  • Instrument: Log tool/sub-agent counts and recursion errors; fail gracefully with a helpful message to the user.

Thank you. this is quite helpful.

Let me try some experiments.

1 Like