Skip to main content
与 Open Managed Agents的通信是基于事件的。您向智能体发送用户事件,并接收返回的智能体事件和会话事件以跟踪状态。
托管智能体 API 请求需要 managed-agents-2026-04-01 Beta 请求头,但记忆存储端点除外,它们使用 agent-memory-2026-07-22。SDK 会自动设置正确的 Beta 请求头。请参阅Beta 请求头

事件类型

事件以两个方向流动。
  • 用户事件系统事件是您发送给智能体的内容:user.* 事件用于启动会话并在会话进行过程中对其进行引导;system.message 用于追加系统级上下文,该上下文适用于随附的轮次及所有后续轮次。
  • 会话事件跨度事件智能体事件会发送给您,以便您观察会话状态和智能体进度。选择加入的流连接还会接收事件增量
会话、跨度、智能体、用户和系统事件类型字符串遵循 {domain}.{action} 命名约定。仅限流的增量预览事件(event_startevent_delta)是例外。请参阅参考文档中的事件类型以获取完整目录。 每个持久化事件都包含一个 processed_at 时间戳,该时间戳在事件完成处理时设置。对于您发送的事件,当事件仍在排队等待处理先前事件时,processed_at 为 null。例外情况是 user.define_outcomeuser.custom_tool_resultuser.tool_result,它们在接收时即被处理,并在回显时已填充 processed_at

集成事件

发送 user.message 事件以启动或继续智能体的工作:
发送 user.interrupt 事件以在执行过程中停止智能体,然后跟进发送 user.message 事件以重定向它:
智能体会确认中断并切换到新任务。被中断的轮次以 session.status_idle 事件结束,其 stop_reasonend_turn,与自行完成的轮次的值相同;没有专门针对中断的停止原因。

事件增量

默认情况下,智能体的响应文本以缓冲的 agent.message 事件形式到达流,每个事件仅在生成它的模型请求完成后才发出。事件增量让您能够在模型仍在生成文本时,以实时预览的方式增量渲染该文本。预览不是响应本身:预览是尽力而为的显示辅助,缓冲的 agent.message 始终是权威记录。忽略预览的客户端仍会收到完整、正确的流。

选择加入预览

预览是按流连接选择加入的。将 event_deltas[] 查询参数添加到您正在读取的流中,为您希望预览的每种事件类型重复一次。由于 [] 是 shell 通配符模式,因此在 shell 中构建请求时请为 URL 加引号;示例中将方括号百分号编码为 %5B%5D,这同样有效。两个流端点都接受该参数:位于 GET /v1/sessions/{session_id}/events/stream 的会话级流,以及每个会话线程自己的流,位于 GET /v1/sessions/{session_id}/threads/{thread_id}/stream。接受的值为 agent.messageagent.thinking;任何其他值都会返回 400 错误,包含超过 100 个值的请求也是如此。子智能体的预览出现在该子智能体自己的线程流上。 当预览事件开始时,流会发出一个 event_start,其中携带即将到来的事件的类型和 id
对于 agent.message,起始事件之后是携带增量文本的 event_delta 事件。每个增量在 event_id 中指明它所扩展的事件,在 delta.index 中指明它所扩展的内容块:
当预览 agent.thinking 事件时,仅发出 event_start。不会跟随任何 event_delta 事件,并且结束预览的缓冲 agent.thinking 事件不携带任何思考内容;它是一个进度信号,而非内容载体。 与持久化事件不同,event_startevent_delta 本身没有 idprocessed_at。它们携带的唯一标识符是它们所预览的事件的 id
事件增量使用与流式传输消息不同的传输格式,这种差异是有意为之的。预览的 agent.message 会得到一个 event_start,之后仅跟随 event_delta 事件。没有针对每个内容块的开始或停止事件,也没有针对预览事件本身的停止事件。增量类型是 content_delta,而非 content_block_delta。为消息 API 编写的累加器代码无法原封不动地沿用。

累加与协调

