用 AI 寫程式最大的問題是什麼?對我們來說,不是模型不夠聰明,而是不放心。
- LLM token 越來越貴,但大部分都在重複看已經知道的程式碼結構。
- Agent 改完程式編譯不過,要來回好幾輪才修好。
- 工作到一半 context 滿了,重開 session 什麼都不記得了。
- 有時候改壞了檔案還沒人知道。
這些問題大概不是只有我們遇到。我們的做法是寫兩個小工具來補,一個管輸入成本,一個管操作安全。兩者透過 MCP 協定接進 OpenCode,各自只做一件事。
工具一:GraphifyRust — 讓 LLM 不用重看整包程式碼
GraphifyRust 是用 Rust 寫的靜態分析引擎。用 Tree-sitter 解析原始碼,把 function、struct、trait 這些節點抽出來,建成一個有向圖。
AI agent 要改程式時,傳統做法是把整支檔案丟給 LLM。幾百行的檔案可能只有幾段 function 相關,但 LLM 還是得看完所有 import、註解、不相干的邏輯。
Graphify 的 skeleton_extract 只回傳 AST 骨架 — function 名稱、行號、簽名。實際壓縮效果:
server.go:1,289 token → 117 token(省 90.9%)toon.rs:2,132 token → 147 token(省 93.1%)
骨架不夠用時,用 range mode 精準讀取特定 function。不需要整包丟進去。
選 Rust 的理由很務實:Tree-sitter 的 Rust binding 最成熟。在 110 個檔案、422 條邊的測試專案上,建圖只要 16ms,比之前 Python 版快 26 倍。節點用 petgraph arena 預分配,減少 heap 碎片。輸出用自訂的 .toon 格式,體積比 JSON 少 60%。
語意搜尋用本機 Qdrant,沒有雲端費用。目前支援 9 種語言:Rust、Python、Go、JavaScript、TypeScript、C、C++、Java、PHP、Swift。
工具二:StateMachineMcp — 永遠不讓壞掉的程式碼進硬碟
StateMachineMcp 是用 Go 寫的 MCP server,概念上就是一個安全閘門:Agent 想改程式碼,必須先通過狀態機檢查。
Phase Gate
每次任務有四個階段:初始化 → 規劃 → 執行 → 驗證 → 完成。執行階段才能改程式碼,規劃階段呼叫 apply_patch 會被擋掉。連續三次改失敗會自動暫停,等人來看。
Double Buffer + Compiler Verify
機制很簡單但很有效:
- Agent 送出 patch(精準搜尋區塊 + 取代區塊)。
- Patch 先寫到
/tmp/的 staging 副本,原始檔案不動。 - 自動跑
cargo check、tsc --noEmit或go vet。 - 通過才寫進硬碟,建立 checkpoint。
- 失敗就丟掉 staging,原始檔案完好如初。
壞掉的程式碼永遠不會進到檔案系統。聽起來很基本,但沒有這個機制之前,我們被 Agent 改壞過好幾次。
Checkpoint Resume
.opencode/state.json 記錄每次 checkpoint:在哪個階段、改了哪些檔案、compiler 結果。context 滿了要重開 session 時,新 session 載入這個檔案就可以從中斷的地方繼續,不用重跑。
跟 DeepSeek Harness 的關係
後來看到 DeepSeek Harness 的論文,發現他們提出的架構概念跟我們遇到的問題幾乎一樣。DeepSeek Harness 底層用 Cordis 當 plugin 框架 — 模型配接器、工具註冊表、session log、agent loop 全部都是可替換的 plugin。
| Harness 概念 | 我們的解法 |
|-------------|-----------|
| Session Log(事件溯源) | .opencode/state.json checkpoint log |
| Code Mode(批次工具呼叫) | apply_patch + compiler verify |
| Plugin 系統 | MCP 協定 |
| 可觀測性 | skeleton_extract 90%+ token 壓縮 |
我們不是先有架構再寫工具,是先有痛才做工具,然後發現這些工具剛好可以拼成一個架構。
Session Log 與長期記憶
Harness 論文把記憶分成兩層,這個區分我們也是實作後才體會到:
- Session Log:單次任務的執行軌跡。短暫、用完就丟。StateMachineMcp 的
state.json負責。 - Vault Memory:跨 session 的持久知識。專案規則、架構決策、設定值。Magic Context — OpenCode 的 plugin — 負責這個。它可以儲存持久事實(
ctx_memory)、工作筆記(ctx_note)、以及全文搜尋的完整對話歷史(ctx_search),全部跨壓縮、跨重啟存活。
兩者不能互相取代。Session log 讓任務內可恢復,vault memory 讓任務之間有連續性。
實際成本
這組工具跑在一個每月約 $10 的 BytePlus 方案上,加上一台有 GPU 的本機機器做 embedding。成本控制的關鍵:
- 輸入壓縮:Graphify 把 AST token 減少 90%+。
- 本機驗證:StateMachineMcp 攔截編譯錯誤,不用 LLM 來修語法問題。
- Checkpoint resume:從 checkpoint 繼續,不重跑。
$10 是實際月費,不是理論上限。
原始碼
兩套工具都放在 GitHub 上,MIT 授權:
如果這些問題你也有遇到,歡迎拿去用,或給我們 feedback。
留言
張貼留言
回應不用錢,請多多益善!懶得寫字按個讚也是相當感謝!