Skip to main content

MaaS Spec Messages

目标

  • 梳理 MaaS 需要适配的 message / item / content block / part 类型。
  • 明确各协议的 role、type、基础结构和跨协议映射边界。
  • 避免把 provider 的中间状态错误地压平成纯文本,尤其是 tool call、tool result、reasoning/thought、citation、multimodal content。

Canonical Model

MaaS 内部建议把“对话消息”和“协议输出 item”分开建模:

type MaasRole =
| 'system'
| 'developer'
| 'user'
| 'assistant'
| 'tool'
| 'function'
| 'model';

type MaasMessage = {
id?: string;
role: MaasRole;
type?: string; // provider item/message type,例如 message/function_call/thought
content?: MaasContentPart[] | string;
name?: string; // function/tool name, legacy function role name
status?: 'in_progress' | 'completed' | 'incomplete';
phase?: 'commentary' | 'final_answer';
toolCalls?: MaasToolCall[];
toolCallId?: string; // tool/function result references a call
provider?: 'openai' | 'anthropic' | 'google' | string;
providerRaw?: unknown;
};

type MaasContentPart =
| MaasTextPart
| MaasImagePart
| MaasAudioPart
| MaasFilePart
| MaasToolCallPart
| MaasToolResultPart
| MaasReasoningPart
| MaasRefusalPart
| MaasCitationPart
| MaasCodePart
| MaasUnknownPart;

Canonical Part Types

Canonical type说明OpenAIAnthropicGoogle
text普通文本输入/输出input_text, output_text, chat texttexttext
refusal拒答文本refusal通常是普通 text 或 stop/error 语义safety/block metadata 或文本
image图片输入/输出input_image, chat image_urlimageinline_data, file_data
audio音频输入/输出chat input_audio, realtime/audio output通常通过 file/document 或专用能力inline_data, live audio chunks
file / document文件、PDF、文档input_filedocumentfile_data, inline_data
tool_call模型请求调用工具function_call, chat tool_calls[]tool_use, server_tool_use, mcp_tool_usefunctionCall, Interactions function_call
tool_result工具调用结果function_call_output, chat role=tooltool_result, mcp_tool_resultfunctionResponse, Interactions function_result / function_response
reasoning / thought推理/思考状态reasoningthinking, redacted_thinkingthought / thought signatures
code代码执行请求或结果code interpreter itemscode execution server tool blocksexecutableCode, codeExecutionResult
citation / annotation引用、搜索结果、定位信息annotations on output_textcitations/search result blocksgrounding metadata / citations
unknown保留未知 provider 扩展原样保存原样保存原样保存

不变量

  • 不要把未知 type 丢弃;放入 providerRawunknown part。
  • 不要把多个不同 tool call 合并为一个 tool call;只能合并同一调用的 streaming delta。
  • 手动管理上下文时,应保留 provider 要求回传的中间 item:OpenAI reasoning、Google thought/signature/function_call、Anthropic thinking/redacted_thinking/tool_use 等。
  • Tool result 必须引用对应 tool call ID;字段名因协议不同而不同。

OpenAI Responses API

Input Shape

input 可以是字符串,也可以是 input item 列表。

{
"model": "gpt-5.4",
"input": [
{
"type": "message",
"role": "developer",
"content": [{ "type": "input_text", "text": "You are concise." }]
},
{
"type": "message",
"role": "user",
"content": [
{ "type": "input_text", "text": "Describe this image" },
{ "type": "input_image", "image_url": "data:image/png;base64,...", "detail": "auto" }
]
}
]
}

Input Message Roles

Role说明
developer开发者/应用指令;优先级高于 user
system系统指令;部分新模型更推荐 developer
user终端用户输入
assistant之前模型输出;手动管理上下文时可回放

OpenAI Responses 的 assistant message 还可能带 phase

phase说明
commentary中间评论/过程消息
final_answer最终回答

对 Codex/GPT-5.3+ 一类模型,后续请求回放 assistant messages 时应保留 phase

Input Content Types

Type基本字段说明
input_texttext文本输入
input_imageimage_urlfile_id, detail图片输入
input_filefile_id / file_url / file_data / filename, detail文件输入

Output Item Types

Responses API 的 output[] 不是单一 assistant message;它是 item 列表。

