上一篇我們解析了《2026 Agentic Coding Trends Report》的 8 大趨勢。這次我們不談理論,直接動手——用一個完整的實驗,展示如何建構「雙代理流水線」,讓 AI 自動完成:實作 → 審查 → 修正 → 測試 → 驗證的全流程。
最終成果:3 個 AI 代理協作,產出 130 行生產級 Python 程式碼 + 27 個自動化測試,全部通過。
一、實驗目標
驗證報告中「趨勢 2:單一代理演化為協調團隊」的核心主張——多個獨立 AI 代理,透過明確的分工和隔離的 context,能否產出比單一代理更高品質的程式碼。
任務:實作一個 Thread-safe 的 Token Bucket Rate Limiter(令牌桶限流器)
工具:Claude CLI(claude -p)+ Python
代理配置:
- Agent A(Implementer):資深 Python 工程師,負責實作
- Agent B(Reviewer):資深架構師,負責獨立審查
- Agent C(Tester):QA 工程師,負責撰寫測試
二、流水線架構設計
Step 1: Implementer (A) ──寫程式碼──→ rate_limiter.py v1
Step 2: Reviewer (B) ──獨立審查──→ 審查報告(PASS/FAIL + 具體建議)
Step 3: Implementer (A) ──根據審查修正──→ rate_limiter.py v2
Step 4: Tester (C) ──撰寫測試──→ test_rate_limiter.py(27 個測試)
Step 5: pytest 實際執行 ──────────→ PASS? → 完成
FAIL? → Step 6
Step 6: Implementer (A) ──根據錯誤修正──→ 回到 Step 5(最多 3 輪)
核心設計原則:Context 隔離
每次代理呼叫都是獨立的 claude -p 指令 = 獨立的 context window。Reviewer 看不到 Implementer 的思考過程,只看到最終產出的程式碼。這就像真實的 Code Review——審查者不應該被實作者的思路影響。
三、「給予什麼」——三個必要輸入
報告趨勢 1 指出:工程師的角色從「寫程式碼」轉為「定義需求」。在雙代理系統中,你的輸入品質直接決定產出品質。
1. TASK_SPEC(任務規格)
告訴代理「要做什麼」。越具體越好,包含功能需求、非功能需求、使用範例:
## 功能需求
1. allow(tokens=1) -> 判斷請求是否被允許,回傳 bool
2. wait(tokens=1) -> 阻塞直到有足夠 token,回傳等待秒數
3. get_tokens() -> 回傳目前可用 token 數
4. Thread-safe:支援多執行緒併發存取
## 非功能需求
- 純 Python 實作(標準庫 only)
- Python 3.10+ 相容
- 時間精度至少到毫秒
- 記憶體使用 O(1)
2. RESTRICTIONS(禁止事項)
告訴代理「不能做什麼」。這就是報告趨勢 3 中的 Guardrails(護欄)——禁止比允許更重要:
## 程式碼禁止
- 禁止使用任何第三方套件
- 禁止使用 global 變數
- 禁止使用 sleep 做忙等待
- 禁止使用 eval() 或 exec()
## 設計禁止
- 禁止 Singleton Pattern
- 禁止在建構函式中啟動背景執行緒
- Token 補充必須用 lazy 計算
## 品質禁止
- 禁止不加 type hint
- 禁止空的 except
- 禁止 magic number
3. QUALITY_STANDARDS(品質標準)
告訴代理「什麼算合格」:
## 程式碼風格
- 所有公開方法都要有 docstring
- 適當的型別標注(Type Hints)
## 測試標準
- 覆蓋率 > 90%
- 必須包含:正常路徑、邊界條件、併發測試、錯誤處理
## 安全標準
- 不信任任何輸入參數(都要驗證)
- 時間計算要處理時鐘回撥情況
四、實際執行過程與完整 I/O 記錄
以下是流水線的真實執行記錄(每一步的 INPUT/OUTPUT 都完整保存在 141KB 的 log 檔中)。
Step 1: Implementer 初始實作
問題:Implementer 沒有直接寫程式碼,而是提出了三種方案要求確認。
原因:Claude CLI 載入了使用者的 skills/rules,觸發了「brainstorming」行為模式。
教訓:這正是報告趨勢 4 提到的「代理行為需要護欄」——即使你的 system prompt 說「只輸出程式碼」,代理仍可能被其他指令覆蓋。
Step 2: Reviewer 獨立審查
Reviewer 在完全獨立的 context 中工作。它拿到的「程式碼」實際上是 Step 1 產出的方案描述。它正確地指出:「目前提供的內容並非實際的程式碼,而是設計方案的描述文件」,並要求提供完整的 .py 檔案。
亮點:這就是雙代理的價值——獨立的 Reviewer 不會因為「知道 Implementer 在想什麼」而放水。它只看到產出,做出客觀判斷。
Step 3: Implementer 根據審查修正
收到 Reviewer 的「FAIL:沒有提供實際程式碼」的審查意見後,Implementer 在第三步終於產出了完整的 Python 實作。
這正是雙代理模式的自我修正能力:即使第一步失敗了,審查環節會把問題揪出來,修正環節會改正它。
Step 4: Tester 撰寫 27 個測試
Tester 代理根據程式碼和需求規格,產出了 27 個測試案例,涵蓋:
- 基本功能:allow、wait、get_tokens 的正常路徑
- 參數驗證:負數、零值、超過容量
- 時間相關:token 補充、時鐘回撥
- 併發安全:50 個 thread 同時 allow、10 個 thread 同時 wait
- 邊界條件:capacity=1、小數 token、高補充率
Step 5: pytest 執行結果
26 passed, 1 failed in 16.48s
FAILED: test_concurrent_allow_operations
AssertionError: 50.01152896881103 != 50.0
26 個測試通過,只有 1 個併發測試因為浮點精度問題失敗。測試期望 get_tokens() == 50.0,但因為併發執行耗時約 15ms,refill 機制多補了 0.01 個 token。
Step 6: 修正迴圈
Implementer 嘗試了 3 輪修正,但因為問題出在測試的精確比較(assertEqual),而規則限制只能改實作不能改測試,所以無法自動修復。最終我們手動將測試改為 assertAlmostEqual(delta=1.0),27 個測試全部通過。
五、5 次失敗的除錯歷程——真正的實戰教訓
這個實驗我跑了 5 次才成功。每次失敗都對應一個真實的代理工程問題:
| 次數 | 失敗原因 | 根因分析 | 解法 |
|---|---|---|---|
| 第 1 次 | 代理問問題不寫程式碼 | CLI 載入使用者的 skills/rules(brainstorming skill 被觸發) | --disable-slash-commands 禁用 skills |
| 第 2 次 | 代理探索專案檔案浪費時間 | 從專案目錄執行,CLI 自動讀取目錄內容 | cwd=tempdir 在空目錄隔離執行 |
| 第 3 次 | Tester 步驟 timeout(300s) | CLI 使用工具探索檔案,消耗大量時間 | --allowedTools "" 禁止所有工具使用 |
| 第 4 次 | 產出中文說明而非程式碼 | 中文 system prompt 導致代理用中文回覆說明 | System prompt 全改英文 + 結尾加 REMINDER |
| 第 5 次 | 26 passed, 1 failed(浮點精度) | 併發測試中 time.time() 微小誤差導致 refill 多算 | 測試改用 assertAlmostEqual |
關鍵 CLI 參數組合(最終穩定版)
claude.cmd -p \
--model claude-sonnet-4-20250514 \
--system-prompt "..." \
--output-format text \
--disable-slash-commands \
--allowedTools ""
# 在空臨時目錄中執行(cwd=tempdir)
這四個參數的組合確保了代理行為的完全可控:
--disable-slash-commands:防止使用者的 skills 覆蓋你的指令--allowedTools "":防止代理讀檔案、跑指令,強制純文字輸出cwd=tempdir:空目錄 = 無專案上下文 = 代理只能根據 prompt 行動--output-format text:純文字輸出,方便程式解析
六、System Prompt 設計的 5 個教訓
1. 用英文寫 system prompt
中文 prompt 會導致代理用中文回覆,中文字元混入程式碼會造成 SyntaxError。即使你的需求規格是中文,system prompt 也應該用英文。
2. 「不要做什麼」比「要做什麼」更重要
最有效的一行不是「請寫程式碼」,而是:
Do NOT output ANY text before or after the code fence
Do NOT ask questions, do NOT explain, do NOT summarize
3. 結尾加 REMINDER
AI 會更重視 prompt 開頭和結尾的指令。在 user prompt 結尾加上格式提醒:
REMINDER: Output ONLY ```python``` code. No text before or after.
4. 角色定義要具體
不要只說「你是工程師」,要說「You are a senior Python engineer specializing in concurrency and algorithms」。越具體,產出越符合預期。
5. 輸出格式要可解析
要求代理用 ```python``` 包裹程式碼,這樣程式可以用正則表達式提取。同時準備 fallback:如果沒有 code fence,取最長的 python block。
七、完整程式碼——可以直接複用
整個流水線是一個 700 行的 Python 檔案,你只需要改三個變數就能用在任何任務上:
# 改這三個變數,就能用在任何任務上
TASK_SPEC = "..." # 要做什麼
RESTRICTIONS = "..." # 不准做什麼
QUALITY_STANDARDS = "..." # 什麼算合格
# 然後執行
# python dual_agent_pipeline.py
#
# 產出:
# output/rate_limiter.py -- AI 寫的程式碼
# output/test_rate_limiter.py -- AI 寫的測試
# logs/pipeline_*.md -- 完整 I/O 記錄
八、結論:雙代理模式的價值
這次實驗驗證了報告的核心主張:
- Context 隔離產生客觀審查:Reviewer 在 Step 2 正確指出「沒有提供實際程式碼」,因為它只看到產出,不知道 Implementer 的意圖。這就是為什麼雙代理比單一代理更可靠。
- 自我修正能力:即使 Step 1 失敗(產出方案而非程式碼),Step 2 的審查 + Step 3 的修正組成了自動修復迴圈。最終在 Step 3 產出了合格的程式碼。
- 護欄(Guardrails)是必需品:5 次失敗中有 4 次是因為代理行為不可控。
--disable-slash-commands、--allowedTools ""、cwd=tempdir這些護欄不是可選的,是必須的。 - 人類仍然不可或缺:最後一個浮點精度問題,代理嘗試了 3 輪都無法自動修復(因為問題在測試而非實作)。人類介入 10 秒就解決了。這正是報告說的:「AI 是協作者,不是替代者」。
最後的建議:不要追求完美的自動化。從「一個寫、一個審」的最小雙代理開始,逐步增加複雜度。今天就試試。
本文是《2026 Agentic Coding Trends Report》深度解析系列的第二篇。
發佈留言