Agent 迴圈(OpenClaw)

所謂 agentic loop,就是 agent 完整跑一輪的過程:接收訊息 → 組裝上下文 → 模型推論 → 執行工具 → 串流回覆 → 持久化儲存。這條路徑是把一則訊息轉換成實際操作與最終回覆的核心流程,同時確保 session 狀態保持一致。

在 OpenClaw 中,每個 session 一次只會有一個序列化的迴圈在跑,過程中會發出生命週期與串流事件——模型思考、呼叫工具、串流輸出,全都在這裡發生。本文說明這個迴圈從頭到尾是怎麼串起來的。

進入點

  • Gateway RPC:agentagent.wait
  • CLI:agent 指令

運作方式(高層概覽)

  1. agent RPC 驗證參數、解析 session(sessionKey/sessionId)、持久化 session 中繼資料,然後立即回傳 { runId, acceptedAt }
  2. agentCommand 負責執行 agent:
    • 解析模型 + thinking/verbose 預設值
    • 載入 skills 快照
    • 呼叫 runEmbeddedPiAgent(pi-agent-core 執行環境)
    • 如果內嵌迴圈沒有發出生命週期結束/錯誤事件,則由這裡補發
  3. runEmbeddedPiAgent
    • 透過 per-session + 全域佇列序列化執行
    • 解析模型 + 驗證設定檔,建立 pi session
    • 訂閱 pi 事件,串流 assistant/tool 的差量更新
    • 強制逾時 → 超時則中止執行
    • 回傳 payload + 用量中繼資料
  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 為單位序列化(session lane),也可透過全域 lane 控制。
  • 這防止了工具/session 的競態條件,保持 session 歷史記錄的一致性。
  • 通訊頻道可選擇佇列模式(collect/steer/followup),這些模式會餵入 lane 系統。 請參閱 Command Queue

Session 與工作區準備

  • 解析並建立工作區;沙盒模式可能會將工作目錄重新導向到沙盒工作區根目錄。
  • 載入(或重用快照中的)Skills,並注入到環境變數和提示詞中。
  • 解析引導/上下文檔案,注入系統提示詞報告。
  • 取得 session 寫入鎖;在串流開始前開啟並準備好 SessionManager

提示詞組裝與系統提示詞

  • 系統提示詞由 OpenClaw 的基礎提示詞、skills 提示詞、引導上下文、以及 per-run 覆寫組合而成。
  • 會強制套用模型限制和壓縮保留的 token 數量。
  • 參閱 System prompt 瞭解模型實際看到的內容。

Hook 攔截點(你可以介入的地方)

OpenClaw 有兩套 hook 系統:

  • 內部 hook(Gateway hook):透過事件驅動腳本處理指令和生命週期事件。
  • 外掛 hook:在 agent/工具生命週期和 gateway 管線中提供擴充點。

內部 hook(Gateway hook)

  • agent:bootstrap:在建構引導檔案、系統提示詞定稿之前執行。 可用來新增/移除引導上下文檔案。
  • 指令 hook/new/reset/stop 及其他指令事件(請參閱 Hooks 文件)。

請參閱 Hooks 取得設定與範例。

外掛 hook(agent + gateway 生命週期)

這些在 agent 迴圈或 gateway 管線內部執行:

  • before_model_resolve:在 session 之前執行(沒有 messages),可在模型解析前確定性地覆寫 provider/model。
  • before_prompt_build:在 session 載入後執行(有 messages),可注入 prependContextsystemPromptprependSystemContextappendSystemContext。用 prependContext 注入每回合的動態文字,用 system-context 欄位注入應放在系統提示詞空間的穩定指引。
  • before_agent_start:相容性 hook,可能在上述任一階段執行;建議改用上面明確的 hook。
  • agent_end:在完成後檢視最終訊息列表和執行中繼資料。
  • before_compaction / after_compaction:觀察或標註壓縮週期。
  • before_tool_call / after_tool_call:攔截工具參數/結果。
  • tool_result_persist:在工具結果寫入 session 對話記錄之前,同步轉換其內容。
  • message_received / message_sending / message_sent:入站 + 出站訊息 hook。
  • session_start / session_end:session 生命週期邊界。
  • gateway_start / gateway_stop:gateway 生命週期事件。

請參閱 Plugins 瞭解 hook API 與註冊細節。

串流與部分回覆

  • 助理差量從 pi-agent-core 串流傳出,以 assistant 事件發出。
  • 區塊串流可在 text_endmessage_end 時發出部分回覆。
  • 推理串流可以作為獨立串流或區塊回覆發出。
  • 請參閱 Streaming 瞭解分段與區塊回覆行為。

工具執行與訊息工具

  • 工具的 start/update/end 事件在 tool 串流上發出。
  • 工具結果在記錄/發出前會經過大小和圖片 payload 的清理處理。
  • 訊息工具的發送會被追蹤,以抑制重複的助理確認訊息。

回覆整形與抑制

  • 最終 payload 由以下內容組裝:
    • 助理文字(以及可選的推理內容)
    • 行內工具摘要(在 verbose + 允許的條件下)
    • 模型出錯時的助理錯誤文字
  • NO_REPLY 被視為靜默 token,會從出站 payload 中過濾掉。
  • 訊息工具的重複內容會從最終 payload 列表中移除。
  • 如果沒有可渲染的 payload 且某個工具出錯,會發出備用的工具錯誤回覆 (除非訊息工具已經發送了使用者可見的回覆)。

壓縮與重試

  • 自動壓縮會發出 compaction 串流事件,並可能觸發重試。
  • 重試時,記憶體內的緩衝區和工具摘要會被重設,以避免重複輸出。
  • 請參閱 Compaction 瞭解壓縮管線。

事件串流(目前)

  • lifecycle:由 subscribeEmbeddedPiSession 發出(agentCommand 作為備用)
  • assistant:從 pi-agent-core 串流的差量
  • tool:從 pi-agent-core 串流的工具事件

聊天頻道處理

  • 助理差量被緩衝為聊天 delta 訊息。
  • 生命週期結束/錯誤時發出聊天 final

逾時

  • agent.wait 預設:30 秒(僅等待)。可用 timeoutMs 參數覆寫。
  • Agent 執行環境:agents.defaults.timeoutSeconds 預設 600 秒;在 runEmbeddedPiAgent 的中止計時器中強制執行。

可能提前結束的情況

  • Agent 逾時(中止)
  • AbortSignal(取消)
  • Gateway 斷線或 RPC 逾時
  • agent.wait 逾時(僅等待,不會停止 agent)