Type关键字段说明
messageid, role=assistant, content[], status, phaseassistant 文本/refusal 输出
function_callid, call_id, name, arguments, status模型请求调用函数;结果引用 call_id
function_call_outputid, call_id, output, status函数结果;通常作为下一轮 input item
reasoningid, summary[], content[], encrypted_content, statusreasoning 模型中间项;手动上下文管理时需要保留
compactionid, encrypted_contentresponses compact API 生成的压缩项
tool_search_callid, call_id, arguments, execution, statustool search 调用
tool_search_outputtools[]tool search 加载出的工具定义
computer_callid, call_id, action, statuscomputer use 动作调用
computer_call_outputcall_id, output fieldscomputer use 动作结果
file_search_callid, query/result fieldsfile search 工具调用
web_search_callid, action/status fieldsweb search 工具调用
image_generation_callid, result, status图像生成工具调用
code_interpreter_callid, code/container/output fieldscode interpreter 工具调用
mcp_call / mcp_list_toolsMCP fieldsremote MCP 工具相关 item
additional_toolstool definitions模型请求追加/加载工具定义的扩展项

Output Message Content Types

Type基本字段说明
output_texttext, annotations[], logprobs?assistant 文本输出
refusalrefusal拒答内容

output_text.annotations[] 常见类型包括:

Annotation type说明
file_citation文件引用
url_citationURL 引用
container_file_citationcontainer file 引用
file_path生成/引用的文件路径

Responses Streaming 聚合

Event family聚合键说明
response.output_item.addedoutput_index, item id创建 output item
response.output_text.deltaitem_id / output_index / content index合并文本 delta
response.function_call_arguments.deltaitem_id / output_index合并 function arguments 字符串
response.function_call_arguments.doneitem_id / output_index得到完整 function call

MaaS 规则:同一 output item 的 delta 合并为一个 item;不同 output_index 不合并。

OpenAI Chat Completions

Message Roles

Role说明content 类型
developer新模型优先使用的开发者指令;替代部分 system 用法string 或 text parts
system系统指令,旧模型/兼容接口常用string 或 text parts
user用户输入string 或 parts: text, image_url, input_audio
assistant模型输出string/parts、tool_calls[]refusal、audio 等
tooltool resulttext content + tool_call_id
functionlegacy function resultname + content;已被 tool 取代

Content Part Types

RolePart type基本字段说明
developer / systemtexttext指令文本
usertexttext用户文本
userimage_urlimage_url.url, detail?图片输入
userinput_audioinput_audio.data, format音频输入
assistanttexttextassistant 文本 part
assistantrefusalrefusal拒答 part
tooltexttext工具结果文本;Chat Completions tool message 只支持文本 part

Assistant Tool Calls

{
"role": "assistant",
"content": null,
"tool_calls": [
{
"id": "call_...",
"type": "function",
"function": {
"name": "get_weather",
"arguments": "{\"location\":\"Paris\"}"
}
}
]
}

Result:

{
"role": "tool",
"tool_call_id": "call_...",
"content": "{\"temperature\":25}"
}
  • finish_reason=tool_calls 表示模型调用了工具。
  • Streaming 时按 choices[].delta.tool_calls[].index 聚合同一 tool call;function.arguments 是字符串片段。
  • 多个 tool result 不应合成一个 role=tool message,因为每条 tool message 只有一个 tool_call_id

Anthropic Messages API

Message Roles

Role说明
user用户输入,也承载 client tool 的 tool_result blocks
assistantClaude 输出,包含文本、thinking、tool_use 等 blocks
system通常是 top-level system;新文档也支持 mid-conversation role=system,位置受限

Mid-conversation system message 约束:

  • 必须紧跟 user turn,或紧跟以 server tool use 结束的 assistant turn。
  • 不能插在 assistant tool_use 与对应 user tool_result 中间。
  • 不要放不可信内容;tool output / retrieved content 应放在 tool_result

Content Block Types

Block typeRole基本字段说明
textuser/assistant/systemtext文本
imageusersource图片输入;source 可为 base64/url/file
documentuser/tool_resultsource, title?, context?文档/PDF/文本文件
tool_useassistantid, name, inputclient-executed tool call
tool_resultusertool_use_id, content?, is_error?client tool result
server_tool_useassistantid, name, input/tool-specific fieldsserver-executed tool call
server tool result blockassistanttool-specific fields例如 web/code/search 结果;由 Anthropic server 产生
thinkingassistantthinking, signature?extended thinking block;继续对话时不能改
redacted_thinkingassistantencrypted/redacted fieldsredacted thinking;继续对话时不能改
mcp_tool_useassistantid, server_name, name, inputMCP connector 工具调用
mcp_tool_resultassistant/user-like MCP flowtool_use_id, content, is_error?MCP connector 工具结果
search_resultnested in contentsource/title/url/content可嵌在 tool result / search content 中

