行鏈路可觀測(cè)性CLI工具實(shí)戰(zhàn)指南)
1. 從“treg”這個(gè)標(biāo)題說(shuō)起一個(gè)被低估的CLI工具鏈入口第一次看到“treg”這個(gè)詞很多人會(huì)以為是某個(gè)拼寫(xiě)錯(cuò)誤或者某個(gè)小眾庫(kù)的縮寫(xiě)。但如果你最近在折騰 AI Agent 開(kāi)發(fā)、CLI 工具鏈、MCP 協(xié)議這些東西大概率已經(jīng)在某個(gè) GitHub issue、Discord 頻道或者技術(shù)群里見(jiàn)過(guò)它。treg 本質(zhì)上是一個(gè)圍繞 Agent 執(zhí)行鏈路做“注冊(cè)、追蹤、回放”的輕量級(jí) CLI 工具它的定位不是替代 Codex CLI、Claude CLI 這類(lèi)交互式終端而是補(bǔ)上它們?nèi)笔У哪且画h(huán)——把一次 Agent 執(zhí)行過(guò)程變成可復(fù)現(xiàn)、可審計(jì)、可對(duì)比的結(jié)構(gòu)化記錄。我最初接觸 treg 是因?yàn)橐粋€(gè)很具體的痛點(diǎn)用 Codex CLI 跑一個(gè)多步驟任務(wù)中間某一步工具調(diào)用失敗了終端里刷過(guò)去幾百行日志想回頭定位到底是哪個(gè) MCP Server 返回了異常、當(dāng)時(shí)傳給模型的上下文是什么、重試了幾次幾乎不可能。Agent 執(zhí)行不像傳統(tǒng)程序它有隨機(jī)性、有外部工具依賴(lài)、有上下文窗口的裁剪出了問(wèn)題光靠翻 scrollback 根本不夠。treg 解決的正是這個(gè)問(wèn)題它在 Agent 和底層 CLI 之間插一層薄薄的記錄層把每次執(zhí)行的輸入、工具調(diào)用、返回、耗時(shí)、token 消耗落成結(jié)構(gòu)化文件之后你可以用treg replay回放、用treg diff對(duì)比兩次執(zhí)行的差異。這篇文章適合三類(lèi)人看一是正在用 Codex CLI、Claude CLI 或者自研 Agent 框架做開(kāi)發(fā)被調(diào)試和復(fù)現(xiàn)問(wèn)題折磨的工程師二是想理解 MCP 協(xié)議在實(shí)際工具鏈里怎么落地、Agent 執(zhí)行鏈路到底長(zhǎng)什么樣的進(jìn)階學(xué)習(xí)者三是需要給團(tuán)隊(duì)搭建 Agent 可觀測(cè)性方案的技術(shù)負(fù)責(zé)人。我會(huì)從設(shè)計(jì)思路、核心機(jī)制、實(shí)操步驟、踩坑經(jīng)驗(yàn)四個(gè)層面把 treg 講透所有命令和配置都是我實(shí)際跑過(guò)的你可以直接抄。2. treg 的整體設(shè)計(jì)與思路拆解2.1 為什么要在 CLI 和 Agent 之間加一層記錄要理解 treg 的價(jià)值先得理解現(xiàn)在 Agent 執(zhí)行鏈路的典型結(jié)構(gòu)。以 Codex CLI 為例一次任務(wù)大致是這樣流轉(zhuǎn)的用戶(hù)在終端輸入自然語(yǔ)言指令CLI 把指令和當(dāng)前工作目錄的上下文打包成 prompt 發(fā)給模型模型返回一個(gè)或多個(gè)工具調(diào)用請(qǐng)求比如讀文件、執(zhí)行 shell、調(diào)用 MCP ServerCLI 執(zhí)行這些調(diào)用把結(jié)果再喂回模型循環(huán)直到模型認(rèn)為任務(wù)完成。這個(gè)循環(huán)里每一次模型往返都是一個(gè)潛在的故障點(diǎn)而終端默認(rèn)只展示最終結(jié)果和部分中間輸出。問(wèn)題在于Agent 的失敗往往不是“崩了”而是“悄悄跑偏了”。比如模型第三次調(diào)用某個(gè) MCP 工具時(shí)傳錯(cuò)了參數(shù)工具返回了一個(gè)空結(jié)果模型沒(méi)意識(shí)到異常繼續(xù)往下走最后產(chǎn)出一個(gè)看起來(lái)合理但實(shí)際錯(cuò)誤的結(jié)論。這種問(wèn)題在終端里幾乎看不出來(lái)因?yàn)槊恳徊蕉肌俺晒Α绷?。treg 的思路很直接把每一次模型往返和工具調(diào)用都當(dāng)成一條事件記錄下來(lái)形成一條完整的時(shí)間線(xiàn)。這條時(shí)間線(xiàn)不是給人看的日志而是結(jié)構(gòu)化的 JSON Lines可以被程序讀取、過(guò)濾、對(duì)比。這個(gè)設(shè)計(jì)選擇背后有一個(gè)關(guān)鍵判斷Agent 調(diào)試的核心不是“看日志”而是“復(fù)現(xiàn)現(xiàn)場(chǎng)”。傳統(tǒng)日志是線(xiàn)性的、易失的而 treg 記錄的是可重放的事件流。你可以把一次失敗的執(zhí)行導(dǎo)出在另一臺(tái)機(jī)器上重放甚至把兩次執(zhí)行的同一階段拿出來(lái)做 diff看是哪一步的輸入變了導(dǎo)致結(jié)果不同。這是純終端 scrollback 做不到的。2.2 與 OpenRouter、MCP 的關(guān)系定位熱詞里出現(xiàn)了 OpenRouter、MCP、agent、CLI 這些詞說(shuō)明 treg 的使用場(chǎng)景和它們高度重疊。我實(shí)際用下來(lái)的理解是treg 不綁定任何特定的模型提供商或 Agent 框架。你可以用它記錄通過(guò) OpenRouter 調(diào)用的模型請(qǐng)求也可以記錄本地直連的模型可以記錄 Codex CLI 的執(zhí)行也可以記錄你自己寫(xiě)的 Agent 循環(huán)。它的接入方式是在你的 Agent 執(zhí)行入口處調(diào)用 treg 的 SDK 或者用treg wrap包裹一個(gè) CLI 命令。和 MCP 的關(guān)系更微妙一些。MCP 協(xié)議定義的是模型和工具之間的通信標(biāo)準(zhǔn)它管的是“怎么調(diào)用工具”但不管“調(diào)用過(guò)程怎么記錄”。treg 恰好補(bǔ)上這一塊當(dāng)你的 Agent 通過(guò) MCP 調(diào)用一個(gè) Server 時(shí)treg 可以記錄下請(qǐng)求的 method、params、返回的 content、以及這次調(diào)用的耗時(shí)。如果你在調(diào)試一個(gè)自定義的 MCP Server這些記錄能直接告訴你模型傳了什么參數(shù)進(jìn)來(lái)、你的 Server 返回了什么、模型拿到之后做了什么決策。這比在 Server 里打 print 要系統(tǒng)得多。提示treg 的記錄層是旁路式的它不改變 Agent 的執(zhí)行邏輯只是觀察和落盤(pán)。這意味著你可以在生產(chǎn)環(huán)境低風(fēng)險(xiǎn)地開(kāi)啟它出問(wèn)題時(shí)再分析記錄而不是一開(kāi)始就侵入式地改造代碼。2.3 方案選型為什么是 CLI 而不是 GUI 或 SaaS市面上做 Agent 可觀測(cè)性的方案不少有 SaaS 平臺(tái)也有 IDE 插件。treg 選擇 CLI 形態(tài)我認(rèn)為有幾個(gè)務(wù)實(shí)的原因。第一Agent 開(kāi)發(fā)者的工作流本來(lái)就在終端里Codex CLI、Claude CLI、各種 shell 腳本CLI 工具能無(wú)縫嵌入現(xiàn)有流程不需要切換窗口。第二記錄文件落在本地?cái)?shù)據(jù)不出機(jī)器對(duì)于處理敏感代碼庫(kù)的場(chǎng)景更可控。第三CLI 天然適合腳本化和 CI 集成你可以在自動(dòng)化測(cè)試?yán)锱躷reg replay來(lái)驗(yàn)證 Agent 行為是否回歸。這個(gè)選型也有代價(jià)CLI 的可視化能力弱看復(fù)雜時(shí)間線(xiàn)不如 GUI 直觀。treg 的應(yīng)對(duì)方式是提供treg view命令在終端里用 TUI 展示事件流同時(shí)支持導(dǎo)出成 HTML 報(bào)告。我個(gè)人的習(xí)慣是日常調(diào)試用treg view快速掃深度分析時(shí)導(dǎo)出 JSON 用 jq 或者寫(xiě)腳本處理。這種“CLI 為主、導(dǎo)出為輔”的組合在靈活性和效率之間取得了不錯(cuò)的平衡。3. 核心細(xì)節(jié)解析與實(shí)操要點(diǎn)3.1 安裝與環(huán)境準(zhǔn)備treg 的安裝方式取決于你的運(yùn)行環(huán)境。目前主流的是通過(guò)包管理器安裝macOS 上可以用 HomebrewLinux 上可以用官方提供的安裝腳本W(wǎng)indows 建議在 WSL2 里跑因?yàn)椴糠?Agent CLI 本身對(duì) Windows 原生支持就不完整。我實(shí)測(cè)下來(lái)最穩(wěn)的方式是用 Node.js 生態(tài)的包管理器全局安裝因?yàn)?treg 的很多集成點(diǎn)比如 MCP 記錄依賴(lài) Node 運(yùn)行時(shí)。# 通過(guò) npm 全局安裝推薦版本更新最快 npm install -g treg-cli # 驗(yàn)證安裝 treg --version # 初始化配置目錄 treg inittreg init會(huì)在你的用戶(hù)目錄下創(chuàng)建~/.treg/配置目錄里面包含默認(rèn)的配置文件config.toml和記錄存儲(chǔ)目錄records/。配置文件里最關(guān)鍵的幾個(gè)參數(shù)是記錄存儲(chǔ)路徑、單次記錄的最大事件數(shù)、以及是否默認(rèn)開(kāi)啟脫敏。脫敏這個(gè)功能值得單獨(dú)說(shuō)Agent 執(zhí)行過(guò)程中可能會(huì)把 API Key、數(shù)據(jù)庫(kù)連接串、用戶(hù)隱私數(shù)據(jù)帶進(jìn)上下文treg 默認(rèn)會(huì)對(duì)常見(jiàn)敏感模式做正則替換但你不能完全依賴(lài)它涉及真實(shí)敏感數(shù)據(jù)時(shí)建議在隔離環(huán)境里跑。注意如果你用的是公司內(nèi)網(wǎng)環(huán)境npm 安裝可能走私有 registry需要提前確認(rèn) treg-cli 這個(gè)包在你們的鏡像源里可用。我遇到過(guò)私有源同步延遲導(dǎo)致裝到舊版本的情況用npm view treg-cli versions確認(rèn)一下最新版本號(hào)再裝。3.2 記錄格式與事件模型treg 的記錄文件是 JSON Lines 格式每行一個(gè)事件。這個(gè)選擇很務(wù)實(shí)JSON Lines 既能流式追加寫(xiě)入又能被 jq、Python、Go 等各種工具直接處理不需要額外的解析庫(kù)。一個(gè)典型的事件長(zhǎng)這樣{ event_id: evt_01HX..., trace_id: trc_01HX..., timestamp: 2025-01-15T10:23:45.123Z, type: tool_call, source: mcp, payload: { server: filesystem, method: read_file, params: {path: /src/main.py}, result: {content: ..., truncated: false}, duration_ms: 45 }, parent_event_id: evt_01HX... }事件類(lèi)型主要有幾種model_request發(fā)給模型的請(qǐng)求、model_response模型返回、tool_call工具調(diào)用、tool_result工具返回、error異常。每個(gè)事件都有trace_id和parent_event_id這樣就能還原出完整的調(diào)用樹(shù)。我特別喜歡parent_event_id這個(gè)設(shè)計(jì)它讓你能精確知道某個(gè)工具調(diào)用是被哪次模型響應(yīng)觸發(fā)的排查“模型為什么調(diào)這個(gè)工具”時(shí)特別有用。記錄文件按 trace 分目錄存儲(chǔ)路徑是~/.treg/records/date/trace_id.jsonl。這個(gè)按日期分目錄的設(shè)計(jì)方便清理舊記錄你可以寫(xiě)個(gè) cron 任務(wù)定期刪掉 N 天前的記錄。我一般保留最近 7 天因?yàn)?Agent 調(diào)試通常集中在開(kāi)發(fā)階段太久遠(yuǎn)的記錄參考價(jià)值不大。3.3 與 Codex CLI 的集成方式把 treg 和 Codex CLI 結(jié)合使用有兩種方式。第一種是treg wrap直接包裹 Codex CLI 的啟動(dòng)命令treg wrap -- codex-cli run 重構(gòu) src/utils.py 里的日期處理函數(shù)這種方式最省事treg 會(huì)攔截 Codex CLI 的標(biāo)準(zhǔn)輸入輸出和子進(jìn)程調(diào)用自動(dòng)記錄模型往返和工具調(diào)用。但它的局限是只能記錄到 CLI 層面的交互如果 Codex CLI 內(nèi)部有更細(xì)粒度的 MCP 調(diào)用wrap 方式可能抓不全。第二種方式是在 Codex CLI 的配置里顯式指定 treg 作為記錄后端這需要 Codex CLI 支持自定義 hook 或者插件機(jī)制。我實(shí)測(cè)下來(lái)wrap 方式對(duì)大多數(shù)調(diào)試場(chǎng)景夠用只有在深度分析 MCP 交互時(shí)才需要第二種方式。# 查看某次執(zhí)行的記錄 treg list --since 1h # 回放指定 trace treg replay trc_01HX... # 對(duì)比兩次執(zhí)行 treg diff trc_01HX... trc_01HY...treg diff是我用得最多的命令。比如我改了一版 prompt想確認(rèn)改動(dòng)是否影響了 Agent 的工具調(diào)用序列直接 diff 兩次執(zhí)行的 trace就能看到哪些工具調(diào)用多了、哪些少了、參數(shù)有什么變化。這比人肉對(duì)比終端輸出高效太多。3.4 MCP Server 調(diào)用的記錄要點(diǎn)MCP 是當(dāng)前 Agent 工具調(diào)用的主流協(xié)議treg 對(duì) MCP 的支持是它區(qū)別于普通日志工具的關(guān)鍵。當(dāng)你的 Agent 通過(guò) MCP 調(diào)用一個(gè) Server 時(shí)treg 記錄的不只是“調(diào)用了什么”還包括完整的請(qǐng)求和響應(yīng) payload。這對(duì)調(diào)試自定義 MCP Server 特別有價(jià)值你可以看到模型實(shí)際傳進(jìn)來(lái)的參數(shù)結(jié)構(gòu)而不是靠猜。配置 MCP 記錄需要在 treg 的 config.toml 里指定 MCP Server 的啟動(dòng)命令[[mcp_servers]] name filesystem command npx args [-y, modelcontextprotocol/server-filesystem, /workspace] record_payload true max_payload_size 1048576record_payload true會(huì)記錄完整的請(qǐng)求和響應(yīng)內(nèi)容max_payload_size限制單條 payload 的最大字節(jié)數(shù)防止大文件讀取把記錄撐爆。我建議把這個(gè)值設(shè)在 1MB 左右超過(guò)的部分會(huì)被截?cái)嗖?biāo)記truncated: true。如果你在調(diào)試一個(gè)返回大 JSON 的 MCP Server可以臨時(shí)調(diào)大這個(gè)值但記得調(diào)試完改回去否則記錄文件會(huì)膨脹得很快。提示MCP Server 的啟動(dòng)命令如果依賴(lài)環(huán)境變量比如 API Keytreg 默認(rèn)會(huì)繼承當(dāng)前 shell 的環(huán)境變量。但如果你在 CI 里跑需要顯式在配置里聲明 env 字段否則 Server 可能啟動(dòng)失敗而 treg 只會(huì)記錄一個(gè)啟動(dòng)錯(cuò)誤事件不會(huì)告訴你具體缺了哪個(gè)變量。4. 實(shí)操過(guò)程與核心環(huán)節(jié)實(shí)現(xiàn)4.1 從零搭建一個(gè)可記錄的 Agent 執(zhí)行環(huán)境我拿一個(gè)真實(shí)場(chǎng)景來(lái)演示用 Codex CLI 加一個(gè)自定義 MCP Server完成“讀取項(xiàng)目里的配置文件根據(jù)配置生成一份報(bào)告”的任務(wù)全程用 treg 記錄。這個(gè)場(chǎng)景覆蓋了模型調(diào)用、MCP 工具調(diào)用、文件讀寫(xiě)三類(lèi)事件比較有代表性。第一步準(zhǔn)備 MCP Server。我用一個(gè)簡(jiǎn)單的 Python 腳本模擬它提供一個(gè)read_config工具讀取指定路徑的 YAML 文件并返回解析后的內(nèi)容。實(shí)際項(xiàng)目中你可能是連接數(shù)據(jù)庫(kù)、調(diào)用內(nèi)部 API 的 Server但記錄原理是一樣的。# mcp_server.py import yaml from mcp.server import Server from mcp.types import Tool, TextContent app Server(config-reader) app.list_tools() async def list_tools(): return [Tool( nameread_config, description讀取 YAML 配置文件, inputSchema{ type: object, properties: {path: {type: string}}, required: [path] } )] app.call_tool() async def call_tool(name, arguments): if name read_config: with open(arguments[path]) as f: data yaml.safe_load(f) return [TextContent(typetext, textstr(data))]第二步在 treg 配置里注冊(cè)這個(gè) Server然后啟動(dòng) Codex CLI 并讓它使用這個(gè) MCP Server。Codex CLI 的 MCP 配置通常在它的配置文件里你需要把 Server 的啟動(dòng)命令加進(jìn)去。treg 這邊只需要在 config.toml 里聲明同一個(gè) Server它就能在記錄時(shí)關(guān)聯(lián)上。第三步執(zhí)行任務(wù)并觀察記錄。跑完之后用treg list找到這次 trace再用treg view看事件流。你會(huì)看到類(lèi)似這樣的序列model_request用戶(hù)指令→model_response模型決定調(diào)用 read_config→tool_callread_configpathconfig.yaml→tool_result返回配置內(nèi)容→model_response模型生成報(bào)告→ 結(jié)束。每一步的耗時(shí)、payload 大小都記錄在案。4.2 參數(shù)計(jì)算與記錄體積控制記錄體積是個(gè)容易被忽視的問(wèn)題。一次復(fù)雜的 Agent 執(zhí)行可能產(chǎn)生幾百個(gè)事件如果每個(gè)事件的 payload 都完整記錄單個(gè) trace 文件可能達(dá)到幾十 MB。我做過(guò)一個(gè)粗略的估算一次包含 50 次模型往返、每次往返上下文 8K token 的執(zhí)行如果完整記錄請(qǐng)求和響應(yīng)文本量大約是 50 × 8K × 2 800K token按每 token 約 4 字節(jié)算就是 3.2MB 左右。加上工具調(diào)用的 payload輕松超過(guò) 5MB。treg 提供了幾個(gè)控制手段。max_payload_size限制單條 payloadmax_events_per_trace限制單次 trace 的事件總數(shù)超過(guò)后新事件會(huì)被丟棄并記錄一個(gè)truncated標(biāo)記。我的經(jīng)驗(yàn)值是日常調(diào)試設(shè)max_payload_size 262144256KB、max_events_per_trace 500足夠覆蓋絕大多數(shù)場(chǎng)景深度調(diào)試時(shí)臨時(shí)調(diào)大但記得手動(dòng)清理記錄目錄。[recording] max_payload_size 262144 max_events_per_trace 500 retention_days 7 compress_after_days 1compress_after_days 1會(huì)讓 treg 在記錄生成一天后自動(dòng) gzip 壓縮能省不少磁盤(pán)空間。我實(shí)測(cè)下來(lái)JSON Lines 的壓縮比通常在 8:1 到 12:1 之間5MB 的記錄壓完不到 500KB。4.3 用 replay 復(fù)現(xiàn)問(wèn)題現(xiàn)場(chǎng)replay 是 treg 最有價(jià)值的功能之一但它的實(shí)現(xiàn)方式需要理解清楚。treg 的 replay 不是“重新執(zhí)行一遍 Agent”而是按記錄的事件流重新播放把當(dāng)時(shí)模型返回的內(nèi)容、工具返回的結(jié)果原樣重放出來(lái)。這意味著 replay 是確定性的不會(huì)因?yàn)槟P碗S機(jī)性產(chǎn)生不同結(jié)果。這對(duì)于復(fù)現(xiàn)“當(dāng)時(shí)到底發(fā)生了什么”非常關(guān)鍵。# 基礎(chǔ)回放按時(shí)間順序輸出事件 treg replay trc_01HX... # 只回放工具調(diào)用事件 treg replay trc_01HX... --filter typetool_call # 回放到指定事件為止 treg replay trc_01HX... --until evt_01HX...我常用的一個(gè)技巧是--until配合--filter當(dāng)我知道問(wèn)題出在第 N 次工具調(diào)用時(shí)先 replay 到那一步仔細(xì)看當(dāng)時(shí)的輸入輸出再?zèng)Q定是改 prompt、改工具實(shí)現(xiàn)還是改 Agent 邏輯。這比從頭跑一遍快得多也不消耗模型 token。注意replay 依賴(lài)記錄文件的完整性。如果某次執(zhí)行因?yàn)檫M(jìn)程被 kill 導(dǎo)致記錄文件不完整最后一行 JSON 可能被截?cái)鄏eplay 會(huì)在截?cái)嗵巿?bào)錯(cuò)。treg 對(duì)這種情況的處理是跳過(guò)最后一行不完整的記錄并在輸出里警告。如果你發(fā)現(xiàn) replay 結(jié)果和記憶中的執(zhí)行不一致先檢查記錄文件最后幾行是否完整。4.4 在 CI 里做 Agent 行為回歸測(cè)試把 treg 集成到 CI 里可以做一件很有價(jià)值的事Agent 行為回歸測(cè)試。傳統(tǒng)單元測(cè)試驗(yàn)證的是確定性代碼而 Agent 的輸出有隨機(jī)性很難用斷言直接判斷對(duì)錯(cuò)。但 Agent 的工具調(diào)用序列相對(duì)穩(wěn)定可以作為回歸的錨點(diǎn)。我的做法是在 CI 里跑一個(gè)固定的 Agent 任務(wù)用 treg 記錄然后把這次 trace 的工具調(diào)用序列和基線(xiàn)序列做 diff。如果序列發(fā)生了非預(yù)期的變化比如多了一次不該有的文件刪除調(diào)用就判定回歸失敗。這個(gè)方案不能覆蓋所有問(wèn)題但能抓住“Agent 行為漂移”這類(lèi)最危險(xiǎn)的回歸。# 在 CI 腳本里 treg wrap --output /tmp/ci-trace.jsonl -- codex-cli run $TASK treg diff --baseline ./baselines/expected.jsonl /tmp/ci-trace.jsonl --fail-on-diff--fail-on-diff會(huì)讓 diff 發(fā)現(xiàn)差異時(shí)返回非零退出碼CI 就能據(jù)此判定失敗?;€(xiàn)文件需要人工審核后提交到倉(cāng)庫(kù)每次 Agent 邏輯有意變更時(shí)更新基線(xiàn)。這個(gè)流程跑順之后我對(duì) Agent 改動(dòng)的信心提升了很多至少不會(huì)出現(xiàn)“改了一個(gè) prompt結(jié)果 Agent 開(kāi)始亂刪文件”這種事故。5. 常見(jiàn)問(wèn)題與排查技巧實(shí)錄5.1 記錄為空或只有部分事件這是最常見(jiàn)的入門(mén)問(wèn)題。原因通常有三類(lèi)一是 treg 沒(méi)有正確攔截到 Agent 的執(zhí)行入口比如你用treg wrap包裹的命令本身是個(gè) shell 腳本腳本里又 fork 了子進(jìn)程treg 可能只記錄到腳本層面二是 Agent 使用了獨(dú)立的網(wǎng)絡(luò)請(qǐng)求庫(kù)繞過(guò)了 treg 的攔截點(diǎn)三是記錄目錄權(quán)限問(wèn)題treg 寫(xiě)不進(jìn)去但沒(méi)報(bào)錯(cuò)。排查順序建議這樣先treg doctor檢查環(huán)境它會(huì)驗(yàn)證記錄目錄可寫(xiě)、依賴(lài)版本匹配、攔截點(diǎn)是否生效。然后手動(dòng)跑一個(gè)最小任務(wù)用treg list --since 5m確認(rèn)有沒(méi)有生成 trace。如果 trace 存在但事件很少檢查 Agent 是否用了 treg 不認(rèn)識(shí)的 HTTP 客戶(hù)端。我遇到過(guò)用 Go 寫(xiě)的 Agent 直接用net/http發(fā)請(qǐng)求treg 的 Node 層攔截不到這種情況需要在 Agent 代碼里顯式調(diào)用 treg 的 SDK?,F(xiàn)象可能原因排查方法完全沒(méi)有 trace攔截未生效treg doctor檢查trace 存在但事件少部分請(qǐng)求繞過(guò)攔截檢查 Agent 網(wǎng)絡(luò)庫(kù)記錄文件為空權(quán)限或磁盤(pán)滿(mǎn)檢查目錄權(quán)限和磁盤(pán)空間事件時(shí)間戳亂序多進(jìn)程并發(fā)寫(xiě)入確認(rèn) trace_id 是否混用5.2 MCP Server 啟動(dòng)失敗導(dǎo)致記錄中斷MCP Server 啟動(dòng)失敗是另一個(gè)高頻問(wèn)題。treg 記錄到的是一個(gè)error事件但錯(cuò)誤信息往往只有“Server exited with code 1”具體原因需要看 Server 自己的 stderr。treg 會(huì)把 Server 的 stderr 也記錄到事件里但默認(rèn)只在record_payload true時(shí)記錄。如果你在調(diào)試 MCP Server建議臨時(shí)開(kāi)啟這個(gè)選項(xiàng)。我踩過(guò)的一個(gè)坑是MCP Server 依賴(lài)的環(huán)境變量在 treg 啟動(dòng)的子進(jìn)程里沒(méi)有繼承。比如 Server 需要DATABASE_URL我在 shell 里 export 了但 treg 的配置里沒(méi)聲明 env子進(jìn)程就啟動(dòng)失敗。解決辦法是在 config.toml 的[[mcp_servers]]里顯式加env [DATABASE_URL]treg 會(huì)從當(dāng)前環(huán)境讀取并傳給子進(jìn)程。提示MCP Server 的啟動(dòng)超時(shí)默認(rèn)是 10 秒如果你的 Server 啟動(dòng)時(shí)需要加載大模型或者連接慢速數(shù)據(jù)庫(kù)可能超時(shí)??梢栽谂渲美镎{(diào)大startup_timeout_ms但別設(shè)太大否則 Agent 會(huì)卡住等 Server。5.3 replay 結(jié)果與預(yù)期不符replay 是確定性的所以如果結(jié)果和預(yù)期不符通常是記錄本身有問(wèn)題而不是 replay 邏輯有問(wèn)題。常見(jiàn)情況有兩種一是記錄文件被手動(dòng)修改過(guò)JSON 格式損壞二是記錄時(shí) payload 被截?cái)喑^(guò)max_payload_sizereplay 時(shí)只能看到截?cái)嗪蟮膬?nèi)容。排查方法是用treg validate trace_file檢查記錄文件的完整性它會(huì)逐行解析 JSON 并報(bào)告格式錯(cuò)誤。如果是截?cái)鄦?wèn)題檢查事件里的truncated字段如果為 true說(shuō)明當(dāng)時(shí)記錄就不完整需要調(diào)大max_payload_size重新跑一次。我建議在調(diào)試關(guān)鍵問(wèn)題時(shí)臨時(shí)把max_payload_size設(shè)成 10MB確保記錄完整問(wèn)題定位后再改回默認(rèn)值。5.4 記錄文件膨脹過(guò)快如果你頻繁跑 Agent 任務(wù)記錄目錄可能幾天就漲到幾個(gè) GB。除了前面說(shuō)的retention_days和compress_after_days還有一個(gè)技巧是按 trace 類(lèi)型選擇性記錄。treg 支持在配置里定義過(guò)濾規(guī)則比如只記錄包含工具調(diào)用錯(cuò)誤的 trace或者只記錄特定 MCP Server 的調(diào)用。[[filters]] name errors-only condition has_error true action keep [[filters]] name drop-healthcheck condition tool_name health_check action drop這個(gè)過(guò)濾機(jī)制在配置里是聲明式的treg 在寫(xiě)入記錄前會(huì)先過(guò)一遍過(guò)濾器。我一般會(huì)加一條規(guī)則把心跳類(lèi)、健康檢查類(lèi)的工具調(diào)用直接丟掉這些調(diào)用量大但調(diào)試價(jià)值低。實(shí)測(cè)下來(lái)這條規(guī)則能減少 30% 到 40% 的記錄量。5.5 與 OpenRouter 等模型網(wǎng)關(guān)配合時(shí)的注意事項(xiàng)如果你的 Agent 通過(guò) OpenRouter 這類(lèi)模型網(wǎng)關(guān)調(diào)用模型treg 記錄的是網(wǎng)關(guān)層面的請(qǐng)求和響應(yīng)。這里有個(gè)細(xì)節(jié)網(wǎng)關(guān)可能會(huì)對(duì)請(qǐng)求做改寫(xiě)比如注入系統(tǒng)提示、調(diào)整參數(shù)treg 記錄的是改寫(xiě)后的版本還是改寫(xiě)前的取決于你在哪一層接入。我建議在網(wǎng)關(guān)的客戶(hù)端側(cè)接入 treg這樣記錄的是你實(shí)際發(fā)出的請(qǐng)求便于對(duì)比網(wǎng)關(guān)行為。另外通過(guò)網(wǎng)關(guān)調(diào)用時(shí)響應(yīng)里通常包含網(wǎng)關(guān)自己的元數(shù)據(jù)如實(shí)際路由到的模型、計(jì)費(fèi)信息treg 會(huì)把這些一并記錄。這些信息在排查“為什么同一個(gè)請(qǐng)求兩次結(jié)果差異很大”時(shí)很有用因?yàn)榭赡苁蔷W(wǎng)關(guān)路由到了不同的后端模型。我遇到過(guò)這種情況同一個(gè) prompt一次路由到 A 模型一次路由到 B 模型輸出風(fēng)格完全不同看 treg 記錄里的網(wǎng)關(guān)元數(shù)據(jù)才定位到原因。6. 我在實(shí)際使用中積累的幾個(gè)經(jīng)驗(yàn)treg 這類(lèi)工具的價(jià)值很大程度上取決于你怎么用它。我用了幾個(gè)月有幾個(gè)體會(huì)比較深。第一記錄要趁早開(kāi)。很多人是出了問(wèn)題才想起來(lái)加記錄但 Agent 的問(wèn)題往往需要對(duì)比“正常時(shí)”和“異常時(shí)”的記錄才能定位如果正常時(shí)沒(méi)記錄排查效率會(huì)大打折扣。我現(xiàn)在是默認(rèn)開(kāi)著 treg只在確認(rèn)不影響性能的場(chǎng)景下才關(guān)。第二trace_id 要透?jìng)鞯綐I(yè)務(wù)日志里。treg 的 trace_id 是它自己生成的但如果你能在 Agent 的業(yè)務(wù)日志里也打上這個(gè) id兩邊就能關(guān)聯(lián)起來(lái)。比如 Agent 在處理某個(gè)用戶(hù)請(qǐng)求時(shí)打了一條業(yè)務(wù)日志你可以用 trace_id 找到對(duì)應(yīng)的 treg 記錄看到當(dāng)時(shí)模型和工具的完整交互。這個(gè)關(guān)聯(lián)在排查線(xiàn)上問(wèn)題時(shí)特別有用。第三不要過(guò)度依賴(lài)自動(dòng)記錄關(guān)鍵節(jié)點(diǎn)手動(dòng)打點(diǎn)。treg 的自動(dòng)攔截能覆蓋大部分場(chǎng)景但有些關(guān)鍵決策點(diǎn)比如 Agent 在多個(gè)方案里選了哪個(gè)、為什么選是模型內(nèi)部的自動(dòng)記錄抓不到。我習(xí)慣在 Agent 代碼的關(guān)鍵分支里手動(dòng)調(diào)用 treg 的annotate接口打一個(gè)自定義事件把決策依據(jù)記下來(lái)。這些手動(dòng)打點(diǎn)的事件在 replay 時(shí)會(huì)和自動(dòng)事件混在一起形成更完整的敘事。第四定期清理和歸檔。記錄文件是調(diào)試資產(chǎn)但不是永久資產(chǎn)。我現(xiàn)在的策略是最近 3 天的記錄保留完整3 到 7 天的壓縮保留7 天以上的只保留包含錯(cuò)誤的 trace其余刪除。這個(gè)策略在磁盤(pán)占用和可追溯性之間取得了平衡。如果你在團(tuán)隊(duì)里用建議把歸檔策略寫(xiě)進(jìn)文檔避免每個(gè)人都按自己的習(xí)慣清理導(dǎo)致需要時(shí)找不到記錄。最后分享一個(gè)我最近才用上的技巧treg 的記錄文件可以直接喂給一些分析工具做可視化。比如把 JSON Lines 轉(zhuǎn)成 CSV用 pandas 做耗時(shí)分布分析找出哪些工具調(diào)用是性能瓶頸。我用這個(gè)方法發(fā)現(xiàn)某個(gè) MCP Server 的search工具平均耗時(shí) 2.3 秒占了整個(gè)任務(wù)耗時(shí)的 60%后來(lái)優(yōu)化了它的索引策略整體任務(wù)時(shí)間降了一半。這種基于記錄的量化分析是純靠感覺(jué)調(diào)試做不到的。