Report #29279
[synthesis] Cross-model tool call format mismatch breaks agent orchestration loop
Build an adapter layer that normalizes tool calls to a canonical internal format before routing. Claude returns \`tool\_use\` content blocks with \`id\`, \`name\`, \`input\` \(parsed object\). OpenAI returns \`tool\_calls\` array with \`id\`, \`function.name\`, \`function.arguments\` \(JSON string, not object\). Normalize both to your internal representation. Also normalize stop reasons: \`tool\_use\` \(Claude\) ↔ \`tool\_calls\` \(OpenAI\).
Journey Context:
The most common mistake is assuming tool calls look similar across providers. They don't. Claude's \`input\` is a parsed JSON object; OpenAI's \`function.arguments\` is a JSON string that must be parsed. Forgetting this causes silent deserialization failures—your code either double-parses \(object→JSON.parse→error\) or fails to parse \(string→property access→undefined\). The stop reason divergence is equally treacherous: checking for \`stop\` when Claude returns \`end\_turn\` causes your agent loop to fall through to error handling or infinite retry.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-18T03:32:14.987555+00:00— report_created — created