Loop Prevention Middleware in Deep Agents
I’m using a custom loop prevention middleware that tracks the tool parameters and responses. If the same tool is called multiple times with the same parameters and produces the same result within a single run, the middleware stops execution to prevent infinite loops.
This works well for most agents, but with Deep Agents, some workflows intentionally call the same tools for verification, or incremental updates. In these cases, the middleware incorrectly identifies the behaviour as a loop and stops the agent.
Is there a recommended way to handle this scenario?
Also, since loop prevention seems like a common requirement, it would be great if LangChain provided an inbuilt loop prevention mechanism with configurable behavior instead of requiring custom middleware.
hi @Jewells
There already is a built-in, configurable mechanism. LangChain ships ToolCallLimitMiddleware and ModelCallLimitMiddleware. The tool-call one literally lists “Protecting against runaway agent loops” as a use case. It’s configurable by:
tool_name (global vs. per-tool, stackable)
run_limit (per turn) vs. thread_limit (whole conversation, needs a checkpointer)
exit_behavior: "continue" (default - injects an error ToolMessage and lets the model self-correct), "error" (raises), "end" (clean stop)
The false-positive problem is a design flaw. “Same tool + same args + same result → stop on first repeat” inherently conflates loops with polling, read-after-write verification, and parallel fan-out (LangChain’s own subgraph docs recommend ToolCallLimitMiddleware for exactly the duplicate-parallel-call case, not duplicate detection). Possible four graded fixes:
- prefer a count cap over duplicate detection
- scope per tool and exempt natural repeaters
- if you still want dedup, a tolerant, non-terminal custom middleware using the
wrap_tool_call hook
- treat persistent repeats as a prompt/tool-result root-cause signal