BridgeCraft logobridgecraft
週報作品集關於聯絡登入
聯絡

bridgecraft

從資料視覺化到 AI Agent,一直在找下一個 meta

文章主題指南週報Labs作品集系統架構關於聯絡RSS

© 2026 BridgeCraft — Waiting7777. All rights reserved.

← 所有文章

讓 Agent 教 Agent:我的 QA Pipeline 怎麼做跨 Session 自我進化

2026年10月20日 · Waiting7777 · 7 分鐘閱讀

AI Agents自動化測試Claude
📂 AI Agents 系列📂 自動化測試 系列📂 Claude 系列

這是 QA Pipeline 系列的第 3 篇。前兩篇講了 整條 pipeline 的結構 跟 為什麼 SSOT 是 spec 不是 test。這一篇講整個系統最有趣的一層 — 讓 agent 跨 session 累積知識。

講真的,大多數 multi-agent 系統的最大弱點就在這:每次 session 從零開始。修好的 bug、踩過的坑、debug 兩小時才通的 edge case — 下次 session 完全不記得。結果系統的「集體 IQ」= 單一 agent 的 IQ。

這篇講我怎麼解。


一個真實事故

2026-04-10 的 night shift,qa-fixer 接到一個 issue:設定頁的「修改密碼」按下去,密碼不夠強時後端會回 HTTP 422。前端原本把 error.response.data.detail 當 string 顯示在 toast — 但 FastAPI 在 validation 失敗時回的 detail 是 array of { loc, msg, type, ... }。結果 toast 顯示了 [object Object]。

Fixer 改了 useChangePassword.ts、加上 typeof detail === 'string' ? detail : Array.isArray(detail) && ... ? detail[0].msg : fallback 的處理、發 PR、merge。

故事結束?以「傳統 agent demo」來說是。但這裡有個問題:一樣的錯誤格式在 useLogin、useUpdateProfile、還有其他十幾個 hook 裡都會發生。除非剛好踩到 test、讓 E2E 失敗、讓 analyzer 報進 Linear,否則它們會繼續埋著,在 production 出現「顯示 [object Object]」這種丟臉訊息。

人類 engineer 碰到這個案例,第一個反應通常是「啊這個要全域搜一下」。但 agent 沒這個本能 — 除非你把它寫進系統設計。

跨 Session 的資料結構:.learned-patterns.json

我在 reports/.learned-patterns.json 留一個跨 session memory 檔。以 FastAPI 422 那條 pattern 為例,實際內容:

{
  "name": "FastAPI 422 array detail — propagation to all hooks",
  "trigger": "any hook that calls err.response.data?.detail without handling array format from FastAPI",
  "fix": "apply useChangePassword.ts pattern: typeof detail === 'string' ? detail : Array.isArray(detail) && detail.length > 0 && typeof detail[0]?.msg === 'string' ? detail[0].msg : fallback",
  "learned_from": "code-bug::useLogin::fastapi-422-array-detail",
  "date": "2026-04-11",
  "files_affected": [
    "src/features/auth/hooks/useLogin.ts",
    "src/features/settings/hooks/useUpdateProfile.ts"
  ],
  "applied_count": 3,
  "graduated": true,
  "graduated_date": "2026-04-16",
  "graduated_to": ".claude/skills/api-patterns.md"
}

五個欄位是整個系統的靈魂:

  • trigger — 什麼條件下 planner 要去掃
  • fix — 發現時要怎麼處理(給 fixer 的 playbook)
  • applied_count — 被自動套用了幾次
  • graduated — 是不是已經從「熱區記憶」畢業成永久 skill
  • graduated_to — 畢業後的落腳處(例:.claude/skills/api-patterns.md)

注意 graduated 這個欄位。它是我後來才想到的,但現在整個系統最重要的設計之一。下面會講。

Feedback loop 怎麼串

以 FastAPI 422 那個 case 為例,實際跑了這幾步:

Day 1(2026-04-10)— 初次發現

qa-fixer 修完 useChangePassword.ts 後多做了一件事:問自己「這個 bug 的 root cause 有沒有通用性?」FastAPI validation response 格式不是一次性 bug,是一個 class of bug。於是寫了 Pattern #1 進 .learned-patterns.json,applied_count: 1。

Day 2(2026-04-11)— Planner 主動擴散

