tiny-agent 從第一性原理打造可靠 Agent

第四部|走向 Production · 第 8 章

測試、Observability 與安全邊界

用 deterministic fixtures 與 run events 提升成功率,同時劃清 MCP、sandbox 與多租戶責任。

約 24 分鐘 8 / 8

這章證明迴圈值得信任——先用測試證明它平常做得對,再用 observability 證明它正在做得對,最後劃清安全邊界,證明「信任」本身有極限。你需要分開評估結果是否正確、過程為何失敗、成本花在哪裡,這三件事各自對應測試與 observability;但無論這三件事看起來多漂亮,都不能取代第三步:它是否越過了授權邊界。

三層測試

層級 驗證對象 是否呼叫真實模型
Unit / contract tools、provider normalization、Session reducer/planner
Conformance / integration 四語言、MCP loopback、CLI behavior
Capability eval Agent 能否完成真實 coding task

一般 CI 必須免費且 deterministic。公開 MCP endpoints 只適合 optional compatibility smoke,不能成為 release gate。

Outcome 是分數,Trace 是解釋

Repo 內最小 eval 會複製 fixture 到 temp workspace,執行四個 CLI,再跑 hidden verifier:

make eval
AGENT=tiny-rs TASK=fix-bug make eval

主要分數只有:

verifier exit 0 → PASS
otherwise       → FAIL

Duration、tokens 與 tool count 獨立報告,不能補償錯誤結果。Agent 少用兩個 tools 卻修錯 bug,不應取得較高分。

Structured Run Events

TypeScript 提供 one-shot machine mode:

tiny-ts --json "調查問題"

stdout 只輸出 JSONL:

{"type":"run.started","sessionId":"...","model":"..."}
{"type":"model.completed","durationMs":1589.31,"usage":{"input":157,"output":31,"cacheRead":1536,"cacheWrite":0,"cacheHitRate":90.72}}
{"type":"tool.started","toolCallId":"call_1","tool":"read"}
{"type":"tool.completed","toolCallId":"call_1","tool":"read","durationMs":12.4,"ok":true}
{"type":"run.completed","result":{"status":"succeeded","answer":"..."}}

Events 預設不含 prompt、tool arguments 與 results,避免 monitoring pipeline 複製企業資料。完整證據仍保存在 job 的 Session;Session 本身不會自動提供 tenant isolation。Go、Python、Rust 目前沒有 --json;不要把 TS reference 能力寫成四語言共有。

觀察 Cache 崩潰

每個 model.completed 記錄當次 request 的 cache hit rate,因此可以看到:

turn 1  91.2%
turn 2  90.8%
turn 3   0.0%  ← prompt prefix改變或cache失效
turn 4  89.7%

Run result 中的 rate 由整個 run 累計 counters 計算。兩種 scope 必須分開,才能最佳化成本而不誤判。

安全邊界:誰信任誰

還記得第 1 章的責任表嗎?這裡把「介面與部署」那一欄攤開,順便把「產生副作用」與「持續與恢復」兩欄裡「不該負責什麼」的部分也交代清楚。

責任 由誰負責 不該負責什麼 08 章對應說明
選擇下一步 Model 直接取得 host credential Model output 視為 untrusted input,不是 trusted code 的一部分
控制迴圈 Agent runtime 理解每個領域的業務規則 Agent implementation 本身是 trusted code,但執行的是 untrusted model 決定的 tool calls
產生副作用 Tool adapter 自行改變授權範圍 MCP 是 Tool adapter,不是 authorization 或 sandbox;--plugin 是 capability selector,不是 tenant ACL
持續與恢復 Session 猜測未記錄的 effect 是否成功 Session 只保存 durable facts;tenant scope 是外層控制器的責任
介面與部署 CLI / trusted host 把 deployment security 假裝成 agent 功能 Tool registration 是 trusted deployment action;多租戶需要 Execution Capsule(見下一節)
圖 7:第 1 章責任表的展開版。這裡的分欄是責任邊界,不是 process 邊界——同一個 CLI process 同時扮演「介面」與「執行 Agent runtime」兩個角色,不代表實際部署會拆成兩個服務。
  • Agent implementation 與 server operator 是 trusted code。
  • Model output、prompt、repository 與 dependency scripts 視為 untrusted。
  • Tool registration 是 trusted deployment action;tool arguments 是 untrusted model input。
  • MCP 是 Tool adapter,不是 authorization 或 sandbox。
  • --plugin 是 capability selector,不是 tenant ACL。

多租戶需要 Execution Capsule

若外部客戶能提供 repository 或 prompt,Fence 或 path check 都不是完整租戶邊界。每個 job 至少需要獨立 container;hostile native code、高敏感資料、GPU 或 nested container 應升級 microVM/VM。部署層還要負責:

  1. CPU、RAM、PID、wall-clock 與 disk/inode limits。
  2. Network egress、SSRF 與 metadata protection。
  3. Tenant-scoped credentials、audit 與 retention。
  4. TERM → grace → KILL 與 descendant cleanup。

這些責任不放進 tiny-agent core。Tiny-agent 保持一般 CLI,由外層 trusted job controller 建立 execution capsule、綁定 tenant identity、配置 credential,並決定 Session 與 artifact 的儲存位置及存取權限。換句話說,Session 只保存 durable facts;tenant scope 是外層控制器的責任。

企業查詢 Tool 的原則

不要提供萬用 internal_search(query) 或讓模型直接寫 SQL。使用少量 typed operations,並讓 trusted context 注入 tenant、actor 與 credential。每筆結果帶 source、observedAt、retrievedAt、partial 與 conflicts,才能組成可審查的 evidence packet。

親手驗證

先跑全部離線 gate,確認測試、MCP loopback、安全界線與教學書都不需要真實 OpenRouter:

make test
make check
make build
npm --prefix book test

接著查看 capability eval 的 verifier,而不是直接花模型額度:

sed -n '1,220p' eval/run.ts
find eval/tasks -name 'verify.mjs' -o -name 'test.sh' | sort

最後做一個安全界線練習:列出哪些資料由 tiny-agent Session 保存,哪些必須由 job controller 提供。至少應把 tenant identity、credential、network egress、CPU/RAM/PID/disk limits 與 retention 放在外層;若答案把它們交給 MCP arguments 或 --plugin,就跨錯邊界了。

  1. 第一部|最小閉環

    無壓力

  2. 第二部|能力邊界

    能力壓力

  3. 第三部|可靠執行

    失敗壓力

  4. 第四部|走向 Production

    觀測與信任壓力・你在這裡

圖 1:全書地圖(收束版)。

一個迴圈 + 一份誠實的帳本——現在你知道帳本怎麼記了。

接下來要寫什麼,見 首頁的既有規劃