OpenClaw 除錯
本地測試、即時模型、提供者、程式碼模式、工具搜尋、Crabbox、CI 之間的行為各有不同:在猜測之前先取得除錯訊號。
優先閱讀
docs/logging.md:日誌檔案、openclaw logs、針對性的除錯旗標。docs/reference/test.md:本地測試命令。docs/tools/code-mode.md:程式碼模式的執行/等待與工具目錄規則。$openclaw-testing:測試通道選擇。$crabbox:廣泛的、Docker、套件、Linux、即時金鑰、CI 一致性的驗證。
預設循環
- 陳述可疑的邊界:設定、工具建構、提供者負載、擷取、串流/SSE、逐字稿重播、工作執行個體/執行環境、套件/發行、CI。
- 新增/啟用最能證明該邊界的窄化訊號。
- 使用相同的提供者/模型/設定重現。除非模型本身即為測試變數,否則絕不隨意切換模型。
- 比較設定的狀態與實際的執行啟動狀態。
- 修補根本原因。
- 重新執行確切失敗的探測;僅在合約要求時才擴大範圍。
模型傳輸日誌
模型請求形狀/串流計時:使用針對性的環境旗標而非全域除錯:
OPENCLAW_DEBUG_MODEL_TRANSPORT=1 openclaw gateway
OPENCLAW_DEBUG_MODEL_PAYLOAD=tools OPENCLAW_DEBUG_SSE=events openclaw gateway
OPENCLAW_DEBUG_MODEL_PAYLOAD=full-redacted OPENCLAW_DEBUG_SSE=peek openclaw gateway
有用的旗標:
OPENCLAW_DEBUG_MODEL_TRANSPORT=1:請求開始、擷取回應、SDK 標頭、第一個 SSE 事件、串流完成、傳輸錯誤,記錄於info層級。OPENCLAW_DEBUG_MODEL_PAYLOAD=summary:節制的負載摘要。OPENCLAW_DEBUG_MODEL_PAYLOAD=tools:所有對模型暴露的工具名稱。OPENCLAW_DEBUG_MODEL_PAYLOAD=full-redacted:上限設定且經編輯的 JSON 負載。僅在除錯時使用;提示/訊息文字仍可能出現。OPENCLAW_DEBUG_SSE=events:第一個事件 + 串流完成計時。OPENCLAW_DEBUG_SSE=peek:前五個經編輯的 SSE 事件。OPENCLAW_DEBUG_CODE_MODE=1:程式碼模式工具表面診斷。
監看日誌:
openclaw logs --follow
常見邊界
- 設定 vs 啟動:已啟用的設定可能與已停用的執行工具、原始執行、空的允許列表、遺失的模型工具支援共存。在強制實施提供者負載不變量之前,請先檢查實際可見的工具。
- 工具表面:檢查最終對模型可見的工具名稱,而不僅僅是註冊表/設定。程式碼模式 = 在實際啟動後才確實只有
exec+wait。 - 提供者負載:在 SDK 呼叫之前,記錄欄位、模型 ID、服務層級、推理設定、輸入大小、中繼資料鍵、提示快取鍵是否存在、工具名稱。
- 擷取 vs SSE:擷取回應證明 HTTP 標頭已到達;第一個 SSE 事件證明提供者主體進度。此處的差距 = 串流/主體/提供者問題,而非工具執行問題。
- 工作執行個體/發行:涉及工作執行個體、動態匯入、套件匯出、延遲執行環境邊界、已發佈的路徑 →
pnpm build。 - 即時金鑰:遺失的提供者金鑰 → 在聲稱即時驗證受阻之前,先設定好秘密的工作流程。環境檢查僅檢查存在性;絕不列印秘密。
擷取對話與逐字稿
聊天對話錯誤報告:擷取實際的逐字稿、發送者歸屬、附件作為證據。
先使用 CLI(需要已設定的安裝;對即時閘道安全):
openclaw sessions list --agent <agentId> --json
openclaw sessions tail
openclaw sessions export-trajectory
文件:儲存佈局 docs/reference/database-schemas.md;CLI https://docs.openclaw.ai/cli/sessions。
原始儲存:當 CLI 無法使用(例如透過 SSH 連線的遠端主機)或需要事件層級的細節時:
- 每個代理的資料平面:
~/.openclaw/agents/<agentId>/agent/openclaw-agent.sqlite。 標準綱要:src/state/openclaw-agent-schema.sql。 - 託管/systemd 狀態:服務使用者的家目錄(例如
/home/openclaw/.openclaw/...), 而非 root 的家目錄。Root 可能擁有獨立的、遺留的安裝,並帶有不同的代理。 預期的代理目錄遺失:使用以下指令定位真實資料庫find / -maxdepth 6 -name openclaw-agent.sqlite。 - 網頁聊天 URL 的 session-id 片段:
/chat/<agentId>/<slug>-<hex>。 在session_nodes中解析:session_key LIKE '%<hex>%'→current_session_id、display_name。金鑰形狀:agent:<agentId>:<surface>:<uuid>;子代理對話使用 surfacesubagent。 - 逐字稿:
transcript_events(session_id、seq、event_json)。event_json.message:role(user/assistant/toolResult)+content(字串或類型為text/toolCall/image的部分)。 - 發送者來源:真實使用者訊息帶有
message.__openclaw(senderId、senderName、senderIsOwner);執行環境合成的輸入則沒有。 使用此欄位區分操作者撰寫的文字與注入的提示。 - 全文逐字稿搜尋:
session_transcript_fts。 - 附件:
media://inbound/<file>URL →<state-dir>/media/inbound/<file>。 - 使用者附加的圖片 ≠
image內容部分。訊息信封攜帶message.__openclaw.media[]條目:url(media://inbound/<file>)、contentType、kind、fileName。僅提取部分的提取器會遺漏每張圖片; 在原始event_json中搜尋media://。遠端主機:使用 scp 將檔案下載到本地 (每個 scp 參數一個遠端路徑);在本地讀取。
沒有 sqlite3 二進位檔的主機仍有 Node:node:sqlite 不需要任何相依性。
node -e 'const {DatabaseSync}=require("node:sqlite");
const db=new DatabaseSync(process.argv[1],{readOnly:true});
console.log(JSON.stringify(db.prepare(
"SELECT seq,event_json FROM transcript_events WHERE session_id=? ORDER BY seq"
).all(process.argv[2])))' <db-path> <session-id>
- 永遠以
readOnly: true開啟即時儲存;切勿寫入正在執行的閘道狀態 (rootAGENTS.md驗證規則)。 - 使用真實資料進行工作:先將資料庫複製到開發狀態目錄。
程式碼指標
- 模型負載 + Responses 串流:
src/agents/openai-transport-stream.ts - 受保護的擷取/計時:
src/agents/provider-transport-fetch.ts - OpenAI/Codex 提供者包裝器:
src/llm/providers/stream-wrappers/openai.ts - 工具建構、工具搜尋、程式碼模式啟動:
src/agents/embedded-agent-runner/run/attempt.ts - 程式碼模式執行環境和工作執行個體:
src/agents/code-mode.tssrc/agents/code-mode.worker.ts - 工具搜尋目錄:
src/agents/tool-search.ts
驗證路徑選擇
- 單一輔助工具/負載錯誤:本地針對性 Vitest。
- 僅文件/日誌:
pnpm check:docs+git diff --check。 - 工作執行個體/發行/延遲匯入/套件表面:針對性測試 +
pnpm build。 - 即時提供者/模型行為:相同的提供者/模型、除錯旗標、若有則使用真實金鑰。
- Docker/套件/Linux/CI 一致性:若當前專用的 Linux 工作執行個體能勝任則使用;
否則使用
$crabbox。 - CI 失敗:確切的 SHA,僅相關的任務;僅在失敗/完成後查看日誌。
輸出習慣
報告:
- 已測試的邊界
- 確切的命令/環境形狀(已編輯)
- 觀察到的訊號,例如工具名稱或第一個 SSE 事件計時
- 修復位置
- 窄化驗證 + 剩餘風險