隔天早上 AM shift,qa-planner 開始跑。除了讀 spec,它也讀 .learned-patterns.json(對 planner 來說是 optional input,有才讀)。看到 Pattern #1 的 trigger 是「任何 hook 處理 FastAPI 422」、files_affected 只列了一個檔,於是 planner 把這條規則加進 test plan:

Requirement: 所有呼叫 FastAPI endpoint 的 hook 都必須正確處理 detail 為 array 的情況。

Analyzer 拿到這個 requirement 去掃所有 hook、發現 useLogin.ts 跟 useUpdateProfile.ts 都有相同問題、開了新 Linear issue。Fixer 把兩個檔案一起修、發了 PR,commit message:fix(auth,settings): extract FastAPI array detail in 422 handlers。

applied_count 從 1 升到 3。同一天 fixer 把 Pattern #1 升級成 Pattern #2(加上 propagation trigger、更精確的 fix playbook) — 寫 learned-patterns 的是 fixer,不是 reporter,職責切得很乾淨。

Day 6(2026-04-16)— 畢業

applied_count 累積到 3、且這條 pattern 的 fix PR 沒被任何 revert 碰過 — 觸發 graduation 條件。週末跑的 qa-weekly agent 把這條 pattern graduated = true、寫進 .claude/skills/api-patterns.md、從熱區記憶裡拿掉。

之後 planner 每次 session 不用再掃這條 rule。但這個知識沒有消失 — 它現在是每個 agent 開啟時預載的 skill 之一,像內建 lint rule 一樣。

為什麼「畢業」很重要

我 skeleton 裡原本把這一層叫「auto-pruning」,但跑過兩週後發現「畢業(graduation)」才是正確的語彙。差別在:

  • Pruning 暗示「丟掉」— 但這些 knowledge 我不想丟
  • Graduation 暗示「升級成更穩定的 context」— planner 不用每次重掃,但 fixer 寫新 code 時還是會讀到

實際上 .claude/skills/ 裡現在有兩個畢業去處:

  • api-patterns.md — 跟後端溝通的通用規則(422 處理、error shape、auth header…)
  • e2e-testing.md — Playwright 專屬陷阱(Worktree .env.development、browser cache、route mocking…)

這就是為什麼我的熱區 pattern 不會無限成長 — applied_count ≥ 3 且 fix 沒被 revert 就觸發 graduation、從熱區搬到永久 skill。兩週下來 9 條 pattern,4 條已經畢業,佔 44%。

兩週 9 條 pattern 的完整清單

為了不讓讀者覺得只有 FastAPI 這一個 case,以下是 .learned-patterns.json 目前的全部 9 條(applied_count 排序):

PatternTrigger 本質AppliedGraduated
Worktree 缺 .env.development 導致 module-level throwgit worktree 設定漏檔4✅ → e2e-testing.md
Playwright browser cache invalidation版本升級後 browser 遺失4✅ → e2e-testing.md
FastAPI 422 array detail propagation後端錯誤格式3✅ → api-patterns.md
測試 helper goToStepN() 自己該 mock API多步流程 flaky 根因3✅ → e2e-testing.md
StoreTable dual-table strict modePlaywright locator 歧義2還差 1 次套用
Playwright clock + useEffect([countdown])fake timer 語意陷阱2還差 1 次套用
process.env vs import.meta.env in Playwright mockstest runtime 環境差異2還差 1 次套用
FastAPI 422 array detail(初版)(已被 propagation 版取代)1—
Playwright clock fastForward loading-state checkN-1ms 同步問題1還差 2 次套用

22 個總 application 次數 — 等於這 9 條 pattern 裡每一條、平均替人類省下 2.4 次 find-and-replace 級別的手動作業。4 條畢業成 skill — 代表這些知識已經從「熱區試誤」變成「系統預設」。

為什麼這不是 RAG

有人看到「跨 session memory」會直覺聯想到 RAG(retrieval-augmented generation)。不是。

差別在:

  • RAG 是「塞 context 進 prompt 讓 LLM 用」— 仰賴 LLM 自己判斷相關性、容易漏
  • Learned-patterns 是「deterministic 的掃描規則,planner 主動 grep / AST 掃描」— 結果可預期、可複現

舉個極端對比。如果是 RAG:

planner 拿到 80 條 pattern embedding,對每個檔案做 cosine similarity,top-K 拿進 prompt,LLM 自行判斷要不要 flag。

這條路有兩個漏洞:embedding 的相似度跟「這個 pattern 適用於這個檔」是兩回事;LLM 拿到一堆 context 還是有機會判錯。

