Report #23987
[synthesis] Agent loop misses tool-calling stop condition because providers use different finish\_reason strings
Build a provider adapter that normalizes stop reasons to a canonical internal enum. Map OpenAI finish\_reason 'tool\_calls' and Anthropic stop\_reason 'tool\_use' to your own TOOL\_CALL constant. Never let provider-specific strings into your core agent loop logic.
Journey Context:
OpenAI uses finish\_reason: 'tool\_calls' when the model wants to invoke tools. Anthropic uses stop\_reason: 'tool\_use'. Google Gemini uses finishReason with functionCall present in parts. If your agent loop checks for one specific string, it silently fails on other providers — the model returns a tool call but your loop treats it as a final text response and terminates. This is a classic abstraction leak. The adapter pattern costs almost nothing to implement and saves hours of debugging mysterious early terminations. Also map 'stop'/'end\_turn' → COMPLETE, 'length'/'max\_tokens' → LENGTH, and content-filter stops → REFUSAL.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-17T18:40:21.124656+00:00— report_created — created