用四種語言寫一個 AI Coding Agent:loop 很簡單,難的是其他所有事
這篇主要想介紹一下 tiny-agent,順便講講做的過程學到什麼
它是用 TypeScript、Go、Python、Rust 各寫一次的最小 AI coding agent,另外整理成一本繁體中文的教學書:tiny-agent Book
為什麼要做
每天都在用 Claude Code、pi 這些 coding agent,用久了會好奇它到底怎麼動的
看別人的原始碼很快就會迷路,功能太多,分不清哪些是核心、哪些是產品包裝
所以我想自己從零寫一個,只留下一個 coding agent 真的需要的東西
一個語言寫完覺得還不夠,想知道哪些設計是跟語言無關的,就乾脆四個都寫了 XD
agent loop 其實很短
很多人以為 agent 很神秘,其實核心就是一個 while loop
送 messages 給模型→ 模型回文字:結束→ 模型要呼叫 tool:執行 tool,把結果塞回 messages,再送一次tool 也只有四個:bash、read、write、edit
這樣就能讀 code、改 code、跑測試了
第一版 TypeScript 的 loop 加 tool 一天就寫完了
難的是其他所有事
真正花時間的是 loop 以外的東西,這也是書裡大部分篇幅在講的
session 要撐得過 crash
agent 跑到一半被 kill 掉,重開之後要能回答:prompt 送出去了嗎?tool 開始執行了嗎?它的副作用可能已經發生了嗎?可以安全重跑嗎?
我最後的做法是先寫 intent、再做 effect,所有事情都 append 到一個 JSONL,resume 的時候從這些紀錄重建狀態(session design)
取消不能留爛攤子
使用者按 Esc 的時候,正在跑的 bash 要連同整個 process group 一起停掉,session 也要記得這次是被中斷的,不能留一個寫到一半的紀錄
context 會爆
對話一長就要 compaction,把舊的內容交給模型摘要,只保留最近幾輪
切點要對齊完整的 turn,不能把 tool call 跟它的結果拆開
這部分我順便比較了 pi、Claude Code、Codex CLI、Gemini CLI 各自怎麼做(compaction comparison),差異比想像中大
tool 輸出要有上限
一個 cat 大檔案就能把 context 塞滿,所以 bash 輸出超過 2,000 行或 50 KB 只回傳尾巴,完整內容寫到檔案;超過 10 MB 直接把 process 停掉
四個語言怎麼保持一致
這是我覺得最有收穫的部分
以 TypeScript 當 reference,其他三個語言要做出「看起來一模一樣」的行為
光靠人眼對照一定會漂掉,所以我把行為寫成共用的 contract 檔,四個語言的測試都跑同一份
例如 bash tool 的 timeout、失敗、截斷、取消,行為對照表上每一格都是「同左」
MCP 一開始有些語言是手寫 protocol,後來全部改回各語言官方的 MCP SDK,自己只保留 allowlist、timeout、結果大小限制這些 policy
p.s. 程式碼行數大概是 Python 3 千多行、TypeScript 5 千、Go 6 千、Rust 1 萬,不是因為 Rust 比較難寫,是它要自己處理的東西真的比較多
用 eval 選模型,不要憑感覺
tiny-agent 透過 OpenRouter 打模型,預設用哪個模型我是跑 eval 決定的(eval history)
每個 task 有固定的 fixture 跟隱藏的 verifier,120 秒內通過才算數
同一個 task 對每個候選模型各跑 10 次
| 模型 | 通過 | 中位數時間 | 中位數 token |
|---|---|---|---|
openai/gpt-5.6-luna | 10/10 | 21.0s | 2,712 |
deepseek/deepseek-v4-flash-0731 | 10/10 | 29.5s | 8,395 |
z-ai/glm-5.3-flash | 10/10 | 60.6s | 3,754 |
qwen/qwen3.8-flash | 7/10 | 67.0s | 6,958 |
DeepSeek 第一次寫出正確答案其實最快,但時間忽快忽慢,還遇過 timeout
Luna 不是最快寫對的,但最穩、最省 token,寫對之後也最快收尾,所以選它當預設
這只是在我的 task 上的結果,不代表哪個模型比較聰明,provider 的狀況也會變
這本書
書是寫給有資料結構、作業系統基礎的資工大三以上學生,從 token、message、context 講起,一路到 tool、skills、durable session、recovery、cancellation、compaction、測試跟 tracing
- 模型、Token 與 Context
- 從 LLM 到 Agent
- 訊息、Transcript 與 Provider Adapter
- Tool 是 Agent 的手
- Context、AGENTS.md 與 Skills
- Durable Session:先記 Intent,再做 Effect
- Reducer、Planner 與 Recovery
- Cancellation 與 Durable Compaction
- 測試、Observability 與安全邊界
- Committed Lifecycle 與 Phoenix Tracing
很多設計是受 pi 啟發的,它的 agent loop、tool 模型、skills 漸進載入都很精簡,很推薦去看原始碼
tiny-agent 不是 pi 的 fork,session 跟 recovery 那塊是自己發展出來的
心得
- agent loop 一天就寫得出來,能不能拿來每天用,差在 session、取消、compaction、輸出限制這些地方
- 多語言實作一定要有共用的 contract 測試,不然一定會漂
- 選模型要跑 eval,而且要看穩定度跟 token,不能只看「有沒有寫對」
有興趣的話可以直接 clone 下來玩,四個版本都能 make install