跳到主要內容
maxstudioNews
教學DEV Community (Claude Code)約 8 分鐘

解析 Claude Code 與 Codex 工作日誌:四大常見陷阱

這篇文章探討了在解析 Claude Code 和 Codex 等 AI 代理的工作日誌時遇到的技術挑戰。作者分享了他在開發桌面應用程式 Refmade 過程中,發現的四大常見陷阱。這些陷阱揭示了讀取這些內部日誌檔案時,可能與直覺不符的行為。

解析 Claude Code 與 Codex 工作日誌:四大常見陷阱
圖片來源:DEV Community (Claude Code)

Claude Code 在互動請求完成時,會將 "turn_duration" 行寫入工作日誌,但 "claude -p" 則不會。這是我在 2026 年 9 月 27 日(Claude Code 2.1.283 版本)實際測量真實日誌時發現的四大差異之一。

這篇文章是上一篇技術文章的後續,當時我決定 Refmade(我獨立開發的桌面應用程式,能將你的 AI 工作階段繪製成辦公室情境)應該讀取本地日誌,而不是信任代理的報告。Refmade 是一個獨立的應用程式,與 Anthropic 或 OpenAI 並無關聯。

Claude Code 和 Codex 代理在我指示下編寫了大部分的日誌讀取器,而以下規則也根據我自己的真實日誌進行了調整。這些是內部日誌格式,版本更新可能會改變,因此任何規則都可能失效。

對於 Claude Code,一個主要的工作階段是一個類似 "~/.claude/projects/<project>/<session>.jsonl" 的檔案。子代理則位於 "<session>/subagents/" 下,每個子代理都是一個 "agent-<id>.jsonl" 檔案,旁邊還有一個小型的 "agent-<id>.meta.json" 檔案。

這個 meta 檔案包含代理類型、一行描述、"parentAgentId"、"workflowPhase" 以及它是否為分支。工作流程運行會為每次運行新增一個 "journal.jsonl"。

Codex 則將 "rollout-*.jsonl" 寫入其自己的工作階段資料夾下,其子代理透過 "parent_thread_id" 指向父代理。日誌讀取器會從上次讀取停止的位置開始追蹤每個檔案,只讀取完整的行,並在解析之前透過位元組針(byte needles)選擇行。一個包含工具結果的龐大使用者行佔了大部分日誌內容,因此從不進行解析,只會擷取其時間戳和 "tool_use_id"。

提示詞、回答、工具參數和路徑會在記憶體中供規則檢查,但不會保留。保留的資訊包括:時間、每個工具名稱的動作、代理類型和單行標籤、工作階段標題和資料夾名稱,以及結尾描述的一句話結果,所有這些都僅限於本地頁面。

陷阱一:大多數「使用者」行並非請求

一個請求始於使用者記錄,但工具結果也是使用者記錄,壓縮摘要、任務通知、中斷標記以及 "! shell" 命令的輸出也都是。

我最終採用的起始規則是:不是 meta 資訊、不是側鏈、不是工具結果、不是自動壓縮寫入的摘要,並且不以一小段前綴列表開頭(例如 "<task-notification"、"<local-command"、"<system-reminder"、"[Request interrupted" 等)。

斜線命令和 "!" 命令會被暫停,直到助理回答。像 "/model" 這樣的本地命令永遠不會得到回答,因此它永遠不會成為請求。普通的輸入提示詞不會被暫停:在真實日誌中,第一個回答平均在 7 秒後才到達,這段時間太長,不能讓辦公室處於盲區。

當沒有請求開啟時,背景任務完成會啟動一個自動回合。團隊會顯示為正在工作,但這個回合沒有編號,也沒有卡片,因為我沒有要求它。

陷阱二:分支從其父級的歷史記錄開始

一個分支的對話記錄會以其父級對話的副本開始。如果天真地讀取它,分支會看起來像執行了其父級所做的所有事情,而且時間戳也與父級相同。

meta 檔案中包含產生該分支的呼叫的 "toolUseId",因此讀取器會在副本中尋找該呼叫,並從該呼叫之後開始計數。

```javascript

// 程式碼片段: cli/lib/office/claude-source.mjs

const needle = Buffer . from ( "id":" ${ agent . forkTool } " );

let found = false ;

scanFdLines ( fd , [ needle ], () => { found = true ; }, { start : 0 , completeOnly : true });

agent . copying = found ? needle : null ;

```

這個檢查只有在產生呼叫確實存在時才會跳過,因為沒有副本的分支沒有什麼需要跳過。如果沒有這個機制,團隊成員會被重複計算。

陷阱三:請求在哪裡結束?

以下是規則的順序,從最可靠到最不可靠:

| 工作階段類型 | 請求如何結束 |

|---|---|

| 互動式 | 下一個系統 "turn_duration" 行。如果沒有,則為 "[Request interrupted" 標記。如果再沒有,則使用下一個請求開始前的最後一個回答。 |

| "claude -p" (入口點 "sdk-cli") | 沒有 "turn_duration",只有在使用者有 Stop hooks 時才有 Stop-hook 摘要。因此:領導者最終的助理記錄 ("end_turn",沒有工具呼叫) 或成功的 "StructuredOutput" 結果。這是暫定的,因為後續的領導者記錄會重新開啟請求。 |

