与 Claude 托管代理的通信是基于事件的。您向代理发送用户事件,并接收代理事件和会话事件以跟踪状态。
所有 Managed Agents API 请求都需要 managed-agents-2026-04-01 beta 标头。SDK 会自动设置该 beta 标头。
事件以两个方向流动。
user.* 事件启动会话并在会话进行过程中对其进行引导;system.message 在轮次之间更新代理的系统提示。会话、跨度、代理、用户和系统事件类型字符串遵循 {domain}.{action} 命名约定。仅限流的增量预览事件(event_start、event_delta)是例外。请参阅参考文档中的事件类型以获取完整目录。
每个持久化事件都包含一个 processed_at 时间戳,指示该事件在服务器端被记录的时间。如果 processed_at 为 null,则表示该事件已被执行框架排队,并将在前面的事件处理完成后进行处理。
默认情况下,代理的响应文本以缓冲的 agent.message 事件形式到达流,每个事件仅在生成它的模型请求完成后才发出。"Event deltas"(事件增量)让您可以在模型仍在生成文本时,以实时预览的方式增量渲染该文本。预览不是响应本身:预览是尽力而为的显示辅助,缓冲的 agent.message 始终是权威记录。忽略预览的客户端仍会收到完整、正确的流。
预览是按流连接选择加入的。将 event_deltas[] 查询参数添加到 GET /v1/sessions/{session_id}/events/stream,为您希望预览的每种事件类型重复添加一次。可接受的值为 agent.message 和 agent.thinking;任何其他值都会返回 400 错误。只有会话级事件流支持该参数。会话线程事件流会拒绝它。
当预览事件开始时,流会发出一个 event_start,其中包含即将到来的事件的类型和 id:
{
"type": "event_start",
"event": {
"type": "agent.message",
"id": "sevt_01abc..."
}
}对于 agent.message,在 start 之后会跟随携带增量文本的 event_delta 事件。每个增量在 event_id 中指明它所扩展的事件,在 delta.index 中指明它所扩展的内容块:
{
"type": "event_delta",
"event_id": "sevt_01abc...",
"delta": {
"type": "content_delta",
"index": 0,
"content": {
"type": "text",
"text": "Here is the summary"
}
}
}当预览 agent.thinking 事件时,只会发出 event_start。不会跟随任何 event_delta 事件,内容会像往常一样在缓冲的 agent.thinking 事件中到达。
与持久化事件不同,event_start 和 event_delta 本身没有 id 或 processed_at。它们携带的唯一标识符是它们所预览的事件的 id。
事件增量使用的传输格式与流式传输消息不同,这种差异是有意为之的。预览的 agent.message 会收到一个 event_start,之后仅跟随 event_delta 事件。没有针对每个内容块的 start 或 stop 事件,也没有针对预览事件本身的 stop 事件。增量类型是 content_delta,而不是 content_block_delta。为 Messages API 编写的累加器代码无法原封不动地沿用。
Python、TypeScript 和 Go SDK 包含一个累加器辅助工具,它以事件的 id 为键来管理预览,并为您处理 index 的记录工作。手动模式适用于所有语言:在其他 SDK 中,将其应用于生成的事件类型。
在手动模式中,将预览视为临时缓冲区,将缓冲事件视为正式记录。以 (event_id, index) 为键管理缓冲区。按模型请求进行协调:一个轮次以单个 session.status_running 事件开始,然后在正常完成的轮次中,每个模型请求依次产生 span.model_request_start、event_start、event_delta 事件、缓冲的 agent.message,最后是 span.model_request_end(在 Span events 选项卡中)。在每个事件到达时进行处理:
event_start 时,记录所宣告的 id。这些标识符始终一致:event_start.event.id、每个 event_delta.event_id 以及缓冲的 agent.message 的 id 都是相同的值。event_delta 时,将 delta.content.text 追加到 (event_id, delta.index) 处的条目,并渲染当前累积的文本。某个 index 的第一个增量会创建该条目。agent.message 到达时,通过 id 进行匹配,丢弃累积的预览,改为渲染该消息的内容。span.model_request_end 时,关闭任何尚未被其缓冲事件协调的预览。不会再有针对它的增量到来。如果轮次出错或被中断,缓冲事件可能永远不会到达;但 span.model_request_end 仍会到达。# 预览快照,以事件 ID 为键。accumulate_managed_agents_event 将每个
# event_start / event_delta 折叠为一个 agent.message 快照;缓冲的
# agent.message 会替换它。
previews: dict[str, BetaManagedAgentsAgentMessageEvent] = {}
# 在此连接上选择启用 agent.message 预览
with client.beta.sessions.events.stream(
session.id, event_deltas=["agent.message"]
) as stream:
client.beta.sessions.events.send(
session.id,
events=[
{
"type": "user.message",
"content": [{"type": "text", "text": "Describe the repo in one sentence."}],
},
],
)
for event in stream:
match event.type:
case "event_start":
snapshot = accumulate_managed_agents_event(None, event)
if snapshot is not None:
previews[event.event.id] = snapshot
print(f"event_start {event.event.type} {event.event.id}")
case "event_delta":
preview = accumulate_managed_agents_event(previews.get(event.event_id), event)
if preview is not None:
previews[event.event_id] = preview
text = "".join(block.text for block in preview.content)
print(f"event_delta preview: {text!r}")
case "agent.message":
# 缓冲的事件即为最终记录:它会替换并关闭预览
preview = accumulate_managed_agents_event(previews.pop(event.id, None), event)
text = "".join(block.text for block in preview.content)
print(f"agent.message {event.id} {text!r}")
case "span.model_request_end":
# 不会再有增量到来。关闭所有
# 缓冲事件从未到达的预览。
for event_id in previews:
print(f"span.model_request_end closing preview for {event_id}")
previews.clear()
case "session.status_idle":
break预览针对响应速度进行了优化。请基于以下约束进行构建:
agent.message 仍会完整到达。切勿将累积的预览视为最终结果。agent.message。无法重新请求遗漏的增量。agent.thinking 仅有 start: agent.thinking 预览仅发出 event_start,作为思考块已开始的信号;不会跟随任何 event_delta 事件。event_start 和 event_delta 仅存在于实时流中。它们不会出现在会话的事件历史记录中(GET /v1/sessions/{session_id}/events)。当代理调用自定义工具时:
agent.custom_tool_use 事件,其中包含工具名称和输入。session.status_idle 事件,其中包含 stop_reason: requires_action。阻塞事件 ID 位于 stop_reason.event_ids 数组中。user.custom_tool_result 事件,在 custom_tool_use_id 参数中传递事件 ID 以及结果内容。running 状态。with client.beta.sessions.events.stream(session.id) as stream:
for event in stream:
if event.type == "session.status_idle" and (stop_reason := event.stop_reason):
match stop_reason.type:
case "requires_action":
for event_id in stop_reason.event_ids:
# 查找自定义工具使用事件并执行它
tool_event = events_by_id[event_id]
result = call_tool(tool_event.name, tool_event.input)
# 将结果发送回去
client.beta.sessions.events.send(
session.id,
events=[
{
"type": "user.custom_tool_result",
"custom_tool_use_id": event_id,
"content": [{"type": "text", "text": result}],
},
],
)
case "end_turn":
break当权限策略要求在工具执行前进行确认时:
agent.tool_use 或 agent.mcp_tool_use 事件。session.status_idle 事件,其中包含 stop_reason: requires_action。阻塞事件 ID 位于 stop_reason.event_ids 数组中。user.tool_confirmation 事件,在 tool_use_id 参数中传递事件 ID。将 result 设置为 "allow" 或 "deny"。使用 deny_message 来解释拒绝原因。running 状态。with client.beta.sessions.events.stream(session.id) as stream:
for event in stream:
if event.type == "session.status_idle" and (stop_reason := event.stop_reason):
match stop_reason.type:
case "requires_action":
for event_id in stop_reason.event_ids:
# 批准待处理的工具调用
client.beta.sessions.events.send(
session.id,
events=[
{
"type": "user.tool_confirmation",
"tool_use_id": event_id,
"result": "allow",
},
],
)
case "end_turn":
break会话在交互之间持久存在。除非会话被显式删除,否则对话历史记录会被保留。当会话进入空闲状态时,其沙箱会被创建检查点,保留完整的沙箱状态,包括文件系统、已安装的软件包以及代理创建的任何文件。这使您能够从非活动状态干净地恢复。
虽然会话历史记录会一直保留到被删除,但检查点仅在会话最后一次活动后保留 30 天。如果您的工作流需要完整的沙箱状态(文件、已安装的工具等)持久保存超过 30 天,请在检查点过期之前定期发送 user.message 事件以重置非活动计时器。
要恢复会话,像往常一样向其发送 user.message 事件:
# 在生产环境中,传入您想要恢复的会话的已存储 ID。
ant beta:sessions:events send --session-id "$SESSION_ID" <<'YAML'
events:
- type: user.message
content:
- type: text
text: Now run the tests against the changes you made earlier.
YAMLsystem.message 目前仅受 Claude Opus 4.8 支持。如果代理上配置的任何模型不支持对话中途的系统注入,该事件将被拒绝,并返回 model_does_not_support_mid_conversation_system 验证错误。
发送 system.message 事件以在轮次之间更新代理的系统提示。与代理定义上的 system 字段(在会话创建时固定)不同,system.message 允许您在会话进行过程中更改系统提示。当代理在会话中途需要更新的系统级指导时使用它:不同的角色设定、修订的约束条件,或在运行时获取的、应影响模型后续行为的上下文。
ant beta:sessions:events send --session-id "$SESSION_ID" <<'YAML'
events:
- type: system.message
content:
- type: text
text: "The user's current timezone is America/New_York."
YAML当会话处于空闲状态且 stop_reason: requires_action 时,无法发送 system.message。content 接受 1–1000 个文本项。
会话对象包含一个 usage 字段,其中包含累积的令牌统计信息。在会话进入空闲状态后获取会话以读取最新总计,并使用它们来跟踪成本、执行预算或监控消耗。
{
"id": "sesn_01...",
"status": "idle",
"usage": {
"input_tokens": 5000,
"output_tokens": 3200,
"cache_creation_input_tokens": 2000,
"cache_read_input_tokens": 20000
}
}input_tokens 报告未缓存的输入令牌,output_tokens 报告会话中所有模型调用的总输出令牌。cache_creation_input_tokens 和 cache_read_input_tokens 字段反映提示缓存活动。缓存条目使用 5 分钟的 TTL,因此在该时间窗口内的连续轮次可以受益于缓存读取,从而降低每令牌成本。
控制台提供代理会话的可视化时间线视图。导航到控制台中的 Claude 托管代理部分以查看:
session.error 事件传达Was this page helpful?