Tool Result Placement

Anthropic tool-use contract:

  1. assistant 返回 stop_reason=tool_use 和一个或多个 tool_use blocks。
  2. 下一条 message 必须是 role=user,并包含每个 tool_use.id 对应的 tool_result.tool_use_id
  3. tool_result blocks 必须在 user content[] 最前面;普通 text 只能放在所有 tool results 后面。
  4. 并行工具结果应放在一个 user message 的多个 tool_result blocks 中,不要拆成多轮 user messages。

示例:

[
{
"role": "assistant",
"content": [
{ "type": "tool_use", "id": "toolu_01", "name": "get_weather", "input": { "location": "SF" } },
{ "type": "tool_use", "id": "toolu_02", "name": "get_time", "input": { "timezone": "America/Los_Angeles" } }
]
},
{
"role": "user",
"content": [
{ "type": "tool_result", "tool_use_id": "toolu_01", "content": "SF: 20C" },
{ "type": "tool_result", "tool_use_id": "toolu_02", "content": "14:30" }
]
}
]

Google Gemini generateContent API

Content Shape

contents[] 是多轮内容数组:

{
"contents": [
{
"role": "user",
"parts": [{ "text": "What is in this image?" }]
},
{
"role": "model",
"parts": [{ "text": "A cat." }]
}
],
"system_instruction": {
"parts": [{ "text": "You are concise." }]
}
}

Roles

Role说明
user用户输入、function response 等客户端提供内容
model模型输出、function call、thought 等模型生成内容

system_instruction 是独立字段,不是普通 contents[].role=system

Part Types

Google Part 是 oneof 风格,常见字段如下:

Part field说明MaaS canonical
text文本text
inline_data / inlineDatainline bytes + MIME typeimage / audio / file
file_data / fileData文件 URI + MIME typefile / image / audio
function_call / functionCall模型请求调用函数tool_call
function_response / functionResponse函数结果tool_result
executable_code / executableCodecode execution 请求code
code_execution_result / codeExecutionResultcode execution 结果code / tool_result
thought fields / signaturethinking/tool context continuationreasoning / provider metadata

注意:如果模型使用 thinking 或 tools,Google 文档要求保留并原样回传模型生成的 steps/parts,例如 thoughtfunction_call 及其 signatures。

Google Interactions API

新版 Interactions API 把一次交互拆成 input/steps。

Input / Step Types

Type方向基本字段说明
user_inputclient -> modelcontent string 或 content blocks用户输入 step
thoughtmodel -> client/historycontent?, signature?模型思考;Gemini 3+ stateless 回放要保留 signature
function_callmodel -> clientid, name, arguments, signature?custom function call;id 用于结果关联
function_resultclient -> modelname, call_id, result[]function call 执行结果;examples 使用此名
function_responseclient/model contextid/call_id, result, signature?tool-combination 文档也称 result step 为 function_response
built-in tool stepsmodel/servertool-specific args/results, signature?google_search/maps/url_context/file_search 等 built-in tool 上下文
model text/content stepmodel -> clientcontent[] / text fields最终或中间模型输出

Stateful vs Stateless

Mode规则
Stateful使用 previous_interaction_id,server 自动处理 idsignature
Stateless客户端自己维护 history;必须把模型生成 steps 原样放回下一轮 input,包括 thoughtfunction_call、built-in tool steps、signature

Function result 示例:

{
"type": "function_result",
"name": "set_light_values",
"call_id": "fc_...",
"result": [{ "type": "text", "text": "{\"brightness\":25}" }]
}

Tool Choice

Value说明
auto默认;模型自行决定是否调用工具
any必须调用函数
none禁止函数调用
validatedPreview;保证 schema adherence;tool context circulation 默认用 validated
allowed_tools限制可调用工具集合

Google Live API

Live API 是双向流,message/event 类型与 generateContent 不同。

DirectionMessage family说明
client -> serversetup建立模型、工具、音频等配置
client -> serverclientContent发送 turns;turns 是 {role, parts},可带 turnComplete
client -> serverrealtimeInput实时音频/视频/activity 输入
client -> servertoolResponse客户端工具结果
server -> clientserverContent模型内容、转录、turnComplete、interrupted 等
server -> clienttoolCall模型请求客户端执行工具
server -> clienttoolCallCancellation工具调用取消
server -> clientsetupComplete / errors会话状态

MaaS 如果只做非实时 Chat/Responses 兼容,可以先不把 Live event 压成普通 message;保留为 stream event 更安全。

Cross-Protocol Mapping

Roles

CanonicalOpenAI ResponsesOpenAI ChatAnthropicGoogle generateContentGoogle Interactions
systemsystemsystemtop-level system 或 mid-conversation role=systemsystem_instructionrequest-level config
developerdeveloperdeveloper无直接等价,通常映射到 system无直接等价request-level instruction/config
useruseruseruseruseruser_input
assistantassistant output messageassistantassistantmodelmodel output/content steps
toolfunction_call_output itemrole=tooluser message with tool_result blocksfunctionResponse partfunction_result step
functionlegacy onlyrole=function legacy

Text / Multimodal

CanonicalOpenAI ResponsesOpenAI ChatAnthropicGoogle
text inputinput_texttext part/stringtext block/stringtext part / user_input.content
text outputoutput_textassistant content/text deltatext blocktext part / model content step
image inputinput_imageimage_urlimageinline_data / file_data
audio inputaudio-specific input or chat input_audioinput_audiofile/document style unless model-specificinline_data / Live realtime input
file/documentinput_filelimited by model/APIdocumentfile_data / inline_data

Tool Calls

CanonicalOpenAI ResponsesOpenAI ChatAnthropicGoogle
call IDfunction_call.call_idtool_calls[].idtool_use.idfunctionCall.id or Interactions function_call.id
provider item IDfunction_call.idsame as call ID or message idsame as call ID/block idstep/part id
call namenamefunction.namenamename
argumentsJSON string argumentsJSON string function.argumentsobject inputobject args / arguments
result referencefunction_call_output.call_idtool_call_idtool_result.tool_use_idfunctionResponse.name/id or Interactions call_id
parallel result packagingmultiple output itemsmultiple role=tool messagesone user message, multiple tool_result blocksmultiple parts/steps

MaaS Implementation Notes

Parse Rules

  • OpenAI Responses:
    • Treat top-level output[] item type as message/item type.
    • For message.content[], treat nested type as content part type.
    • function_call.call_id is the canonical tool call ID; keep id as provider item ID.
  • OpenAI Chat:
    • Treat messages[].role as message role.
    • Treat content[] part type as content part type.
    • Treat assistant.tool_calls[] as tool call parts even though they are not in content.
  • Anthropic:
    • Treat messages[].content[] blocks as first-class parts.
    • Preserve thinking / redacted_thinking unchanged when replaying.
    • Validate tool_result placement before sending.
  • Google:
    • For generateContent, parse contents[].parts[] oneof fields into parts.
    • For Interactions, parse each input[] / steps[] element by type.
    • Preserve signature and model-generated steps in stateless mode.

Serialization Rules

  • Do not serialize tool results as plain user text unless the target protocol has no tool-result primitive.
  • When converting OpenAI Chat -> Anthropic, merge consecutive role=tool messages that answer the same assistant tool_calls[] into one Anthropic user.content[] with multiple tool_result blocks.
  • When converting Anthropic -> OpenAI Chat, split one Anthropic user message containing multiple tool_result blocks into multiple role=tool messages.
  • When converting Responses -> Chat, map function_call.call_id to Chat tool_calls[].id; map function_call_output.call_id to tool_call_id.
  • When converting Google Interactions stateless history, never drop thought or signature fields even if MaaS does not expose them to callers.

Unknown / Future Types

Provider schemas change frequently. MaaS should:

  • keep providerRaw for every unrecognized item/block/part;
  • log unknown type counters by provider/model;
  • fail closed only when the unknown type affects required continuation semantics, e.g. a tool call/result or signed thought step;
  • otherwise pass through or expose as unknown part.

References

  • skills/openai-sdk-python/references/responses/input_tokens/count.md
  • skills/openai-sdk-python/references/chat.md
  • skills/openai-docs/references/guides/function-calling.md
  • skills/anthropic-docs/references/build-with-claude/working-with-messages.md
  • skills/anthropic-docs/references/build-with-claude/mid-conversation-system-messages.md
  • skills/anthropic-docs/references/agents-and-tools/tool-use/handle-tool-calls.md
  • skills/anthropic-docs/references/agents-and-tools/tool-use/troubleshooting-tool-use.md
  • skills/google-ai-docs/references/text-generation.md
  • skills/google-ai-docs/references/function-calling.md
  • skills/google-ai-docs/references/tool-combination.md
  • skills/google-ai-docs/references/live-guide.md