| 無法結束 | 閒置 30 分鐘後關閉,如果領導者最後的動作是提問,則為 6 小時。 |

"claude -p" 分支的存在是因為,如果沒有它,一次性運行將會一直保持開啟狀態,直到 30 分鐘的閒置規則將它們關閉。

Schema 運行在成功的 "StructuredOutput" 呼叫時結束,工作流程代理也以相同方式結束。這就是為什麼結束是暫定的:一個阻塞的 Stop hook,或 "StructuredOutput" 提醒,可能會讓回合繼續,而一個在預期結束之後的記錄會重新開啟請求。

子代理有自己的規則。一個代理在助理停止時結束,或在成功的 "StructuredOutput" 結果時結束。如果 10 分鐘內沒有記錄,則其最後一條記錄就是其結束。在停止後超過 30 秒的記錄被視為新的訪問,一個新的辦公室代理,因此閒置間隔從不被繪製為工作。

拒絕的呼叫是小問題。當我在批准卡上拒絕一個工具呼叫時,CLI 會將我的拒絕寫入為錯誤結果。讀取器會立即結束該呼叫的動作,而不是顯示「正在編輯檔案」,直到下一條記錄出現。

陷阱四:工作流程日誌沒有時鐘

工作流程運行的 "journal.jsonl" 檔案中有以 "{"type":"launched""、"started"、"result" 或 "failed" 開頭的行。只有 "launched" 和 "started" 會被解析。

"result" 行包含代理的整個輸出,因此只會擷取其開頭的 "agentId",作為代理完成的訊號。日誌中沒有時間戳。

運行開始於日誌檔案的建立時間(在 macOS 和 Windows 上是真實時間)或其第一個代理的開始時間,取兩者中較早者。當運行結束時,工作階段資料夾中的 "workflows/<runId>.json" 檔案會提供名稱、階段標題和持續時間。

在運行期間,預期的名稱和階段來自主要對話記錄中工作流程呼叫的 "export const meta = {...}" 字面量,它會在前 16 KB 內掃描,並最多讀取 4 KB。腳本不會被保留。

僅從工具名稱判斷的九種工作類型

每個觀察到的步驟都會根據工具名稱,被歸類為九種動作之一。

| 動作 | Claude Code 工具 (範例) |

|---|---|

| 讀取 (read) | Read, Grep, Glob, Skill, ToolSearch |

| 寫入 (write) | Edit, Write, MultiEdit, design 和 media-generator MCP 工具 |

| 運行 (run) | Bash, Monitor, 任何未知工具 |

| 網路 (web) | WebSearch, WebFetch, 瀏覽器和電腦控制 |

| 委派 (delegate) | Agent, Task, Workflow |

| 對話 (talk) | SendMessage |

| 提問 (ask) | AskUserQuestion |

| 規劃 (plan) | TaskCreate, TodoWrite, plan 模式 |

| 思考 (think) | 無工具,僅文字 |

未知工具會退回到「運行」。Codex 工具會映射到另一個表格中的相同九種動作,而 "exec" 呼叫則根據其輸入中找到的已知工具識別碼進行分類,該識別碼會在前 64 KB 中搜尋,但不會儲存。

它哪裡出錯了?

一個完成的請求不等於一個成功的請求。辦公室應用程式只會在 Claude Code 結束其回合時繪製一張卡片,僅此而已。處於「提問」狀態的團隊僅表示領導者最後的動作是提問。應用程式的任務列表會用簡單的文字說明同樣的事情,就像下方等待我回答的示範任務一樣。

應用程式任務列表中的示範資料。韓文顯示「正在等待回答」和「Codex 正在等待我的回答」;步驟條是「環顧四周 > 建立和修復 > 正在等待我的回答 > 完成」。任務「分類客戶詢問回覆」是虛構的。

每個完成的請求也會得到一個「一句話結果」,取自領導者最後的回答,並且只顯示在這台電腦的頁面上。只有當回答是韓文時才會保留;否則頁面會自行編寫句子。AI 生成的識別碼有時會洩漏到該句子中。

而且,"claude -p" 或 Codex "exec" 運行足夠短,以至於辦公室應用程式之後會將其顯示為「休息中的團隊」。

下一篇文章將涵蓋建置過程:一份合約文件、五個並行建置器和一個整合器。應用程式連結將在系列文章的最後一篇中提供。

如果你自己解析這些檔案,你會先遇到哪一個陷阱?你是否發現了第五個我應該處理的陷阱?

Share

覺得值得一看?分享給朋友。

以上為 AI 自動翻譯導讀。原文版權歸 DEV Community (Claude Code) 所有, 建議透過「閱讀原文」前往原始網站,以取得最完整資訊並支持原作者。

Newsletter

不用每天追,AI 重點每週寄給你

43 個來源、每 2 小時更新,太多看不完。電子報每週挑最值得看的幾則,附上 Max 的看法。

每週一封。Email 只用來寄電子報,每封信都能一鍵退訂。