anvil · reference

Provider wire formats

How each canonical concept maps to each wire protocol. Verified against provider docs in Oct 2026. These APIs change, so re-check the linked docs when a fixture surprises you. ← course ·

Requests

CanonicalAnthropic MessagesOpenAI Chat CompletionsOpenAI ResponsesGemini
EndpointPOST /v1/messagesPOST /chat/completionsPOST /v1/responsesPOST /v1beta/models/{m}:streamGenerateContent?alt=sse
Authx-api-key + anthropic-version: 2023-06-01Authorization: Bearer (optional locally)Authorization: Bearerx-goog-api-key
systemsystem (string or blocks)first message role: systeminstructionssystemInstruction.parts[].text
Role::Assistantassistantassistantoutput itemsmodel
Text{type:text,text}{type:text,text} / stringinput_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 msgseparate {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 replayablewhole 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_tokensmax_tokens (required)max_completion_tokens (compat: max_tokens)max_output_tokensgenerationConfig.maxOutputTokens
Cachingcache_control:{type:ephemeral} ≤ 4 breakpointsautomatic prefix + prompt_cache_keyautomatic + prompt_cache_keyimplicit; explicit cachedContents

Streams

StreamEventAnthropicOpenAI ChatOpenAI ResponsesGemini
TextDeltacontent_block_delta / text_deltachoices[0].delta.contentresponse.output_text.deltaparts[].text (not thought)
ReasoningDeltathinking_deltadelta.reasoning_content / reasoning (compat)response.reasoning_summary_text.deltaparts[].text with thought:true
ReasoningDone(meta)signature_delta → content_block_stopn/aresponse.output_item.done (reasoning item)signature rides on functionCall part
ToolCallStartcontent_block_start type tool_usefirst delta.tool_calls[i] with id+nameresponse.output_item.added (function_call)whole functionCall part (synthesize id)
ToolCallDeltainput_json_delta.partial_jsontool_calls[i].function.argumentsresponse.function_call_arguments.deltaemit the full args once
Usagemessage_start (input, cache) + message_delta (cumulative output)final chunk with usage (needs include_usage). Subtract cached from prompt.response.completed.response.usageusageMetadata (subtract cached, add thoughts to output)
Finishmessage_delta.stop_reason → message_stopfinish_reason → [DONE] (may be missing)response.completed / .incompletefinishReason, stream end. STOP + calls ⇒ ToolUse
Error mid-streamevent: error (overloaded_error){"error":…} chunkresponse.failed / error{"error":…}
Ignoreping, unknown typesempty deltasother response.* eventsempty parts

Finish reasons

CanonicalAnthropicOpenAI ChatGemini
EndTurnend_turn, stop_sequence, pause_turnstopSTOP (no calls)
ToolUsetool_usetool_calls (or stop + calls)STOP + function calls
MaxTokensmax_tokenslengthMAX_TOKENS
Refusalrefusalcontent_filterSAFETY, RECITATION, PROHIBITED_CONTENT, BLOCKLIST, SPII

Primary docs