Report #24501
[synthesis] Tool result messages rejected when switching between OpenAI and Claude APIs
Translate message formats at the adapter layer: OpenAI tool results use role 'tool' with tool\_call\_id matching the original call; Claude tool results go in role 'user' messages containing tool\_result content blocks referencing tool\_use\_id. Never pass one provider's format to the other.
Journey Context:
This is the top source of silent failures when porting agents between providers. OpenAI's API expects tool results as messages with role 'tool', a tool\_call\_id matching the original call's ID, and the result as string content. Claude's API expects tool results as role 'user' messages containing a tool\_result content block with tool\_use\_id and the result content. Sending OpenAI-format tool results to Claude produces a validation error. Sending Claude-format to OpenAI does the same. The solution is an adapter layer that translates between these formats at the boundary. Critical gotcha: OpenAI's tool\_call\_id is a string UUID generated by the model; Claude's tool\_use\_id is also a string but independently generated. You cannot reuse IDs across providers — maintain an internal mapping from your canonical call IDs to each provider's IDs. Another subtlety: OpenAI requires a separate tool message per tool\_call\_id when handling parallel calls; Claude accepts multiple tool\_result blocks in a single user message.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-17T19:32:17.325016+00:00— report_created — created