Files
openclaw-notes/agent-loop.md
T

3.2 KiB
Raw Blame History

OpenClaw Agent Loop

本文基于 2026.6.2 版本源码,关键文件: packages/agent-core/src/agent-loop.tspackages/agent-core/src/types.ts


是什么

Agent loop 是 OpenClaw 的核心驱动引擎,控制一次 agent 运行的完整生命周期。

一次用户请求进来后,不是只请求一次 LLM 就结束——模型可能要多次调用工具、每次看完工具结果再继续思考,直到给出最终答复。Agent loop 就是控制这个"请求 → 工具执行 → 再请求"反复循环的引擎。

两个入口:

  • agentLoop(prompts, context, config) — 带新消息启动,返回 EventStream
  • agentLoopContinue(context, config) — 从现有 context 继续(用于重试)

两者都是异步流,调用方通过监听 AgentEvent 来驱动 UI 更新。


双重循环结构(runLoop

外层 while(true)
│   等待 steering 消息(用户在 agent 工作时插入的消息)
│   没有新消息且无 tool call → 检查 getFollowUpMessages()
│   还是空 → 退出
│
└── 内层 while(hasMoreToolCalls || pendingMessages.length > 0)
        ① 注入 pending steering 消息
        ② streamAssistantResponse()  —— 一次 LLM 流式请求
        ③ 检测 toolCall 块
        ④ executeToolCalls()         —— 执行这批 tool,结果写回 transcript
        ⑤ prepareNextTurn()          —— 可替换下一轮的 model/context
        ⑥ shouldStopAfterTurn()      —— 可优雅退出

三个核心输入

输入 类型 说明
AgentContext 当前状态 systemPrompt + messages(完整 transcript+ 可用 tools
AgentLoopConfig 行为配置 model、各种 hook、转换函数
AgentMessage[] 新消息 这轮用户输入

AgentLoopConfig 关键 hook

hook 作用
convertToLlm AgentMessage[] → LLM Message[](必填,过滤 UI-only 消息)
transformContext 发给 LLM 前压缩/裁剪 context window
beforeToolCall 可拦截 tool 执行(返回 { block: true }
afterToolCall 可修改 tool result,或设 stopAfterBatch 终止本批
resolveDeferredTool 动态加载初始列表之外的 tool
getSteeringMessages 每轮工具执行完后注入的插队消息
getFollowUpMessages agent 即将退出时追加的后续消息
prepareNextTurn 每轮结束后替换 model 或 context
shouldStopAfterTurn 优雅退出(如 context 快满时)

AgentEvent 事件序列

调用方(UI、channel、测试)订阅事件流来渲染界面或做断言,不需要关心内部循环细节。

agent_start
  turn_start
    message_start  (user)
    message_end    (user)
    message_start  (assistant, 流式开始)
      message_update × N  (流式 delta)
    message_end    (assistant)
    tool_execution_start
      tool_execution_update × N  (进度回调)
    tool_execution_end
    message_start  (toolResult)
    message_end    (toolResult)
  turn_end
  turn_start       ← 有 tool call 时进入下一轮
  ...
agent_end

tool call 的具体执行流程见 function-call-flow.md