【實戰教學】雙代理流水線完整實作 — 從零到一走過實作、審查、測試的 AI 協作開發

上一篇我們解析了《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 記錄

八、結論:雙代理模式的價值

這次實驗驗證了報告的核心主張:

  1. Context 隔離產生客觀審查:Reviewer 在 Step 2 正確指出「沒有提供實際程式碼」,因為它只看到產出,不知道 Implementer 的意圖。這就是為什麼雙代理比單一代理更可靠。
  2. 自我修正能力:即使 Step 1 失敗(產出方案而非程式碼),Step 2 的審查 + Step 3 的修正組成了自動修復迴圈。最終在 Step 3 產出了合格的程式碼。
  3. 護欄(Guardrails)是必需品:5 次失敗中有 4 次是因為代理行為不可控。--disable-slash-commands--allowedTools ""cwd=tempdir 這些護欄不是可選的,是必須的。
  4. 人類仍然不可或缺:最後一個浮點精度問題,代理嘗試了 3 輪都無法自動修復(因為問題在測試而非實作)。人類介入 10 秒就解決了。這正是報告說的:「AI 是協作者,不是替代者」。

最後的建議:不要追求完美的自動化。從「一個寫、一個審」的最小雙代理開始,逐步增加複雜度。今天就試試。

本文是《2026 Agentic Coding Trends Report》深度解析系列的第二篇。

留言

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *