Files
cursor-byok/docs/协议消息参考.md
T
2026-08-13 22:01:11 +08:00

655 lines
31 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Agent Bidi / RunSSE 协议消息参考
本文描述 Agent Bidi / RunSSE 链路中的消息功能、字段语义和消息之间的关联关系。
本文是协议参考,不描述服务端或客户端的内部实现。字段定义以当前 `internal/backend/cursor/proto/agent_v1.proto``internal/backend/cursor/proto/aiserver_v1.proto` 为准。
范围包括 BidiAppend / RunSSE 传输封装、`AgentClientMessage` 的全部顶层分支、`AgentServerMessage` 的全部顶层分支,以及这些分支直接关联的主要请求、响应和控制消息。工具专属的 Args / Result 类型按功能归类,不展开为具体执行流程。
## 1. 协议概览
该协议将一次 Agent 通信拆成两条方向相反的通道:
- `BidiAppend`:客户端向服务端追加消息。
- `RunSSE`:服务端持续向客户端返回消息。
两条通道通过同一个 `request_id` 关联。
```text
客户端 服务端
| |
| BidiAppend(request_id, append_seqno, data)|
|------------------------------------------>|
| |
| RunSSE(request_id) |
|------------------------------------------>|
| |
| stream AgentServerMessage |
|<------------------------------------------|
```
### 1.1 主要关联标识
| 标识 | 范围 | 功能 |
| --- | --- | --- |
| `conversation_id` | 会话 | 标识一个可持续多轮的 Agent 会话。 |
| `request_id` | 请求流 | 关联 BidiAppend、RunSSE 和一次活跃请求。 |
| `run_id` | 运行 | 独立标识一次 Agent Run;不得假定它与 `request_id` 等值。 |
| `message_id` | 用户消息 | 标识一条用户输入。 |
| `model_call_id` | 模型调用 | 标识一次具体的模型调用或 provider pass。 |
| `call_id` / `tool_call_id` | 工具调用 | 标识模型发起的一次工具调用。 |
| `id` | 桥接消息 | 关联 Exec、Interaction 或 KV 的请求和响应。 |
| `exec_id` | 客户端执行 | 标识一次客户端执行任务,可跨多个流式消息。 |
| `append_seqno` | Bidi 请求流 | 表示同一 `request_id` 下客户端上行消息的顺序。 |
### 1.2 Connect 流式帧封装
RunSSE 中的每条消息都位于 Connect 流式帧中。帧由固定 5 字节帧头和消息载荷组成:
| 部分 | 长度 | 功能 |
| --- | --- | --- |
| `flags` | 1 字节 | 描述压缩和流结束状态。 |
| `length` | 4 字节 | 使用大端序表示后续载荷的字节数,不包含 5 字节帧头。 |
| `payload` | `length` 字节 | 普通帧中是 protobuf 消息;流结束帧中是结束状态。 |
`flags` 属于 Connect 传输层,不是 `AgentServerMessage` 或其他 protobuf 消息的字段。当前使用的标志位为:
| 标志 | 含义 |
| --- | --- |
| `0x00` | 普通、未压缩的数据帧。 |
| `0x01` | 压缩的数据帧,载荷需要按照流声明的压缩算法解压后再解析。 |
| `0x02` | 流结束帧,载荷表示 EndStream 状态,不应按业务 protobuf 消息解析。 |
这些值按 bit 表达:最低位 `0x01` 表示压缩,次低位 `0x02` 表示流结束,其余 bit 为保留位。因此,判断帧类型时应读取标志位,而不是把 `flags` 当作 protobuf 枚举。
例如下面的 RunSSE 帧:
```json
{
"kind": "interaction_update",
"messageType": "agent.v1.AgentServerMessage",
"flags": "0x00",
"length": 4,
"compressed": false,
"endStream": false,
"message": {
"interaction_update": {
"heartbeat": {}
}
}
}
```
它表示载荷是一个长度为 4 字节、未压缩且尚未结束流的 `AgentServerMessage``heartbeat` 消息很小,使用 `0x00` 是正常情况;较大的业务消息可能使用 `0x01`
## 2. BidiAppend 传输消息
### 2.1 `BidiAppendRequest`
功能:向指定请求流追加一条客户端消息。
| 字段 | 类型 | 功能 |
| --- | --- | --- |
| `data` | `string` | 十六进制编码的 `AgentClientMessage` protobuf 数据。 |
| `request_id` | `BidiRequestId` | 指定消息所属的请求流。 |
| `append_seqno` | `int64` | 指定消息在当前请求流中的追加顺序。 |
| `data_binary` | `bytes` | 二进制形式的消息载荷。 |
约束:
- `data``data_binary` 表达的是消息载荷,不应同时承载语义不同的消息。
- `append_seqno` 只在同一个 `request_id` 内比较。
- 解码后的根消息必须是 `AgentClientMessage`
### 2.2 `BidiAppendResponse`
功能:确认本次 append 请求已经被接收。
该消息没有业务字段。它只确认 unary 请求本身,不代表 Agent Run 已经完成。
### 2.3 `BidiRequestId`
| 字段 | 类型 | 功能 |
| --- | --- | --- |
| `request_id` | `string` | 标识 BidiAppend 与 RunSSE 共享的请求流。 |
## 3. 客户端上行根消息
### 3.1 `AgentClientMessage`
功能:封装一条客户端到服务端的 Agent 消息。
`message``oneof`,一条消息只能选择以下一个分支:
| 分支 | 消息类型 | 功能 |
| --- | --- | --- |
| `run_request` | `AgentRunRequest` | 启动或恢复一次 Agent Run。 |
| `exec_client_message` | `ExecClientMessage` | 返回客户端工具执行的数据或结果。 |
| `kv_client_message` | `KvClientMessage` | 返回 blob 读取或写入结果。 |
| `conversation_action` | `ConversationAction` | 追加会话动作,例如继续、取消或执行计划。 |
| `exec_client_control_message` | `ExecClientControlMessage` | 返回客户端执行通道的控制事件。 |
| `interaction_response` | `InteractionResponse` | 回答服务端发起的用户交互请求。 |
| `client_heartbeat` | `ClientHeartbeat` | 表示客户端连接仍然活跃。 |
| `prewarm_request` | `PrewarmRequest` | 提前准备会话、模型和上下文。 |
## 4. `AgentRunRequest`
功能:携带启动或恢复 Agent Run 所需的会话状态、动作、模型与能力信息。
### 4.1 核心字段
| 字段 | 类型 | 功能 |
| --- | --- | --- |
| `conversation_state` | `ConversationStateStructure` | 客户端掌握的会话 checkpoint。 |
| `action` | `ConversationAction` | 本次 Run 要执行的会话动作。 |
| `model_details` | `ModelDetails` | 旧式或展示用途的模型信息。 |
| `requested_model` | `RequestedModel` | 本次实际请求的模型、参数和凭据。 |
| `conversation_id` | `string?` | 本次 Run 所属会话。 |
| `run_id` | `string?` | 客户端分配的 Run 标识。 |
### 4.2 工具和上下文字段
| 字段 | 类型 | 功能 |
| --- | --- | --- |
| `mcp_tools` | `McpTools` | 本次 Run 可用的 MCP 工具定义。 |
| `mcp_file_system_options` | `McpFileSystemOptions?` | MCP 文件系统能力和描述符。 |
| `skill_options` | `SkillOptions?` | 可用技能及技能加载选项。 |
| `custom_system_prompt` | `string?` | 调用方提供的自定义系统提示。 |
| `exclude_workspace_context` | `bool?` | 是否排除工作区上下文。 |
| `pre_fetched_blobs` | `PreFetchedBlob[]` | 调用前已经取得的 blob 内容。 |
### 4.3 模式和子 Agent 字段
| 字段 | 类型 | 功能 |
| --- | --- | --- |
| `subagent_type_name` | `string?` | 当前 Run 使用的子 Agent 类型。 |
| `selected_subagent_models` | `RequestedModel[]` | 为子 Agent 选择的模型。 |
| `selected_subagent_model_details` | `ModelDetails[]` | 子 Agent 模型的展示信息。 |
| `subagent_model_overrides` | `SubagentModelOverride[]` | 按子 Agent 类型覆盖模型选择。 |
| `can_create_cloud_subagents` | `bool?` | 客户端是否允许创建云端子 Agent。 |
| `suppress_subagent_progress_update_tool` | `bool?` | 是否隐藏子 Agent 进度更新工具。 |
| `conversation_group_id` | `string?` | 将多个相关会话归入同一组。 |
### 4.4 客户端能力字段
| 字段 | 类型 | 功能 |
| --- | --- | --- |
| `suggest_next_prompt` | `bool?` | 是否请求生成下一条提示建议。 |
| `harness` | `string?` | 标识调用方所使用的 Agent harness。 |
| `dev_raw_model_slug` | `string?` | 开发模式下使用的原始模型标识。 |
| `client_supports_inline_images` | `bool?` | 客户端是否支持内联图片。 |
| `client_supports_send_to_user` | `bool?` | 客户端是否支持 send-to-user 能力。 |
| `computer_use_coordinate_mode` | `string?` | Computer Use 坐标系模式。 |
## 5. `PrewarmRequest`
功能:提前提供模型、会话状态和能力声明,使后续正式 Run 可以复用已经准备好的上下文。
其主要字段与 `AgentRunRequest` 相同,但没有直接携带 `ConversationAction`
| 字段组 | 字段 |
| --- | --- |
| 模型 | `model_details``requested_model` |
| 会话 | `conversation_id``conversation_state``conversation_group_id` |
| 工具 | `mcp_tools``mcp_file_system_options` |
| Prompt | `custom_system_prompt``exclude_workspace_context` |
| 子 Agent | `subagent_type_name``selected_subagent_models``selected_subagent_model_details``subagent_model_overrides` |
| 客户端能力 | `suggest_next_prompt``client_supports_inline_images``client_supports_send_to_user``computer_use_coordinate_mode` |
| 预取 | `pre_fetched_blobs` |
| 候选选择 | `best_of_n_group_id``try_use_best_of_n_promotion` |
## 6. 模型选择消息
### 6.1 `RequestedModel`
功能:描述调用方实际希望使用的模型和运行参数。
| 字段 | 类型 | 功能 |
| --- | --- | --- |
| `model_id` | `string` | Provider 模型标识。 |
| `max_mode` | `bool` | 是否启用该模型的 max 模式。 |
| `parameters` | `ModelParameterValue[]` | 额外模型参数,每项包含字符串 `id``value`。 |
| `built_in_model` | `bool` | 是否为内建模型。 |
| `is_variant_string_representation` | `bool` | `model_id` 是否表示模型变体字符串。 |
| `credentials` | `oneof` | `api_key_credentials``azure_credentials``bedrock_credentials`。 |
### 6.2 `ModelDetails`
功能:提供模型展示信息、别名、思考能力和凭据。
| 字段 | 类型 | 功能 |
| --- | --- | --- |
| `model_id` | `string` | 模型标识。 |
| `display_model_id` | `string` | 面向 UI 的模型标识。 |
| `display_name` | `string` | 完整展示名称。 |
| `display_name_short` | `string` | 短展示名称。 |
| `aliases` | `string[]` | 可识别的模型别名。 |
| `thinking_details` | `ThinkingDetails?` | 模型思考能力声明。 |
| `max_mode` | `bool?` | 是否启用 max 模式。 |
| `credentials` | `oneof` | API Key、Azure 或 Bedrock 凭据。 |
凭据字段属于敏感信息,不应写入普通日志、错误消息或会话记录。
## 7. `ConversationAction`
功能:描述一次会话级动作。`action``oneof`
### 7.1 公共字段
| 字段 | 类型 | 功能 |
| --- | --- | --- |
| `triggering_auth_id` | `string?` | 触发动作的认证主体。 |
| `triggering_user_info` | `TriggeringUserInfo?` | 触发用户的信息。 |
| `request_context_parts` | `RequestContextPartReferences?` | 通过 blob 引用传递的大型上下文部分。 |
### 7.2 动作分支
| 分支 | 主要参数 | 功能 |
| --- | --- | --- |
| `user_message_action` | `user_message``request_context``prepend_user_messages``conversation_history` | 提交新用户消息并开始或继续会话。 |
| `resume_action` | `request_context` | 从已有 checkpoint 或等待点继续会话。 |
| `cancel_action` | `reason``interrupted_pending_tool_call_resolutions` | 取消当前 Run,并可携带未完成工具的解决结果。 |
| `summarize_action` | 无字段 | 请求生成或刷新会话摘要。 |
| `shell_command_action` | `shell_command``exec_id` | 将一次显式 Shell 命令写入会话。 |
| `start_plan_action` | `user_message``request_context``is_spec` | 进入计划编制流程。 |
| `execute_plan_action` | `request_context``plan`、计划文件字段、`execution_mode``plan_id` | 执行已有计划。 |
| `async_ask_question_completion_action` | `original_tool_call_id``original_args``result` | 回填异步 AskQuestion 的结果。 |
| `cancel_subagent_action` | `subagent_id` | 取消指定子 Agent。 |
| `background_task_completion_action` | `completions[]` | 上报后台 Shell 或子 Agent 的进度和终态。 |
| `background_shell_action` | `tool_call_id` | 将指定 Shell 工具调用切换到后台语义。 |
| `background_subagent_action` | `tool_call_id` | 将指定子 Agent 工具调用切换到后台语义。 |
| `subscription_notification_action` | `notifications[]``request_context` | 将订阅系统产生的消息注入会话。 |
| `goal_continuation_action` | 无字段 | 继续当前长期目标。 |
| `inject_context_action` | `injection_id``expected_run_id``user_context/system_context` | 向仍在运行的 Run 注入上下文。 |
## 8. `UserMessage`
功能:描述用户输入及其选择的上下文和运行模式。
| 字段组 | 字段 | 功能 |
| --- | --- | --- |
| 内容 | `text``rich_text``text_blob_id``rich_text_blob_id` | 用户输入的纯文本、富文本或 blob 引用。 |
| 身份 | `message_id``thread_id``prompt_reference_id` | 消息、线程和提示引用标识。 |
| 上下文 | `selected_context``conversation_state_blob_id` | 用户选择的文件、代码或会话状态。 |
| 模式 | `mode``custom_mode_intent` | Agent、Ask、Plan、Debug、Multitask 或自定义模式。 |
| 计划 | `execute_plan_info` | 当前消息关联的计划。 |
| 子 Agent | `subagent_system_reminder``project_details` | 子 Agent 或项目相关信息。 |
| 模拟消息 | `is_simulated_msg``simulated_msg_reason``simulated_message_metadata` | 标记系统代用户生成的输入。 |
| Hook | `hook_additional_contexts` | Hook 产生的附加上下文。 |
## 9. `RequestContext`
功能:描述本次请求可见的工作区、规则、工具和运行环境。
字段较多,按语义分组如下:
| 字段组 | 代表字段 | 功能 |
| --- | --- | --- |
| 环境 | `env` | OS、Shell、工作区路径、时区、终端目录、sandbox 与 Computer Use 能力。 |
| 规则 | `rules``non_file_rules``cloud_rule``disabled_team_rules` | 本次请求适用的规则集合。 |
| 仓库 | `repository_info``git_repos``project_layouts`、完整性标记 | 仓库索引、Git 和项目布局。 |
| MCP | `tools``mcp_instructions``mcp_file_system_options``mcp_meta_tool_options` | MCP 工具与文件系统能力。 |
| 技能 | `skill_options``agent_skills` | 可用技能和技能内容。 |
| 子 Agent | `custom_subagents` | 自定义子 Agent 声明。 |
| 文件 | `file_contents` | 已预取的路径到文件内容映射。 |
| Web | `web_search_enabled``web_fetch_enabled` | Web Search 和 Web Fetch 能力开关。 |
| Hook | `hooks_additional_context``hooks_config` | Hook 配置和附加上下文。 |
| 权限 | `user_permissions_auto_run``project_permissions_auto_run``admin_permissions_auto_run``admin_command_denylist` | 自动执行许可和禁止命令。 |
| 功能能力 | `supports_mcp_auth``read_lints_enabled``search_conversations_enabled``send_message_enabled` | 客户端可提供的附加能力。 |
大型上下文也可以通过 `RequestContextPartReferences` 传递。该结构为 rules、skills、subagents 和 MCP 分别携带 `blob_id` 与字节长度,并用 `dynamic_context` 继续携带小型动态字段。
## 10. `ExecClientMessage`
功能:返回 `ExecServerMessage` 所请求的客户端执行数据或结果。
### 10.1 公共字段
| 字段 | 类型 | 功能 |
| --- | --- | --- |
| `id` | `uint32` | 与对应 `ExecServerMessage.id` 相同。 |
| `exec_id` | `string` | 与对应 `ExecServerMessage.exec_id` 相同。 |
| `local_execution_time_ms` | `int32?` | 客户端本地执行耗时。 |
| `hook_additional_contexts` | `HookAdditionalContext[]` | 执行 Hook 返回的附加上下文。 |
| `message` | `oneof` | 工具特定的结果或流式事件。 |
### 10.2 主要结果分支
| 分类 | 分支 | 功能 |
| --- | --- | --- |
| 文件 | `read_result``redacted_read_result` | 返回文件读取结果。 |
| 文件 | `write_result``delete_result` | 返回文件写入或删除结果。 |
| 搜索 | `grep_result``ls_result` | 返回文本搜索、Glob 或目录列表结果。 |
| 诊断 | `diagnostics_result``canvas_diagnostics_result` | 返回代码或 Canvas 诊断结果。 |
| Shell | `shell_result``shell_stream` | 返回一次性 Shell 结果或流式 Shell 事件。 |
| Shell | `background_shell_spawn_result``write_shell_stdin_result``force_background_shell_result` | 返回后台 Shell 创建、输入和后台切换结果。 |
| 上下文 | `request_context_result` | 返回动态构建的 RequestContext。 |
| MCP | `mcp_result``list_mcp_resources_exec_result``read_mcp_resource_exec_result``mcp_state_exec_result` | 返回 MCP 调用和资源操作结果。 |
| Hook | `execute_hook_result` | 返回 Hook 执行结果。 |
| 子 Agent | `subagent_result``force_background_subagent_result``subagent_await_result` | 返回子 Agent 运行、后台切换和等待结果。 |
| Web/Computer | `fetch_result``record_screen_result``computer_use_result` | 返回网页、录屏或 Computer Use 结果。 |
| 权限预检 | `shell_allowlist_precheck_result``mcp_allowlist_precheck_result``web_fetch_allowlist_precheck_result` | 返回 allowlist 检查结果。 |
| Git | `git_diff_response` | 返回 Git diff。 |
| Pi 工具 | `pi_read_result``pi_bash_result``pi_edit_result``pi_write_result``pi_grep_result``pi_find_result``pi_ls_result` | 返回 Pi 工具族的执行结果。 |
| 其他 | `smart_mode_classifier_result``conversation_search_result``agent_store_conflict_result` | 返回模式分类、会话搜索或 Agent Store 冲突处理结果。 |
对于 `shell_stream`,其内部 `event` 也是 `oneof`,常见事件包括:
- `start`:进程已经启动。
- `stdout`:标准输出增量。
- `stderr`:标准错误增量。
- `exit`:进程已经退出。
- `rejected`:执行请求被拒绝。
- `permission_denied`:缺少执行权限。
- `backgrounded`:进程已经转入后台。
## 11. `ExecClientControlMessage`
功能:描述客户端执行通道本身的状态,不承载正常工具结果。
`message``oneof`
| 分支 | 参数 | 功能 |
| --- | --- | --- |
| `stream_close` | `id` | 表示指定 Exec 数据流已经关闭。 |
| `throw` | `id``error``stack_trace?``error_code?` | 表示客户端执行通道异常终止。 |
| `heartbeat` | `id` | 表示指定 Exec 仍然存活。 |
## 12. `InteractionResponse`
功能:返回客户端或用户对 `InteractionQuery` 的响应。
| 字段 | 类型 | 功能 |
| --- | --- | --- |
| `id` | `uint32` | 与对应 `InteractionQuery.id` 相同。 |
| `result` | `oneof` | 交互类型对应的响应。 |
当前主要响应分支:
| 分支 | 主要内容 | 功能 |
| --- | --- | --- |
| `ask_question_interaction_response` | `AskQuestionResult` | 返回问题答案、拒绝、错误或异步状态。 |
| `create_plan_request_response` | `CreatePlanResult` | 返回计划 URI以及成功或错误。 |
| `web_search_request_response` | `approved/rejected` | 批准或拒绝 Web Search。 |
| `web_fetch_request_response` | `approved/rejected` | 批准或拒绝 Web Fetch。 |
| `switch_mode_request_response` | `approved/rejected` | 批准或拒绝模式切换。 |
协议还定义 VM 环境、PR 管理、MCP Auth、图片生成、环境替换和 SCM 连接等响应分支。
## 13. `KvClientMessage`
功能:返回 `KvServerMessage` 发起的 blob 操作结果。
| 字段 | 类型 | 功能 |
| --- | --- | --- |
| `id` | `uint32` | 与对应 `KvServerMessage.id` 相同。 |
| `get_blob_result` | `GetBlobResult` | 返回 `blob_data``error`。 |
| `set_blob_result` | `SetBlobResult` | 返回可选的写入错误;无错误表示写入成功。 |
## 14. `ClientHeartbeat`
功能:表示客户端 Agent 通道仍然存活。
该消息没有业务字段,也不与 `ExecClientHeartbeat` 混用:
- `ClientHeartbeat` 面向整个 Agent 请求通道。
- `ExecClientHeartbeat` 面向某个具体 `ExecServerMessage.id`
## 15. RunSSE 请求与服务端根消息
### 15.1 RunSSE 请求
RunSSE 请求体是 `BidiRequestId`,只包含:
| 字段 | 类型 | 功能 |
| --- | --- | --- |
| `request_id` | `string` | 订阅指定请求流的服务端消息。 |
### 15.2 `AgentServerMessage`
功能:封装一条服务端到客户端的 Agent 消息。
| 字段 | 类型 | 功能 |
| --- | --- | --- |
| `ttft_breakdown` | `TtftBreakdown` | 可选的首 token 延迟分解。 |
| `message` | `oneof` | 本条消息的业务载荷。 |
`message` 可以选择以下一个分支:
| 分支 | 消息类型 | 功能 |
| --- | --- | --- |
| `interaction_update` | `InteractionUpdate` | 返回文本、思考、工具和 turn 生命周期更新。 |
| `exec_server_message` | `ExecServerMessage` | 请求客户端执行本地工具。 |
| `exec_server_control_message` | `ExecServerControlMessage` | 控制已经发出的客户端执行。 |
| `conversation_checkpoint_update` | `ConversationStateStructure` | 更新客户端持有的会话 checkpoint。 |
| `kv_server_message` | `KvServerMessage` | 请求客户端读取或写入 blob。 |
| `interaction_query` | `InteractionQuery` | 请求用户或客户端作出交互决策。 |
## 16. `InteractionUpdate`
功能:承载模型输出和一次 turn 中的增量状态。
`message``oneof`。当前主要消息如下。
### 16.1 文本和思考
| 分支 | 参数 | 功能 |
| --- | --- | --- |
| `text_delta` | `text``is_server_notice` | 返回可展示文本增量。 |
| `thinking_delta` | `text``thinking_style?` | 返回思考文本增量及展示样式。 |
| `thinking_completed` | `thinking_duration_ms` | 表示思考阶段结束。 |
### 16.2 工具调用
| 分支 | 参数 | 功能 |
| --- | --- | --- |
| `tool_call_started` | `call_id``tool_call``model_call_id` | 宣布工具调用已经建立。 |
| `partial_tool_call` | `call_id``tool_call``args_text_delta``model_call_id` | 在参数尚未完整时返回部分 ToolCall。 |
| `tool_call_delta` | `call_id``tool_call_delta``model_call_id` | 返回 Shell、Task、Edit 或环境替换的增量。 |
| `tool_call_completed` | `call_id``tool_call``model_call_id` | 表示工具调用已经得到终态结果。 |
| `shell_output_delta` | `stdout/stderr/start/exit` | 返回 Shell 进程输出和生命周期增量。 |
同一次工具调用的这些消息必须使用相同的 `call_id`;同一次模型调用产生的工具事件应使用相同的 `model_call_id`
### 16.3 摘要和结束
| 分支 | 参数 | 功能 |
| --- | --- | --- |
| `summary_started` | 无字段 | 表示摘要阶段开始。 |
| `summary` | `summary` | 返回摘要文本。 |
| `summary_completed` | `hook_message?` | 表示摘要阶段完成,并可携带后续 Hook 信息。 |
| `turn_ended` | token 统计字段 | 表示当前 turn 正常结束。 |
`turn_ended` 的 token 字段包括:
- `input_tokens`
- `output_tokens`
- `cache_read_tokens`
- `cache_write_tokens`
- `reasoning_tokens`
### 16.4 保活
| 分支 | 参数 | 功能 |
| --- | --- | --- |
| `heartbeat` | 无字段 | 保持 RunSSE 活跃,不表示业务状态变化。 |
协议还定义 `user_message_appended``token_delta`、step 生命周期、prompt suggestion、branch change、feedback、response comparison 和 context injection state 等更新。
## 17. `ExecServerMessage`
功能:要求客户端执行一项本地能力。
### 17.1 公共字段
| 字段 | 类型 | 功能 |
| --- | --- | --- |
| `id` | `uint32` | 执行桥消息编号,客户端回包必须原样携带。 |
| `exec_id` | `string` | 执行任务标识,流式消息应保持一致。 |
| `span_context` | `SpanContext?` | 可选的分布式追踪上下文。 |
| `accept_hook_additional_contexts` | `bool?` | 是否接受客户端在结果中返回 Hook 附加上下文。 |
| `message` | `oneof` | 工具特定的执行参数。 |
### 17.2 主要执行分支
| 分类 | 分支 | 功能 |
| --- | --- | --- |
| 文件 | `read_args``write_args``delete_args` | 读取、写入或删除文件。 |
| 搜索 | `grep_args``ls_args` | 搜索文本、匹配路径或列出目录。 |
| 诊断 | `diagnostics_args` | 获取编辑器或项目诊断。 |
| Shell | `shell_stream_args` | 启动流式 Shell 命令。 |
| Shell | `write_shell_stdin_args``force_background_shell_args` | 向 Shell 写入输入或切换后台执行。 |
| MCP | `mcp_args``list_mcp_resources_exec_args``read_mcp_resource_exec_args` | 调用 MCP 工具或读取 MCP 资源。 |
| Hook | `execute_hook_args` | 请求客户端执行 Agent Hook。 |
| 子 Agent | `subagent_args` | 请求客户端启动子 Agent。 |
协议还定义普通 Shell、后台 Shell 创建、RequestContext、Fetch、Computer Use、allowlist 预检、Git diff、Pi 工具、会话搜索和 Agent Store 冲突等执行分支。
### 17.3 回包规则
客户端返回 `ExecClientMessage``ExecClientControlMessage` 时:
- `id` 必须与请求一致。
- 如果存在 `exec_id`,应与请求一致。
- 流式执行可以返回多条数据消息。
- 最终结果、`throw` 或明确终态用于结束本次执行关联。
## 18. `ExecServerControlMessage`
功能:控制此前已经发出的 Exec 请求。
当前协议分支:
| 分支 | 参数 | 功能 |
| --- | --- | --- |
| `abort` | `id` | 请求客户端终止对应的 Exec。 |
`abort.id` 对应 `ExecServerMessage.id`,不是 `tool_call_id`
## 19. `InteractionQuery`
功能:请求用户或客户端完成不能由模型单独决定的交互。
### 19.1 公共字段
| 字段 | 类型 | 功能 |
| --- | --- | --- |
| `id` | `uint32` | 交互编号,响应必须原样携带。 |
| `query` | `oneof` | 具体交互内容。 |
### 19.2 主要查询分支
| 分支 | 主要参数 | 功能 |
| --- | --- | --- |
| `ask_question_interaction_query` | `args``tool_call_id` | 向用户展示一个或多个问题。 |
| `create_plan_request_query` | `args``tool_call_id` | 请求客户端创建或保存计划。 |
| `web_search_request_query` | `args` | 请求批准 Web Search。 |
| `web_fetch_request_query` | `args``skip_approval``smart_mode_approval` | 请求批准或执行 Web Fetch。 |
| `switch_mode_request_query` | `args.target_mode_id``explanation?``tool_call_id` | 请求切换 Agent 模式。 |
协议还定义 VM 环境、PR 管理、MCP Auth、图片生成、环境替换和 SCM 连接查询。
### 19.3 响应规则
客户端必须用 `InteractionResponse` 返回结果:
- `InteractionResponse.id` 与查询 `id` 相同。
- `result` 分支必须与原查询类型匹配。
- 批准/拒绝型响应应明确选择对应的 `oneof` 分支,不能用空消息代替拒绝。
## 20. `KvServerMessage`
功能:请求客户端提供或保存较大的二进制数据。
| 字段 | 类型 | 功能 |
| --- | --- | --- |
| `id` | `uint32` | KV 操作编号。 |
| `span_context` | `SpanContext?` | 可选追踪上下文。 |
| `get_blob_args` | `GetBlobArgs` | 按 `blob_id` 读取数据。 |
| `set_blob_args` | `SetBlobArgs` | 按 `blob_id` 保存 `blob_data`。 |
客户端使用相同 `id` 返回 `KvClientMessage`
Blob 字段是原始 bytes。协议使用 `blob_id` 引用它们,以避免在主要会话消息中重复传输大型上下文。
## 21. `ConversationStateStructure`
功能:表示可跨请求传递的会话 checkpoint。
该结构既可以由客户端随 `AgentRunRequest` 上传,也可以由服务端通过 `conversation_checkpoint_update` 返回。
| 字段组 | 代表字段 | 功能 |
| --- | --- | --- |
| Prompt | `root_prompt_messages_json` | 根 Prompt 消息,元素以 bytes 保存。 |
| Turn | `turns``turn_timings` | 历史 turn 和耗时。 |
| 工具 | `pending_tool_calls` | 尚未解决的工具调用。 |
| 状态 | `todos``plan``plans` | Todo 和计划状态。 |
| Token | `token_details` | 已用 token、最大 token 和上下文分解。 |
| 摘要 | `summary``summary_archive``summary_archives``self_summary_count` | 当前摘要和历史摘要。 |
| 文件 | `file_states``file_states_v2``read_paths` | 会话涉及的文件状态。 |
| 工作区 | `previous_workspace_uris``tracked_git_repo_branches``active_branch_name` | 工作区和 Git 状态。 |
| 模式 | `mode``agent_type` | 当前 Agent 模式和类型。 |
| 子 Agent | `subagent_states``subagent_threads``subagent_runs_by_parent_tool_call_id``subagent_state_refs` | 子 Agent checkpoint。 |
| 通信进度 | `communicate_update_*` | 长任务进度和最终摘要。 |
| 会话时间 | `conversation_started_timestamp_ms``conversation_started_time_zone` | 会话开始时间。 |
| Goal | `goal_state` | 长期目标状态。 |
注意:多个字段使用 `bytes`,其内部内容通常仍是另一种 protobuf 或 JSON 编码。消费者必须依据字段定义解码,不能把所有 bytes 都当作 UTF-8 文本。
## 22. 消息配对关系
### 22.1 Run
```text
AgentClientMessage.run_request
-> AgentServerMessage.interaction_update (...多条)
-> AgentServerMessage.conversation_checkpoint_update
-> AgentServerMessage.interaction_update.turn_ended
-> stream end
```
### 22.2 Exec
```text
AgentServerMessage.exec_server_message(id, exec_id)
-> AgentClientMessage.exec_client_message(id, exec_id) (...可多条)
-> AgentClientMessage.exec_client_control_message(id) (...可选)
```
### 22.3 Interaction
```text
AgentServerMessage.interaction_query(id, query)
-> AgentClientMessage.interaction_response(id, matching_result)
```
### 22.4 KV
```text
AgentServerMessage.kv_server_message(id, get/set)
-> AgentClientMessage.kv_client_message(id, matching_result)
```
## 23. `oneof` 与可选字段规则
- 同一个 `oneof` 在一条 protobuf 消息中只能设置一个分支。
- 未设置 `optional` 字段和设置为默认值在业务语义上可能不同,消费者需要保留 presence 信息。
- 未识别的 protobuf 字段应按 protobuf 兼容规则保留或忽略,不应导致整条消息无法解析。
- 请求与响应的类型必须匹配,不能只依赖相同的 `id`
- `request_id``conversation_id``model_call_id``tool_call_id``exec_id` 和桥接 `id` 属于不同命名空间,不应互相替代。
- 增量消息只表达追加内容;接收方不应把 delta 当作完整快照覆盖已有内容。
- checkpoint 表达完整状态视图;同类的新 checkpoint 可以替代旧 checkpoint。
## 24. 错误与终止语义
协议需要区分三类结束:
1. 正常业务结束
- 典型信号是 `InteractionUpdate.turn_ended`,随后流结束。
2. 用户或系统取消
- 可能先出现 Exec `abort`,随后 RunSSE 以 canceled 状态结束。
3. 协议、provider 或服务错误
- 可以通过 Connect end-stream error 返回,不一定存在对应的 `AgentServerMessage.oneof` 分支。
因此,客户端不能仅凭“流关闭”判断正常完成;还需要结合最后一条业务消息和流终止状态。