每个支持事件增量的 SDK 都包含一个累加器辅助工具,为您处理 index 的记录工作。Go、Java、Ruby 和 C# 的辅助工具还会按事件的 id 为累加中的预览建立键值映射;使用 Python、TypeScript 和 PHP 的辅助工具时,您需要自己维护该映射,并将每个增量合并到其 id 对应的条目中。当您需要自定义记录逻辑时,手动模式在每种语言中同样适用:将其应用于生成的事件类型即可。 在手动模式中,将预览视为临时缓冲区,将缓冲事件视为正式记录。以 (event_id, index) 作为缓冲区的键。按模型请求进行协调:一个轮次以单个 session.status_running 事件开始,然后在正常完成的轮次中,每个模型请求依次产生 span.model_request_startevent_start、若干 event_delta 事件、缓冲的 agent.message,最后是 span.model_request_end(位于“跨度事件”选项卡中)。在传输层面,这是该序列的预览部分,与连接的其他缓冲事件交错出现:
event_delta 行对每个文本片段重复一次。在每个事件到达时进行处理:
  1. 收到 event_start 时,记录所宣告的 id。这些标识符始终一致:event_start.event.id、每个 event_delta.event_id 以及缓冲的 agent.messageid 都是相同的值。
  2. 收到每个 event_delta 时,将 delta.content.text 追加到 (event_id, delta.index) 处的条目,并渲染累积的文本。某个 index 的第一个增量会创建该条目。
  3. 当缓冲的 agent.message 到达时,按 id 匹配它,丢弃累加的预览,改为渲染该消息的内容。
  4. 收到 span.model_request_end 时,关闭任何尚未被其缓冲事件协调的预览。不会再有针对它的增量到来。如果轮次出错或被中断,缓冲事件可能永远不会到达;但 span.model_request_end 仍会到达。
该模式所依赖的保证:
  • 按到达顺序连接某个预览的增量,并以 (event_id, index) 为键,可得到缓冲事件中 content[index].text 的前缀(是前缀,不一定是完整文本,因为在负载较高时增量可能被丢弃)。
  • 一个连接对每个 event_id 最多发出一个 event_start,并且缓冲事件是该连接为该 id 传递的最后一项内容。

预览会话线程事件

多智能体会话中,每个会话线程在 GET /v1/sessions/{session_id}/threads/{thread_id}/stream 处都有自己的事件流,并且它接受相同的 event_deltas[] 参数和相同的值。预览在设计上是线程范围的:一个连接仅预览它正在读取的线程。子线程的预览在该子线程自己的流上传递,永远不会交叉发布到会话级流,后者的预览始终限定于主线程。要在模型生成时观察子智能体的文本,请打开该子智能体的线程流。 线程流的路径很容易弄错:它是 /threads/{thread_id}/stream,而不是 /events/stream(后者仅存在于会话级别),并且不存在 /threads/{thread_id}/events/stream 端点。 预览事件本身不会改变。event_startevent_delta 在线程流上的结构与在会话级流上相同,累加与协调模式可按原样应用。唯一的调整是记录方式:为每个流连接运行一个累加器实例。
读取循环在 session.thread_status_idle 时退出,该事件在会话线程的轮次完成且线程进入空闲状态时发出。

限制

预览针对响应速度进行了优化。请基于以下约束进行构建:
  • 尽力而为: 在负载较高时,服务器可能会丢弃某个事件的增量。发生这种情况时,您会收到文本的连续前缀,之后不再收到该事件的任何增量。缓冲的 agent.message 仍会完整到达。切勿将累加的预览视为最终结果。
  • 重连时不重放: 增量仅在选择加入的连接打开期间传递给该连接。这同样适用于会话级流和每个会话线程流,并且在模型请求开始后打开的连接不会收到该进行中事件的任何增量。如果流断开,请按照”流式传输事件”选项卡中的重连步骤操作:重新打开流并列出事件历史记录。历史记录包含您断开连接期间发出的所有缓冲事件,包括您的预览正在等待的 agent.message。无法重新请求已错过的增量。
  • 单线程,仅文本: 预览涵盖连接正在读取的线程上的助手文本。工具使用、工具结果、MCP 结果以及任何其他会话线程上的活动永远不会在该连接上被预览。
  • agent.thinking 仅有起始事件: agent.thinking 预览仅发出 event_start 作为思考块已开始的信号;不会跟随任何 event_delta 事件。
  • 从不持久化: event_startevent_delta 仅存在于实时流中。它们不会出现在会话的事件历史记录(GET /v1/sessions/{session_id}/events)中,也不会出现在任何会话线程的事件历史记录中。

