会话事件流
发送事件、流式传输响应,并在执行过程中中断或重定向您的会话。
与 Claude Managed Agents 的通信基于事件。您打开一个流来跟踪会话,发送事件来指挥它,并在它暂停等待输入时作出回应。
事件类型
事件在两个方向上流动:您向智能体发送事件,会话向您发回事件。
- 您发送的事件:
user.*事件用于启动会话,并在会话推进过程中引导它。system.message事件用于追加系统级上下文。 - 您接收的事件: 会话事件、span 事件和智能体事件报告会话的状态和智能体的进度。
这些事件类型字符串遵循 {domain}.{action} 命名约定。完整目录请参阅参考文档中的事件类型。
Webhook 事件类型是独立的,其中一些名称与流中的名称不同。例如,webhook 使用 session.status_idled 而不是 session.status_idle。
流式传输事件
从会话流式传输事件,以便在智能体工作时接收实时更新。流只会传递其打开之后发出的事件,因此请在发送事件之前打开流,以避免竞态条件。
# 先打开流,再发送用户消息
with client.beta.sessions.events.stream(session.id) as stream:
client.beta.sessions.events.send(
session.id,
events=[
{
"type": "user.message",
"content": [{"type": "text", "text": "Summarize the repo README"}],
},
],
)
for event in stream:
match event.type:
case "agent.message":
for block in event.content:
if block.type == "text":
print(block.text, end="")
case "session.status_idle":
break
case "session.error":
error_message = event.error.message if event.error else "unknown"
print(f"\n[Error: {error_message}]")
break会话通过 session.error 事件报告错误。有关其字段,请参阅事件类型。
智能体的响应文本以缓冲的 agent.message 事件形式到达,每个事件仅在生成它的模型请求完成后才会发出。要在模型仍在生成文本时渲染文本,请参阅使用事件增量预览响应。
重新连接而不遗漏事件
要重新连接到现有会话而不遗漏事件,请将新流与事件历史结合使用:
- 打开一个新流。
- 列出完整的事件历史,以初始化一组已见事件 ID。
- 跟踪实时流,跳过历史列表中已返回的任何事件。
with client.beta.sessions.events.stream(session.id) as stream:
# 流已打开并在缓冲。先列出历史记录,再跟踪实时事件。
history = client.beta.sessions.events.list(session.id)
seen_event_ids = {past_event.id for past_event in history}
# 跟踪实时事件,跳过已见过的事件
for event in stream:
if event.type == "event_start" or event.type == "event_delta":
# 此连接未启用增量预览。
continue
if event.id in seen_event_ids:
continue
seen_event_ids.add(event.id)
match event.type:
case "agent.message":
for block in event.content:
if block.type == "text":
print(block.text, end="")
case "session.status_idle":
break发送事件
发送 user.message 事件以启动或继续智能体的工作:
client.beta.sessions.events.send(
session.id,
events=[
{
"type": "user.message",
"content": [
{
"type": "text",
"text": "Analyze the performance of the sort function in utils.py",
},
],
},
],
)会话历史中的每个事件都包含一个 processed_at 时间戳,在事件处理完成时设置。对于您发送的事件,当事件仍排在较早事件之后等待处理时,processed_at 为 None。例外情况是 user.define_outcome、user.custom_tool_result 和 user.tool_result,它们在收到时即被处理,回显时 processed_at 已被填充。
在会话进入空闲状态时作出响应
session.status_idle 事件表示智能体已停止并正在等待输入。其 stop_reason.type 说明了原因:
stop_reason.type | 会话停止的原因 | 应采取的操作 |
|---|---|---|
end_turn | 智能体完成了其轮次,或您中断了它。 | 当您有更多工作交给智能体时,发送 user.message。 |
requires_action | 一个或多个工具调用需要您的回答,例如自定义工具调用或确认请求。 | 回答每个阻塞的工具调用。 |
budget_reached | 会话跟踪的标价成本达到了其预算。 | 更改或移除预算。 |
您发送的任何事件都无法恢复因达到预算而暂停的会话。当您将预算更改为高于已消耗标价成本的值或移除预算时,被预算暂停的工作会自动恢复。工作恢复时,会话会为每个被预算暂停的工作流运行发出一个 workflow_run.status_running 事件。被中断暂停的运行会保持暂停状态;请参阅在达到预算时恢复会话。有关标记暂停的事件以及会话仍接受的事件,请参阅当会话达到其预算时。
回答使会话暂停的工具调用
当智能体调用自定义工具时,以及当某个工具调用在权限策略下需要您确认时,会话会暂停。这两种暂停遵循相同的顺序:
- 会话以
agent.custom_tool_use、agent.tool_use或agent.mcp_tool_use事件的形式发出工具调用。 - 会话以一个
stop_reason.type为requires_action的session.status_idle事件暂停。阻塞事件的 ID 位于stop_reason.event_ids数组中。 - 针对每个阻塞事件 ID,发送一个
user.custom_tool_result或user.tool_confirmation事件。自定义工具结果不必等待第 2 步。 - 所有阻塞事件都解决后,会话会转换回
running。
在多智能体会话中,子智能体的阻塞事件会被交叉发布到主线程。请参阅工具权限和自定义工具。
返回自定义工具结果
agent.custom_tool_use 事件包含工具名称和输入。在您的系统中运行该工具。然后发送 user.custom_tool_result 事件,在 custom_tool_use_id 参数中传入事件 ID,并附上结果内容。
您可以在 agent.custom_tool_use 事件到达后立即发送结果,无需等待 session.status_idle。会话仍会针对该调用发出带有 requires_action 停止原因的 session.status_idle,您的客户端可以忽略它。针对同一调用的第二个结果会被接受,但不会产生任何效果。
当您重新连接到已暂停的会话时,最新 session.status_idle 事件上的 stop_reason.event_ids 会列出需要回答的调用。
以下示例在每个调用到达时回答它:
with client.beta.sessions.events.stream(session.id) as stream:
for event in stream:
match event.type:
case "agent.custom_tool_use":
# 执行工具
result = call_tool(event.name, 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 "session.status_idle":
if event.stop_reason and event.stop_reason.type == "end_turn":
break如果智能体有打开的工作流运行,自定义工具调用可能会在会话保持 running 时到达。只有当会话的所有线程都不在工作时,requires_action 空闲事件才会到达。不要等待它:在每个调用的 agent.custom_tool_use 事件到达时就回答它。跟踪运行中的示例展示了具体做法。
确认工具调用
发送 user.tool_confirmation 事件,在 tool_use_id 参数中传入事件 ID。将 result 设置为 "allow" 或 "deny"。有关哪些调用需要等待确认以及如何解释拒绝,请参阅响应确认请求。
以下示例批准每个待处理的调用:
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上面的示例在会话进入空闲状态后批准每个调用。如果智能体有打开的工作流运行,工具调用可能会在会话保持 running 时等待您的确认。不要等待空闲事件:当 agent.tool_use 或 agent.mcp_tool_use 事件到达且其 evaluated_permission 为 ask 时,就回答它。跟踪运行中的示例以这种方式回答自定义工具调用,其简介部分说明了如何添加确认。
恢复空闲会话
会话在多次交互之间持久存在。要恢复会话,像往常一样向其发送 user.message 事件即可:
# 通过发送新的 user.message 事件来恢复先前创建的会话。
# 在生产环境中,传入您想要恢复的会话的已存储 ID。
client.beta.sessions.events.send(
session.id,
events=[
{
"type": "user.message",
"content": [
{
"type": "text",
"text": "Now run the tests against the changes you made earlier.",
},
],
},
],
)除非会话被显式删除,否则对话历史会被保留。当会话进入空闲状态时,其沙箱会被创建检查点。检查点保留完整的沙箱状态,包括文件系统、已安装的软件包以及智能体创建的任何文件。
中断智能体
发送 user.interrupt 事件以在执行过程中停止智能体,然后发送 user.message 事件来重定向它:
# 智能体当前正在分析文件...
# 用新的指令中断:
client.beta.sessions.events.send(
session.id,
events=[
{"type": "user.interrupt"},
{
"type": "user.message",
"content": [
{
"type": "text",
"text": "Instead, focus on fixing the bug in line 42.",
},
],
},
],
)事件一旦进入队列,调用就会返回。随后中断按以下顺序生效:
- 智能体应用中断。在此之前,中断的
processed_at保持为None,会话保持running。正在进行的模型响应会立即停止,但当工具调用正在运行时,中断可能需要更长时间才能生效。 user.interrupt事件出现在流中,被中断的轮次以session.status_idle事件结束。- 智能体以您在中断后发送的
user.message开始下一个轮次。
空闲事件的 stop_reason.type 为 end_turn,与自行完成的轮次的值相同。如果有打开的工作流运行,中断不会结束其中任何一个。正在运行的运行可能使会话保持 running,因此第 2 步中的 session.status_idle 事件可能不会到达。请参阅在有打开的运行时中断会话。
列出过去的事件
检索会话的完整事件历史:
events = client.beta.sessions.events.list(session.id)
for event in events.data:
print(f"[{event.type}] {event.processed_at}")传入 types 过滤器以仅返回特定的事件类型:
events = client.beta.sessions.events.list(
session.id,
types=["agent.tool_use", "agent.tool_result"],
)
for event in events.data:
print(f"[{event.type}] {event.processed_at}")发送系统消息
在受支持的模型上,发送 system.message 事件可为智能体提供特权的系统级上下文。该上下文适用于随附的轮次以及所有后续轮次。当智能体在会话中途需要更新的系统级指导时使用它,例如不同的角色设定、修订后的约束条件或在运行时获取的上下文。
该事件的 content 接受 1–1000 个文本项。内容会作为 role: "system" 轮次追加到会话的系统上下文中。它不会替换顶层系统提示,顶层系统提示由智能体定义上的 system 字段设置。
client.beta.sessions.events.send(
session.id,
events=[
{
"type": "system.message",
"content": [
{
"type": "text",
"text": "The user's current timezone is America/New_York.",
},
],
},
],
)受支持的模型
以下模型支持 system.message:
- Claude Fable 5.1
- Claude Mythos 5.1
- Claude Fable 5
- Claude Mythos 5
- Claude Opus 5.5
- Claude Opus 5
- Claude Opus 4.8
- Claude Sonnet 5.5
- Claude Haiku 5.5
如果智能体的主模型不支持在对话中途注入系统内容,该事件将被拒绝,并返回 model_does_not_support_mid_conversation_system 验证错误。子智能体模型不会被检查,因为 system.message 仅落在主线程上。
工具调用待处理时的系统消息
当会话以 requires_action 停止原因处于空闲状态时,system.message 必须在同一请求中跟在工具结果事件之后。如果单独发送或与 user.message 一起发送,在待处理的工具事件解决之前,它都会被拒绝。
后续步骤
在模型仍在生成时渲染智能体的响应文本。
在 Claude Console 中检查会话,并查看其令牌用量和标价成本。
在重大事件发生时获得通知,无需轮询。
查阅会话可以发送或接收的每种事件类型。
Was this page helpful?