我的作法:

planner 讀 pattern #2,看到 trigger 是「任何呼叫 FastAPI err.response.data?.detail 的 hook」。planner 直接 bash grep + AST 掃描所有 src/**/hooks/**/*.ts,找出符合 trigger 的檔案,加進 spec requirement 交給 analyzer。

沒有 similarity、沒有「LLM 自行判斷」。規則是明確的、掃描是 deterministic 的、結果可重現。LLM 只在「發現時要怎麼修」這一步才出場。

這個取捨在多數 agent 系統裡被搞反。

這個模式能抽出來嗎

可以。這其實是一個通用的「三段式自進化」結構:

  1. Discover(發現)— agent 修完一個問題後主動抽象出 pattern(由 fixer 寫入 .learned-patterns.json)
  2. Propagate(擴散)— 下一 session 由 planner 把 pattern 當 requirement 擴散到整個 repo
  3. Graduate(畢業)— applied_count ≥ 3 且 fix 沒被 revert 過,weekly agent 把 pattern 升級成永久 skill

對應還有一個 Demote(降級)機制:如果一條已畢業的 pattern 後來被發現 regression、週 agent 會把 graduated 改回 false、從 skill 檔移除 — 避免壞知識永久污染系統。

我打算把這套抽成 claude-qa-pipeline 的 OSS 版(前置作業已經在 ~/Project/claude-qa-pipeline)。Core 部分跟 QA 解耦 — 你可以用它做 security review pattern、performance review pattern、accessibility review pattern。

對 multi-agent 系統設計的一個 takeaway

把這篇整理成一句話:

跨 session memory 是把「單 agent 的 IQ」乘法成「系統級智慧」的關鍵。沒有這一層,你的 multi-agent 系統不是系統,是一堆獨立 agent。

這也是為什麼我對「agent 框架之爭」沒什麼興趣。LangGraph vs Claude SDK vs CrewAI 是 node / edge / tool 層的選擇。真正決定系統好不好用的不是框架,是你有沒有設計跨 session 的 memory 跟 feedback loop。

下一篇 #4 會講完全相反的另一面 — 這個系統怎麼跑在一台 MacBook 上、不用 cloud、兩個班次、launchd 排程、lock 管理、Slack 通知。Infra 要簡單,agent 才能複雜。


如果你也在做 multi-agent 系統,我特別想聽到:你是怎麼處理跨 session memory 的? RAG?JSON 檔?SQLite?human-curated skill library?Twitter @waiting7777 聊聊。

每週一篇 — 技術趨勢背後的商業邏輯

分享:

Waiting7777

WoW Arena 冠軍轉前端,用電競 meta 思維拆解技術趨勢。

關於作者

相關文章

Orca 七個月拿下 10 萬顆星:我拆了它的 GitHub 數據,看到 agent 開發真正的瓶頸AI Agents開發者工具+1

Orca 七個月拿下 10 萬顆星:我拆了它的 GitHub 數據,看到 agent 開發真正的瓶頸

一個由 agent 寫出來、拿來管 agent 的開源 IDE。19,000 個 commit、979 次 release 背後,最值得看的數字是 2,525 個放了一個月還沒人處理的 PR。

2026年10月20日 · Waiting7777 · 7 分鐘閱讀

繼續閱讀 →
跑了兩週 Agent QA Pipeline — 真實數字、踩到的坑、重來我會怎麼做AI Agents自動化測試+1

跑了兩週 Agent QA Pipeline — 真實數字、踩到的坑、重來我會怎麼做

這是 post-mortem,不是 case study。做對的三件事、做錯的三件事、以及為什麼這套東西接下來要抽成 `claude-qa-pipeline` OSS。

2026年10月20日 · Waiting7777 · 6 分鐘閱讀

繼續閱讀 →
你的 100% Coverage 是假的 — 用 test-audit 抓出沒被真正測到的分支自動化測試開發者工具

你的 100% Coverage 是假的 — 用 test-audit 抓出沒被真正測到的分支

AI 寫的 code 跑出漂亮的覆蓋率數字,但 error path 根本沒人測過,這工具專門抓這個。

2026年10月20日 · Waiting7777 · 3 分鐘閱讀

繼續閱讀 →

這篇文章對你有幫助嗎?

每週一篇 — 技術趨勢背後的商業邏輯

AI 產業在變什麼、工程師該注意什麼——拆清楚寄到你的信箱。