| Canonical | Anthropic Messages | OpenAI Chat Completions | OpenAI Responses | Gemini |
| Endpoint | POST /v1/messages | POST /chat/completions | POST /v1/responses | POST /v1beta/models/{m}:streamGenerateContent?alt=sse |
| Auth | x-api-key + anthropic-version: 2023-06-01 | Authorization: Bearer (optional locally) | Authorization: Bearer | x-goog-api-key |
| system | system (string or blocks) | first message role: system | instructions | systemInstruction.parts[].text |
| Role::Assistant | assistant | assistant | output items | model |
| Text | {type:text,text} | {type:text,text} / string | input_text / output_text | {text} |
| Image | {type:image,source:{type:base64,media_type,data}} | {type:image_url,image_url:{url:"data:…"}} | {type:input_image,image_url} | {inlineData:{mimeType,data}} |
| ToolCall | {type:tool_use,id,name,input:{…}} | tool_calls[{id,type:function,function:{name,arguments:"…"}}] | item {type:function_call,call_id,name,arguments:"…"} | {functionCall:{name,args}, thoughtSignature?} |
| ToolResult | {type:tool_result,tool_use_id,content,is_error} in a user msg | separate {role:tool,tool_call_id,content} per result (no is_error) | item {type:function_call_output,call_id,output} | {functionResponse:{name,response:{…}}}, matched by name |
| Reasoning replay | {type:thinking,thinking,signature} | not replayable | whole reasoning item (with encrypted_content) | thoughtSignature on parts (required for Gemini 3 function calls) |
| Tool spec | {name,description,input_schema} | {type:function,function:{name,description,parameters}} | {type:function,name,description,parameters} (flat) | [{functionDeclarations:[{name,description,parameters}]}] (schema subset) |
| max_tokens | max_tokens (required) | max_completion_tokens (compat: max_tokens) | max_output_tokens | generationConfig.maxOutputTokens |
| Caching | cache_control:{type:ephemeral} ≤ 4 breakpoints | automatic prefix + prompt_cache_key | automatic + prompt_cache_key | implicit; explicit cachedContents |
| StreamEvent | Anthropic | OpenAI Chat | OpenAI Responses | Gemini |
| TextDelta | content_block_delta / text_delta | choices[0].delta.content | response.output_text.delta | parts[].text (not thought) |
| ReasoningDelta | thinking_delta | delta.reasoning_content / reasoning (compat) | response.reasoning_summary_text.delta | parts[].text with thought:true |
| ReasoningDone(meta) | signature_delta → content_block_stop | n/a | response.output_item.done (reasoning item) | signature rides on functionCall part |
| ToolCallStart | content_block_start type tool_use | first delta.tool_calls[i] with id+name | response.output_item.added (function_call) | whole functionCall part (synthesize id) |
| ToolCallDelta | input_json_delta.partial_json | tool_calls[i].function.arguments | response.function_call_arguments.delta | emit the full args once |
| Usage | message_start (input, cache) + message_delta (cumulative output) | final chunk with usage (needs include_usage). Subtract cached from prompt. | response.completed.response.usage | usageMetadata (subtract cached, add thoughts to output) |
| Finish | message_delta.stop_reason → message_stop | finish_reason → [DONE] (may be missing) | response.completed / .incomplete | finishReason, stream end. STOP + calls ⇒ ToolUse |
| Error mid-stream | event: error (overloaded_error) | {"error":…} chunk | response.failed / error | {"error":…} |
| Ignore | ping, unknown types | empty deltas | other response.* events | empty parts |