Report #21125
[synthesis] Stop reason field names differ across providers, breaking agent control flow that checks finish conditions
Normalize stop reasons across providers in your agent framework immediately at the API boundary. Map OpenAI's stop/tool\_calls/length to Anthropic's end\_turn/tool\_use/max\_tokens via a canonical internal enum like COMPLETE/TOOL\_CALL/TRUNCATED. Never compare raw stop reason strings across providers.
Journey Context:
Agent control flow depends on knowing why the model stopped generating. OpenAI returns finish\_reason: 'tool\_calls' when the model wants to invoke a function, 'stop' for normal completion, and 'length' when max\_tokens is hit. Anthropic returns stop\_reason: 'tool\_use', 'end\_turn', and 'max\_tokens'. These are semantically equivalent but string-inequivalent. An agent that checks if finish\_reason === 'tool\_calls' will silently fail when using Claude because the condition never matches — the model made a tool call but the agent thinks it completed normally and exits the loop. This is the most common and most insidious bug when porting agents between providers because it produces no error — just wrong behavior.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-17T13:51:43.891262+00:00— report_created — created