预览故障排查

如果流的行为与您的预期不符:

其他场景

处理自定义工具调用

当智能体调用自定义工具时:
  1. 会话发出一个包含工具名称和输入的 agent.custom_tool_use 事件。
  2. 会话暂停,并发出包含 stop_reason: requires_actionsession.status_idle 事件。阻塞事件 ID 位于 stop_reason.event_ids 数组中。
  3. 在您的系统中执行该工具,并为每个事件发送一个 user.custom_tool_result 事件,在 custom_tool_use_id 参数中传递事件 ID 以及结果内容。
  4. 一旦所有阻塞事件都已解决,会话将转换回 running 状态。

工具确认

权限策略要求在工具执行前进行确认时:
  1. 会话发出 agent.tool_useagent.mcp_tool_use 事件。
  2. 会话暂停,并发出包含 stop_reason: requires_actionsession.status_idle 事件。阻塞事件 ID 位于 stop_reason.event_ids 数组中。
  3. 为每个事件发送一个 user.tool_confirmation 事件,在 tool_use_id 参数中传递事件 ID。将 result 设置为 "allow""deny"。使用 deny_message 解释拒绝原因。
  4. 一旦所有阻塞事件都已解决,会话将转换回 running 状态。

恢复空闲会话

会话在交互之间持久存在。除非显式删除会话,否则对话历史记录会被保留。当会话进入空闲状态时,其沙箱会被检查点保存,保留完整的沙箱状态,包括文件系统、已安装的软件包以及智能体创建的任何文件。这使您能够从非活动状态干净地恢复。
虽然会话历史记录会一直保留直到被删除,但沙箱状态仅在沙箱创建后保留 30 天。活动不会延长此窗口期:30 天后,沙箱状态(文件、已安装的工具等)将无法恢复,恢复的会话将从全新的沙箱开始。如果您的工作流程依赖于沙箱内容,请让智能体在窗口期结束前将重要产物写入输出
要恢复会话,像往常一样向其发送 user.message 事件:

达到会话预算

使用预算创建的会话会暂停而不是超支。当会话的跟踪标价成本达到上限时,平台会在每个线程的下一个模型请求之前暂停该线程,会话进入空闲状态,其 stop_reasonbudget_reached,而不是终止。使总额超过上限的那个请求会运行至完成,因此 session.usage 快照报告的 list_cost 可能显示为等于或略微超过上限。在流上,暂停以三个事件的形式依次到达:
  1. session.thread_status_idle,带有 stop_reason: budget_reached,每个线程暂停时各发出一个。
  2. session.usage,会话累计使用量和跟踪标价成本的快照。
  3. session.status_idle,带有 stop_reason: budget_reachedsession.usage 事件始终紧接在此空闲事件之前。
如果某个线程的最后一个请求既越过了上限又完成了其轮次,则该线程自己的 session.thread_status_idle 事件报告 end_turn,而会话仍报告 budget_reached;请以会话级的 stop_reason 为准来检测暂停。 当会话处于上限状态时,它仅接受用于结清已在进行中的工作的事件:user.tool_confirmationuser.tool_resultuser.custom_tool_resultuser.interrupt。任何会启动新工作的事件(包括 user.message)都会被拒绝,并返回列出上述事件的 400 错误。当会话同时存在一个等待工具确认的线程和一个在上限处暂停的线程时,会话级的 stop_reasonrequires_action 而非 budget_reached:结清该确认请求不会触发模型请求,因此请照常响应它。 没有任何事件能恢复在上限处暂停的会话。取而代之的是更新会话的预算:将上限更改为任何高于已消耗标价成本的值,或通过使用 "budget": null 更新会话来移除预算,都会自动恢复暂停的工作。有关标价成本的跟踪方式和完整的预算更新语义,请参阅会话预算

发送系统消息

