# 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` 分支。 因此,客户端不能仅凭“流关闭”判断正常完成;还需要结合最后一条业务消息和流终止状态。