基础概念

智能体循环(agent loop)

智能体循环(agent loop)是一次完整的"真实"执行过程:接收输入 → 组装上下文 → 模型推理 → 执行工具 → 流式输出回复 → 持久化状态。这是将一条消息转化为具体行动和最终回复的核心流程,同时确保会话状态始终保持一致。

在 OpenClaw 中,每个会话的循环都是串行执行的。当模型在思考、调用工具、流式输出时,系统会发出相应的生命周期事件和流事件。本文档将带你深入了解这个循环是如何端到端运作的。

入口点

  • 网关 RPCagentagent.wait
  • 命令行agent 命令

整体工作流程

整个过程可以分为以下几个关键步骤:

  1. agent RPC 接收请求后,会验证参数、解析会话(通过 sessionKeysessionId)、持久化会话元数据,然后立即返回 { runId, acceptedAt },让调用方知道请求已受理。

  2. agentCommand 负责启动智能体:

    • 解析模型配置,设置思考模式/详细模式的默认值
    • 加载技能快照
    • 调用 runEmbeddedPiAgent(这是 pi-agent-core 运行时的核心)
    • 如果嵌入式循环没有发出生命周期结束/错误事件,则补充发出
  3. runEmbeddedPiAgent 是实际执行循环的地方:

    • 通过会话级队列和全局队列来串行化运行,避免并发冲突
    • 解析模型和认证配置,构建 pi 会话
    • 订阅 pi 事件,流式传输助手消息和工具增量
    • 强制执行超时机制,超时则中止运行
    • 返回执行结果和使用量元数据
  4. subscribeEmbeddedPiSession 负责将 pi-agent-core 的事件桥接到 OpenClaw 的 agent 流:

    • 工具事件 → stream: "tool"
    • 助手增量 → stream: "assistant"
    • 生命周期事件 → stream: "lifecycle"phase: "start" | "end" | "error"
  5. agent.wait 通过 waitForAgentJob 等待指定的 runId 完成:

    • 等待生命周期结束/错误事件
    • 返回 { status: ok|error|timeout, startedAt, endedAt, error? }

队列与并发控制

为什么需要队列?因为智能体的运行必须有序。

  • 每个会话键(session key)对应一个专属通道,运行在该通道内串行执行
  • 可选的全局通道可以进一步控制整体并发
  • 这种设计有效防止了工具执行和会话状态的竞争条件
  • 消息通道可以选择不同的队列模式(collect/steer/followup),这些模式最终都会馈送到上述队列系统

更多细节请参阅 命令队列

会话与工作区准备

在智能体开始思考之前,系统需要做好准备工作:

  • 工作区:解析并创建工作目录;沙盒运行可能会重定向到沙盒工作区根目录
  • 技能:加载技能(或从快照复用),注入到环境变量和提示词中
  • 引导上下文:解析引导文件和上下文文件,注入到系统提示中
  • 会话锁:获取会话写锁,打开并初始化 SessionManager

提示词组装与系统提示

系统提示是如何构建的?

它由以下几个部分组装而成:OpenClaw 的基础提示 + 技能提示 + 引导上下文 + 本次运行的覆盖配置。组装完成后,会根据模型特定的上下文限制和压缩保留令牌数进行约束。

想了解模型实际看到的系统提示是什么样的?请参阅 系统提示

钩子点:你可以在哪里拦截和扩展

OpenClaw 提供了两套钩子系统,让你可以在关键节点插入自定义逻辑:

  • 内部钩子(Gateway hooks):基于事件的脚本,用于处理命令和生命周期事件
  • 插件钩子:深入智能体/工具生命周期和网关管道内部的扩展点

内部钩子(网关钩子)

  • agent:bootstrap:在构建引导文件时运行,此时系统提示尚未最终确定。你可以用它来添加或移除引导上下文文件。
  • 命令钩子/new/reset/stop 等命令事件触发。

设置方法和示例请参阅 钩子

插件钩子(智能体与网关生命周期)

这些钩子运行在智能体循环或网关管道内部:

钩子触发时机用途
before_model_resolve会话创建前(无 messages在模型解析前确定性地覆盖提供者/模型
before_prompt_build会话加载后(有 messages在提交提示前注入 prependContextsystemPromptprependSystemContextappendSystemContextprependContext 适合每轮动态内容,系统上下文字段适合放在系统提示中的稳定指导
before_agent_start旧版兼容可能在任一阶段运行,建议使用上述明确的新钩子
agent_end完成后检查最终消息列表和运行元数据
before_compaction / after_compaction压缩前后观察或注释压缩周期
before_tool_call / after_tool_call工具调用前后拦截工具参数和结果
tool_result_persist持久化前在工具结果写入会话记录前同步转换
message_received / message_sending / message_sent消息流转时入站和出站消息钩子
session_start / session_end会话边界会话生命周期事件
gateway_start / gateway_stop网关启停时网关生命周期事件

钩子 API 和注册详情请参阅 插件

流式传输与部分回复

当智能体在生成回复时,内容是如何流式输出的?

  • 助手增量从 pi-agent-core 流式传输,以 assistant 事件发出
  • 块流式传输可以在 text_endmessage_end 时发出部分回复
  • 推理流式传输可以作为独立流发出,也可以作为块回复的一部分

分块机制和块回复行为详见 流式传输

工具执行与消息工具

工具是智能体与外部世界交互的重要方式:

  • 工具的开始、更新、结束事件通过 tool 流发出
  • 工具结果在记录或发出前,会进行大小裁剪和图像载荷处理
  • 消息工具的发送会被跟踪,以避免重复的助手确认消息

回复的组装与抑制

最终回复是如何组装的?

最终载荷由以下部分构成:

  • 助手文本(以及可选的推理内容)
  • 内联工具摘要(当启用详细模式且允许时)
  • 模型出错时的错误提示文本

特殊处理:

  • NO_REPLY 被视为静默标记,会从输出载荷中过滤掉
  • 消息工具的重复项会从最终载荷中移除
  • 如果没有可渲染的载荷且工具出错,会发出后备工具错误回复(但如果消息工具已发送了用户可见的回复,则不会重复发送)

压缩与重试

当上下文过长时,系统会自动压缩:

  • 自动压缩会发出 compaction 流事件,并可能触发重试
  • 重试时,内存缓冲区和工具摘要会被重置,避免重复输出

压缩管道的详细说明请参阅 压缩

事件流

当前支持的事件流类型:

  • lifecycle:生命周期事件,由 subscribeEmbeddedPiSession 发出(agentCommand 作为后备)
  • assistant:助手增量,来自 pi-agent-core 的流式输出
  • tool:工具事件,来自 pi-agent-core 的流式输出

聊天通道处理

对于聊天通道(如 Slack、Discord 等):

  • 助手增量会被缓冲成聊天 delta 消息
  • 在生命周期结束/错误时,发出聊天 final 消息

超时设置

不同场景有不同的超时配置:

  • agent.wait 默认 30 秒(仅影响等待行为)。可通过 timeoutMs 参数覆盖。
  • 智能体运行时默认 600 秒,通过 agents.defaults.timeoutSeconds 配置,在 runEmbeddedPiAgent 的中止计时器中强制执行。

可能提前终止的情况

以下情况可能导致循环提前结束:

  • 智能体超时:运行时间超过限制,被中止
  • AbortSignal:外部取消信号
  • 网关断开或 RPC 超时:网络或服务问题
  • agent.wait 超时:仅影响等待,不会停止智能体运行

智能体运行时系统提示