Claude Platform Docs
Managed Agents将工作委派给智能体

会话事件流

发送事件、流式传输响应,并在执行过程中中断或重定向您的会话。

与 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 事件形式到达,每个事件仅在生成它的模型请求完成后才会发出。要在模型仍在生成文本时渲染文本,请参阅使用事件增量预览响应。

重新连接而不遗漏事件

要重新连接到现有会话而不遗漏事件,请将新流与事件历史结合使用:

  1. 打开一个新流。
  2. 列出完整的事件历史,以初始化一组已见事件 ID。
  3. 跟踪实时流,跳过历史列表中已返回的任何事件。
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 事件。被中断暂停的运行会保持暂停状态;请参阅在达到预算时恢复会话。有关标记暂停的事件以及会话仍接受的事件,请参阅当会话达到其预算时。

回答使会话暂停的工具调用

当智能体调用自定义工具时,以及当某个工具调用在权限策略下需要您确认时,会话会暂停。这两种暂停遵循相同的顺序:

  1. 会话以 agent.custom_tool_use、agent.tool_use 或 agent.mcp_tool_use 事件的形式发出工具调用。
  2. 会话以一个 stop_reason.type 为 requires_action 的 session.status_idle 事件暂停。阻塞事件的 ID 位于 stop_reason.event_ids 数组中。
  3. 针对每个阻塞事件 ID,发送一个 user.custom_tool_result 或 user.tool_confirmation 事件。自定义工具结果不必等待第 2 步。
  4. 所有阻塞事件都解决后,会话会转换回 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.",
                },
            ],
        },
    ],
)

事件一旦进入队列,调用就会返回。随后中断按以下顺序生效:

  1. 智能体应用中断。在此之前,中断的 processed_at 保持为 None,会话保持 running。正在进行的模型响应会立即停止,但当工具调用正在运行时,中断可能需要更长时间才能生效。
  2. user.interrupt 事件出现在流中,被中断的轮次以 session.status_idle 事件结束。
  3. 智能体以您在中断后发送的 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?