system.message 目前受 claude-opus-4-8claude-fable-5claude-mythos-5claude-opus-5 支持。如果智能体的主模型不支持对话中途的系统注入,该事件将被拒绝并返回 model_does_not_support_mid_conversation_system 验证错误;子智能体模型不会被检查,因为 system.message 仅落在主线程上。
发送 system.message 事件,为智能体提供特权系统级上下文,该上下文适用于随附的轮次及所有后续轮次。与智能体定义上的 system 字段(用于设置顶层系统提示)不同,system.message 的内容会作为 role: "system" 轮次追加到会话的系统上下文中,而不是替换该提示。当智能体在会话中途需要更新的系统级指导时使用它:不同的角色设定、修订的约束条件,或在运行时获取的、应影响模型后续行为的上下文。
当会话处于空闲状态且 stop_reason: requires_action 时,system.message 仅在同一请求中跟随在工具结果事件之后时才会被接受;如果单独发送或与 user.message 一起发送,它将被拒绝,直到待处理的工具事件得到解决。content 接受 1–1000 个文本项。

跟踪使用情况

会话对象包含一个 usage 字段,其中记录了会话的累计使用情况:令牌计数、服务器工具使用、活跃时间以及按标价计算的成本。在会话进入空闲状态后获取会话,即可读取最新的总计数据。
input_tokens 报告未缓存的输入令牌数,output_tokens 报告会话中所有模型调用的总输出令牌数。cache_read_input_tokens 字段报告从提示缓存中读取的令牌数,cache_creation 对象按缓存生命周期细分缓存创建令牌(ephemeral_5m_input_tokensephemeral_1h_input_tokens)。缓存条目默认使用 5 分钟的 “TTL”(生存时间),因此在该时间窗口内连续进行的轮次可以受益于缓存读取,从而降低每令牌成本。 list_cost 是会话按公开标价计算的累计消费,以字符串形式表示的整数美分值,并附带货币代码。active_seconds 是会话中至少有一个线程在运行的累计时间;并发线程的重叠活动只计算一次,这与会话 stats 对象中的 active_seconds 不同,后者是对每个线程各自活跃时间的求和。这个去重后的数值即为会话运行时成本的计价时长。server_tool_use 统计用于计价的服务器端执行的工具请求数:网络搜索请求按每次请求计入标价成本,而网络抓取请求不收取每次请求费用且不计量,因此 web_fetch_requests 显示为 0。每个会话线程自身的 usage 也包含 list_costactive_seconds。各线程的数值是独立四舍五入的,且不包含会话的运行时间成本,因此它们的总和不会与会话的 list_cost 完全相等;会话级别的数值才是权威数据。 您无需轮询会话即可观察这些总计数据。session.usage 事件会在会话流和事件历史记录中携带相同的累计快照(即 usage 对象,以及会话的 budget,当会话没有预算时该值为 null)。该事件在空闲状态转换时发出,而非按定时器发出:无论停止原因为何,会话都会在进入空闲状态之前立即发出一个此事件;当某个线程在会话预算处暂停时,也会发出一个。因此,流读取器无需额外获取即可看到某个轮次的最终成本,或触及预算的那部分工作的最终成本。 如需强制执行支出限制,请设置会话预算,而不是自行轮询使用情况并停止会话。平台会持续对会话的消费进行计价,一旦会话的标价成本达到上限,就会在每个线程的下一次模型请求之前将其暂停;有关这在流中的表现形式,请参阅达到会话预算

控制台可观测性

OMA 控制台提供了智能体会话的可视化时间线视图。导航至 Open Managed Agents 部分即可查看:
  • 会话列表: 所有会话及其状态、创建时间和智能体
  • 追踪视图: 会话内事件(内容、时间戳、令牌使用情况)的时间顺序视图。追踪视图仅对开发者和管理员开放。
  • 工具执行: 每次工具调用及其结果的详细信息

调试技巧

  • 检查会话事件: 会话错误通过 session.error 事件传达
  • 查看工具结果: 工具执行失败通常可以解释智能体的异常行为
  • 跟踪令牌使用情况: 监控令牌消耗以优化提示并降低成本
  • 使用系统提示: 在系统提示中添加日志记录指令,让智能体解释其推理过程
  • 排查预览问题: 如果选择接收事件增量的流未按预期运行,请参阅排查预览问题