OpenClaw 源码解析(六):openclaw agent 如何触发一次 Agent 运行?

发布时间:2026/5/25 14:19:07

OpenClaw 源码解析(六):openclaw agent 如何触发一次 Agent 运行? 1. 本期要解决的问题前几期我们已经从项目整体结构、CLI 命令体系、配置加载、Gateway 运行机制等角度理解了 OpenClaw 的基础框架。到了这一期可以进一步进入 OpenClaw 最核心的使用动作用户在终端中执行一条openclaw agent --message ...命令后系统内部究竟发生了什么从官方文档看openclaw agent的定位非常明确它用于通过 Gateway 运行一次 agent turn同时也可以通过--local参数强制走本地嵌入式执行路径命令需要至少提供一个会话选择器例如--to、--session-key、--session-id或--agent。(OpenClaw)也就是说openclaw agent并不是一个简单的“大模型问答命令”它本质上是一个带有会话路由、Agent 选择、模型覆盖、回复投递和容错回退能力的任务调度入口。2. 命令入口agent是核心 CLI 命令之一在 CLI 命令描述文件中agent被注册为一个核心命令其说明是 “Run one agent turn via the Gateway”即通过 Gateway 运行一次 Agent 回合。这个定义说明默认情况下 OpenClaw 倾向于让 Agent 请求经过 Gateway而不是直接在当前 CLI 进程里裸跑模型调用。(GitHub)可以把它理解为用户输入命令 ↓ openclaw agent ↓ 构造一次 Agent 请求 ↓ 优先交给 Gateway 执行 ↓ 得到回复后输出到终端或投递到指定聊天渠道这种设计的好处是CLI 不需要自己承担全部运行状态。Gateway 可以统一管理会话、通道、插件、模型、工具、消息投递和长期运行状态。3. 第一层校验消息和目标会话必须存在agent-via-gateway.ts中的agentViaGatewayCommand首先会取出用户传入的message并进行空值校验。如果用户没有传入消息体源码会直接抛出错误提示使用openclaw agent --message ... --agent id或者使用已有会话参数。(GitHub)紧接着它还会检查目标会话是否明确。源码要求用户至少提供--to、--session-id、--agent或--session-key中的一种否则系统不知道这次消息应该发给哪个 Agent 或哪个会话。(GitHub)这一步可以概括为message 为空 → 报错 没有任何会话选择器 → 报错 agent id 不存在 → 报错这个设计很关键。因为 OpenClaw 支持多个 Agent也支持把不同聊天渠道映射到不同会话。如果没有明确的目标选择规则系统就无法判断这次 Agent turn 应该继承哪段上下文也无法判断后续回复应该投递到哪里。4. 第二层准备解析 sessionKey、timeout、model override通过基础校验之后源码会继续解析运行参数。它会根据配置和用户传入的agentId、to、sessionId、sessionKey等信息解析出最终使用的sessionKey。同时它还会解析超时时间、消息渠道、幂等 key以及可选的模型覆盖参数--model。(GitHub)这一段代码的核心作用不是“调用模型”而是把用户输入的 CLI 参数转换为一次标准化的 Agent 运行请求。可以理解为用户参数 ↓ 规范化 agentId ↓ 检查 agent 是否存在 ↓ 解析 sessionKey ↓ 解析 timeout ↓ 解析 model override ↓ 生成 idempotencyKey其中idempotencyKey很值得注意。它用于标识一次请求避免同一个请求在 Gateway 中被重复执行。源码中还专门处理了in_flight状态如果相同 run 已经在执行中CLI 会提示当前 Agent run 已经在进行而不是再启动一个重复任务。(GitHub)5. Gateway 路径真正向 Gateway 发起agent调用参数准备完成后OpenClaw 会通过callGateway向 Gateway 发起请求。这里的请求方法名是agent请求参数包括message、agentId、model、to、sessionId、sessionKey、thinking、deliver、channel、replyChannel、timeout、lane和idempotencyKey等。(GitHub)从这一点可以看出openclaw agent命令发出的不是一个简单文本请求而是一个完整的 Agent 执行请求包。这个请求包同时携带了要说什么message 由谁执行agentId 使用哪个上下文sessionKey / sessionId 是否覆盖模型model 是否投递回复deliver 投递到哪里channel / replyChannel / replyTo 如何控制运行timeout / thinking / lane 如何避免重复idempotencyKey因此Gateway 不是被动转发文本而是承担了 Agent 运行控制中心的角色。6. 输出处理JSON 输出与普通文本输出分开Gateway 返回结果后CLI 会根据用户是否传入--json选择不同输出方式。如果是 JSON 模式源码会把 Gateway 响应写成结构化 JSON如果不是 JSON 模式则会提取payloads逐个格式化后输出到终端。(GitHub)这说明 OpenClaw 同时面向两类使用方式人直接在终端使用 → 输出可读文本 脚本或自动化系统调用 → 输出可解析 JSON这一点对于 CLI 工具非常重要。人类用户需要清晰的终端反馈而自动化脚本需要稳定的结构化返回值。7. 本地路径与回退路径为什么有--local官方文档说明Gateway 模式失败时会回退到 embedded agent而--local可以直接强制使用嵌入式执行同时--local仍会预加载插件注册表以便插件提供的 provider、tool 和 channel 在本地运行中仍然可用。(OpenClaw)源码中的agentCliCommand也体现了这个分支逻辑如果用户设置了--local系统会直接调用agentCommand如果没有设置--local则优先尝试agentViaGatewayCommandWithTransientRetries也就是 Gateway 路径。(GitHub)可以概括成openclaw agent ↓ 是否 --local ├─ 是直接 agentCommand 本地执行 └─ 否优先 Gateway 执行 ↓ Gateway 失败或超时 ├─ 是embedded fallback └─ 否返回 Gateway 结果这一设计增强了可用性。Gateway 正常时系统走统一服务路径Gateway 不可用或超时时CLI 仍然有机会在当前进程中完成一次嵌入式 Agent 执行。8. 嵌入式执行内部agentCommand做了什么当系统进入本地执行或 embedded fallback 时会调用agentCommand相关逻辑。agent-command.ts中的prepareAgentCommandExecution会再次检查消息体和会话选择器并解析配置、Agent、会话、工作区、模型上下文等运行信息。(GitHub)随后系统会解析 session得到sessionId、sessionKey、会话存储、是否新会话、持久化 thinking / verbose 设置等信息还会解析 Agent 所属工作目录、Agent 目录以及模型 manifest 上下文。(GitHub)进入真正执行阶段后源码会调用acpManager.runTurn并监听运行过程中的事件。对于text_delta事件系统会把模型输出的增量文本累积起来再通过运行时事件发送出去。(GitHub)执行结束后源码会整理最终文本持久化 transcript并调用投递逻辑deliverAgentCommandResult处理最终输出或消息发送。(GitHub)因此嵌入式执行链路可以写成agentCommand ↓ prepareAgentCommandExecution ↓ 解析会话、Agent、工作区、模型上下文 ↓ 准备 skills snapshot ↓ acpManager.runTurn ↓ 接收 text_delta / done 等事件 ↓ 累积最终回复 ↓ 保存 transcript ↓ 输出或投递结果9. 整体流程图用户执行 openclaw agent --agent ops --message Summarize logs ↓ agentCliCommand ↓ 规范化参数、校验 sessionKey、生成 runId ↓ 判断是否 --local ↓ ┌─────────────────────────────┐ │ Gateway 优先路径 │ │ agentViaGatewayCommand │ └─────────────────────────────┘ ↓ 校验 message / session selector / agentId ↓ 解析 sessionKey / timeout / model override ↓ callGateway({ method: agent, params: ... }) ↓ Gateway 执行 Agent turn ↓ 返回 response ↓ JSON 输出或 payload 文本输出 ↓ 如果 Gateway 失败或超时 ┌─────────────────────────────┐ │ embedded fallback │ │ agentCommand │ └─────────────────────────────┘ ↓ 解析配置、会话、Agent、工作区、模型、技能 ↓ acpManager.runTurn ↓ 保存 transcript ↓ 返回或投递结果10. 本期小结这一期我们重点分析了openclaw agent命令的执行链路。它表面上只是一个发送消息的 CLI 命令但源码中实际包含了完整的 Agent 运行调度逻辑。它的核心设计可以总结为三点第一openclaw agent是一次会话化 Agent turn不是简单的大模型 completion。系统会通过sessionKey、sessionId、agentId等信息明确上下文归属。第二OpenClaw 采用Gateway-first的执行策略。正常情况下CLI 把请求交给 Gateway由 Gateway 统一处理 Agent、模型、工具、通道和消息投递。第三OpenClaw 设计了embedded fallback机制。当 Gateway 路径失败或超时时CLI 可以回退到本地嵌入式执行从而提高命令可用性。理解了这一期之后我们就能更清楚地看出 OpenClaw 的核心思想它不是把 LLM 调用简单包装成 CLI而是围绕“多 Agent、多会话、多通道、可回退执行”构建了一套完整的 Agent 运行基础设施。

相关新闻