AI & Agent Dev Bug Sandbox logo
AI & Agent Dev Bug Sandbox
Back to Radar

Create_agent Ends Loop On Invalid Structured-Output Call When Ordinary Tool Call Is In Same Batch

When an invalid structured-output tool call and an ordinary tool call appear in the same AIMessage, the agent terminates after the first model call without feeding the validation error back to the model. As a result, no retry happens and structured_response is None.

highConfidence 92%LangchainAffected V1.3.15Affected V1.4.0

Origin Analysis

In `_make_tools_to_model_edge` in `langchain/agents/factory.py`, exit condition 3 returns `end_destination` whenever any trailing ToolMessage has the name of a structured-output tool. It cannot distinguish a validation-error ToolMessage (which carries the structured tool's name but no status='error') from a successful structured output. With a sibling ordinary tool call, the tools node runs and triggers this premature exit, bypassing the model node's retry path.
Create an agent with `response_format=ToolStrategy(Terminal)` and a simple tool `read_file`. Use a fake model that first returns an AIMessage with two tool calls: an invalid Terminal call (result='invalid') and a valid read_file call. Invoke the agent. Observe that the model is called only once, no feedback ToolMessage for Terminal is seen, and structured_response is None. Running without the sibling call shows two model calls and a valid structured_response.

Fixing Code Block

Edge Case Audit

This change relies on `structured_response` being None until a valid structured output is produced. If any code path legitimately sets `structured_response` to None after a successful parse, the exit condition would never fire for that turn, potentially causing an infinite loop. Additionally, if `structured_response` is left over from a previous successful attempt while a new invalid structured tool call arrives, the edge could prematurely exit. Mitigation: clear or reset `structured_response` at the start of each agent invocation and ensure only successful structured outputs set a non-None value. Rollback by restoring the original condition `if any(t.name in structured_output_tools for t in tool_messages): return end_destination`.

Ecosystem Topology