Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Don't write the architecture only in the prompt.

Avatar for Neo Hsu Neo Hsu
October 29, 2026

Don't write the architecture only in the prompt.

Avatar for Neo Hsu

Neo Hsu

October 29, 2026

More Decks by Neo Hsu

Other Decks in Technology

Transcript

  1. PLA TFO RM EN GINEER ING DAY · 2026-10-29 別把架構只寫在

    Pro m p t 用 Executable Guardrails 打造可自我修正的 Agentic SDLC Neo Hsu
  2. 講者介紹 N eo H su 01 OT/工控資安 目前從事 OT/工控資安領域的產品開發 02

    Agentic Coding × 軟體工程 近年專注於 Agentic Coding 與 AI 輔助軟體工程, 持續探索如何將 AI 納入可驗證、可治理且可規模化的軟體開發流程 03 團隊導入與知識分享 同時也是公司內部 Agentic Coding 傳教士, 透過技術分享、工具導入與工作流設計, 推動 AI 輔助開發在團隊中落地
  3. 開場 · 全貌 所有需求與 Bug,都從 Ticket 開始 人:需求確認 自動:PR+CI 通過

    人/Agent:PR approved 自動:測試通過 TODO IN-PROGRESS REVIEW VALIDATE DONE 人:PM・Dev・QA Coding Agent 多個 Agent QA Agent 自動 Agent+Graph 自動開發 代碼審查 自動化測試 完成 經 ACP 呼叫 發 PR、等 CI 綠燈 對照 Ticket 與 PR 品質・符合需求 通過 → DONE 失敗 → 開 Bug 子 Ticket 全部完成 母 Ticket 才 DONE 補全需求與驗收 確保完整、準確 重走同一套流程 找到問題・自動開單 Bug Ticket(子 Ticket) Graph 每一棒都從這裡查系統現況:補需求、寫程式、審查、測試 人集中在需求;之後的每一棒,狀態一切換,逐步交給 Coding Agent。
  4. 第一幕 · 痛 · HUMAN IN THE LOOP 你是不是也成了 Agent

    的保母? 叫它寫 規則寫了,照樣被違反 每一步都要盯 叫它重跑 你 叫它測 換人就重教一次 我們想要:人只出現在需求、決策和例外。 叫它修
  5. 第一幕 · 痛 Prompt 寫得很清楚,Agent 還是直接碰了 DB PRO MPT 「Handler

    不可直接存取資料庫,請透過 Service。」 40 func (h *OrderHandler) Cancel(w http.ResponseWriter, r *http.Request) { 41 id := orderID(r) 42 row := h.db.QueryRowContext(r.Context(), cancelSQL, id) 43 ... 第 42 行:Handler 繞過 OrderService 直接查 DB,測試照樣通過。
  6. 第一幕 · 痛 同一張 Ticket,換一個 Agent,結果就不一樣 Agent A 符合架構 同一段

    Prompt 經由 OrderService Agent B 違反架構 同一段 Prompt Handler 直接查 DB(第 42 行) 同一張 Ticket ORD-246 取消訂單 API 結果取決於這次是哪個 Agent、這次運氣好不好。問題不在 Agent,在規則放錯了地方。
  7. 第一幕 · 痛 結果不同,來自 Prompt、Skills 與 Memory 同事 A 同事

    B Agent Agent A Prompt A 的寫法 Skills A 自己裝的 Memory 用了半年 Agent Agent B ≠ Prompt B 的寫法 Skills B 自己裝的 Memory 剛開始用 Memory 會隨使用時間累積:同一句 Prompt,用了半年和剛開始用的人,得到的結果不同。 這些差異不需要消除——每個人的 workflow 本來就不同。
  8. 第一幕 · 痛 In → Near → Out:人和 Loop 的距離

    人 Agent 人 Agent Agent Human in the loop Human near the loop Human out of the loop 每一步都要人下指令、看結果、叫它修 Agent 自己跑迴圈,人在旁邊盯著、隨時介入 迴圈靠規則自己收斂;人定義需求、處理例外、最 後驗收 人 今天要講的,就是怎麼從 In 走到 Out。
  9. 要統一的是什麼 Prompt 只對一個 Agent 說話, Repo 對每一個 Agent 都有效。 所以,把交付標準從

    Prompt 搬進 Repo,變成會失敗、會指向修正的檢查;個人的 workflow 留給個人。
  10. 第二幕 · 架構 建 Agentic SDLC,其實就像在建 CI pipeline CI pipeline

    Trigger push・PR Runner Build Fail fast Required gate 人看 log 修 Agentic SDLC Ticket Status change 各階段 Coding Agent Implement pre-commit pre-push Test fail Agent 讀 stdout 修 差別只在最後一格:以前看 log 修的是人,現在是 Agent——所以人才能離開迴圈。
  11. 第二幕 · 架構 Repo 是規則的家,平台讓 Workflow 被執行 結果、證據與缺陷回到 Ticket 人

    Repo:規則的家 需求・決策 README・架構文件 執行 Ticket 本輪需求與驗收 事件 Webhook 去重・狀態檢查 啟動 Coding Agent Git 平台 統一執行入口 (mise / make) 任何一個都可以 架構規則(lint・測試) 查詢現況 合併 驗收情境(Gherkin) 診斷 補充 Ticket 部署・QA 驗收 PR Review push Git hooks・本地檢查 CI 必要檢查 CODEOWNERS Merge Queue Graph:現存系統的知識(程式結構、文件、Ticket 關聯)——補 Ticket、實作、Review、QA 都從這裡查
  12. 第二幕 · 架構 Ticket 決定做什麼,Graph 提供系統現況 Ticket:要做什麼 需求、驗收、決策;狀態改變時觸發對應的 Agent 補充

    Ticket 實作 Review QA 會影響哪些模組? 正確路徑在哪?可重用什麼? 這次影響了什麼? 異常從哪條路徑來? → 範圍、路徑寫回 Ticket → 程式與測試 → 可行動的發現 → 重現與缺陷 Ticket Graph:系統現在是什麼 用 Graphify 建立:程式結構、文件語意、Ticket 與 commit 的關聯 只交 Ticket,Agent 只能用猜的。Memory 因人而異,Graph 是團隊共用的系統記憶。
  13. 第二幕 · 架構 Repo 只放交付標準,不放個人 workflow 同事 A 的 workflow

    Agent A/自己的 Prompt/Skills/ Memory 半年 同事 B 的 workflow Agent B/另一套 Prompt/Memory 剛開始 Repo:團隊共同的交付標準 linter・架構測試 驗收情境 工具入口與工具版本 README・架構文件 Graph 索引 CI 必要檢查 同事 C 的 workflow Agent A/Slash commands/自訂 hooks workflow 各自不同,都通過同一組交付標準——像交通規則,怎麼開車留給每個人。
  14. 第二幕 · 架構 接下來會用到的工具,各自負責什麼 看懂系統 會失敗的檢查 伺服器把關 Graph 統一工具入口 驗收情境

    系統的地圖(Graphify) 工具版本管理和指令(mise/Make ) Linter 架構測試 Git hooks 自動的第一關(golanci-lint) 架構規範變成測試 Commit 前做檢查 CI 必要檢查 CODEOWNERS Merge Queue 繞不過的關卡 規則檔的門禁 合併前的總彩排 記角色就好,工具可以換成你們熟悉的。 PM 看得懂的測試(Gherkin)
  15. 第二幕 · 架構 四層守護:每一層回答一個問題 1 2 3 4 守住要做什麼 每一輪只有一個需求來源

    守住怎麼做 Ticket Ticket 補充 驗收情境 事件觸發 工具入口 架構規則 API 契約 Git hooks Repo 提供工具、規則與診斷 守住規則本身 繞路走不通,或一定會被看到 守住合起來的結果 驗證實際交付的組合與環境 地基:Graph 每一層都從這裡取得系統現況 CI 必要檢查 CODEOWNERS Agent 權限 PR Review Merge Queue QA 回到 Ticket 程式結構 文件語意 Ticket・commit 關聯 回饋迴圈
  16. 第一層 · 要做什麼 第一層:守住「要做什麼」 結果、證據與缺陷回到 Ticket 人 Repo:規則的家 需求・決策 執行

    Ticket 本輪需求與驗收 事件 Webhook 啟動 去重・狀態檢查 診斷 補充 Ticket 合併 驗收情境(Gherkin) push 查詢現況 Graph:現存系統的知識(程式結構、文件、Ticket 關聯)——補 Ticket、實作、Review、QA 都從這裡查
  17. 第一層 · 要做什麼 原驗收內自行修正,新方向另開 Ticket 像 React 的 Single Source

    of Truth:每一輪的需求、驗收與決策,只從 Ticket 讀。 ORD-246 出貨前皆可取消 寫清楚:為什麼改・新的驗收・可沿用的成果 原驗收內就地修正 PM 改方向 ORD-218 下單 30 分鐘內可取消 四層守護:要做什麼 › 怎麼做 › 規則本身 › 合起來的結果 ORD-218 被取代 ≠ 通過驗收 Done
  18. 第一層 · 要做什麼 用 Graph 補充 Ticket:取消訂單會碰到什麼? 庫存回補 相關模組、影響範圍與查詢連結,寫進 ORD-246

    EXTRACTED 取消訂單 EXTRACTED 寫回 Ticket 退款 EXTRACTED 原始碼明確寫出的關係 INFERRED INFERRED 通知 四層守護:要做什麼 › 怎麼做 › 規則本身 › 合起來的結果 解析推得,下結論前要查證
  19. 第一層 · 要做什麼 把成功條件寫成能抓到錯誤的驗收 Feature: 優惠券折抵 錯誤實作 仍折抵成 900 元

    Scenario: 已過期優惠券不能折抵 情境必須 FAIL Given 系統時間固定在優惠券到期之後 And 訂單總額為 1000 元 When 使用者套用該優惠券 正確實作 Then 系統拒絕折抵 拒絕折抵,維持 1000 元 And 訂單總額仍為 1000 元 這時才 PASS Gherkin 用 Given/When/Then 描述行為;BDD 工具把每一步接到測試程式,時鐘、入口與斷言都要接上。 四層守護:要做什麼 › 怎麼做 › 規則本身 › 合起來的結果
  20. 第一層 · 要做什麼 事件決定何時開始,Ticket 決定要做什麼 1 Status change 2 3

    4 5 找回 Ticket 確認 仍然有效 查 Graph 再執行 回寫 證據 Status change 只是訊號,接收端負責: 去重:重送不重做 四層守護:要做什麼 › 怎麼做 › 規則本身 › 合起來的結果 狀態檢查:舊單不推進 結果歸屬:寫回正確 Ticket
  21. 第二層 · 怎麼做 第二層:守住「怎麼做」 結果、證據與缺陷回到 Ticket Repo:規則的家 README・架構文件 執行 事件

    啟動 Agent 合併 驗收情境(Gherkin) 工具入口(mise/make) 任何一個都可以 診斷 架構規則(lint・測試) push Git hooks・本地檢查 補充 Ticket 查詢現況 Graph:現存系統的知識(程式結構、文件、Ticket 關聯)——補 Ticket、實作、Review、QA 都從這裡查
  22. 第二層 · 怎麼做 人能離開迴圈,是因為 Agent 會讀錯誤自己修 Agent 改程式 以前 依

    Ticket 實作 錯誤靠人轉述 讀錯誤、修正 查 Graph 改走 Service 人不在這個迴圈裡 執行命令 git commit・lint/test 現在 Agent 直接讀輸出 所以 命令輸出 stdout/stderr+結束碼 四層守護:要做什麼 › 怎麼做 › 規則本身 › 合起來的結果 錯誤訊息寫給 Agent 看
  23. 第二層 · 怎麼做 錯誤輸出要能指向下一步 # mise.toml [tasks."test:architecture"] description = "Check

    dependency boundaries" run = "go test ./architecture/..." FAIL ARCH001 位置 internal/http/order_handler.go:42 實際 Handler 直接呼叫 DB 預期 經由既有 OrderService 重現 mise run test:architecture 四層守護:要做什麼 › 怎麼做 › 規則本身 › 合起來的結果
  24. 第二層 · 怎麼做 API 規範也可以寫進 Repo:一份契約,各端共用 會失敗的檢查 buf lint buf

    generate:各端程式碼 一份 API 契約(Protobuf) 命名、結構規範 介面與型別 // order.proto message ListOrdersRequest { int32 page_size = 1 [ (buf.validate.field).int32 = { gte: 1, lte: 100 } ]; } buf breaking 舊的呼叫端不能壞 Protovalidate 欄位規則,入口自動驗證 Go 服務端 欄位、型別、驗證規則,都只定義一次 換哪個 Agent 實作,介面與驗證都來自同一份契約——不再各端各自理解欄位。 四層守護:要做什麼 › 怎麼做 › 規則本身 › 合起來的結果 對外系統 Client 用同一份欄位 其他語言・團隊 不用各自手寫
  25. 第二層 · 怎麼做 可自我修正:錯誤越早回來,修正越便宜 4 3 2 1 pre-commit 2

    pre-push 3 CI・Merge Queue 4 QA 1 Agent 秒級・格式、lint、快速架構檢查 分鐘級・建置、型別、相關測試 更久・必要驗收與實際合併組合 部署後・環境驗收,缺陷回到 Ticket 每一圈呼叫的,都是 Repo 裡同一組 mise 任務。 四層守護:要做什麼 › 怎麼做 › 規則本身 › 合起來的結果
  26. 第三層 · 規則本身 第三層:守住「規則本身」 結果、證據與缺陷回到 Ticket Repo:規則的家 合併 執行 事件

    啟動 Git 平台 診斷 架構規則(lint・測試) push CI 必要檢查 Git hooks・本地檢查 補充 Ticket 查詢現況 Graph:現存系統的知識(程式結構、文件、Ticket 關聯)——補 Ticket、實作、Review、QA 都從這裡查 CODEOWNERS
  27. 第三層 · 規則本身 Agent 卡關時,常見的三種繞路 略過 HOO K 放寬斷言 改規則設定

    git commit --no-verify 「等於 1000」→「大於 0」 把自己的檔案加進例外名單 跳過 commit 前的檢查 錯誤的實作也能通過 規則還在,對自己失效 通常不是存心作弊,而是在優化「讓命令成功」。 四層守護:要做什麼 › 怎麼做 › 規則本身 › 合起來的結果
  28. 第三層 · 規則本身 Guardrail 本身也需要被保護 Agent 想繞路 規則・main ① Agent

    權限 ② CI 必要檢查 ③ CODEOWNERS 擋 --no-verify・補強 本地略過也會重跑 改規則要指定的人核准 Flaky test:隔離、限制重試、留證據給人。 四層守護:要做什麼 › 怎麼做 › 規則本身 › 合起來的結果
  29. 第四層 · 合起來的結果 第四層:守住「合起來的結果」 結果、證據與缺陷回到 Ticket 部署・QA 驗收 合併 執行

    Ticket 事件 啟動 Git 平台 本輪需求與驗收 PR Review 診斷 補充 Ticket push CI 必要檢查 查詢現況 Merge Queue Graph:現存系統的知識(程式結構、文件、Ticket 關聯)——補 Ticket、實作、Review、QA 都從這裡查
  30. 第四層 · 合起來的結果 可採取行動的 Review,說得出哪條驗收會失敗 Ticket 的驗收 AC-03 位置 order_cancel_service.go:87

    情境 已出貨訂單仍可取消 PR 這次的 diff Review Agent 依據 ORD-246 AC-03 建議 恢復出貨狀態檢查 Graph 原本的出貨檢查路徑 Graph 幫忙找到該看的地方;結論要有 diff、需求和可重現的證據。 四層守護:要做什麼 › 怎麼做 › 規則本身 › 合起來的結果
  31. 第四層 · 合起來的結果 各自綠燈,合在一起還是會壞 PR A CalcDiscount 改名為 ApplyCoupon ApplyCoupon

    PR B mai n + A + B 新增一處呼叫 CalcDiscount 編譯失敗 CI 通過 CI 通過 Merge Queue 把排隊中的 PR 依序疊在最新主線上,用實際要合併的組合跑必要檢查,通過才合併。 四層守護:要做什麼 › 怎麼做 › 規則本身 › 合起來的結果 B 呼叫的函式已經不存在
  32. 第四層 · 合起來的結果 QA 發現:過期優惠券在早上 8 點前仍可折抵 根因:到期判斷用了 UTC 仍可折抵的

    8 小時 12/01 00:00(UTC+8) 應該到期 12/01 08:00(UTC+8) = UTC 00:00,才真正拒絕 原驗收沒達成 新的需求範圍 修好之後 原單保持未完成,或用關聯的缺陷 開新 Ticket,確認優先順序與依賴 保存證據、補上回歸情境,才進 Ticket 擋住完成 四層守護:要做什麼 › 怎麼做 › 規則本身 › 合起來的結果 Done
  33. 第四層 · 合起來的結果 每一次缺陷,都讓下一次驗證多一道依據 Scenario: 優惠券在台灣時間到期日結束後不能折抵 Given 優惠券到期日為 2026-11-30 And

    系統時間固定在 2026-12-01 00:30(UTC+8) And 訂單總額為 1000 元 When 使用者套用該優惠券 Then 系統拒絕折抵 And 訂單總額仍為 1000 元 下一次不論是哪個 Agent 改到這段程式,這個情境都會擋下同樣的錯。 四層守護:要做什麼 › 怎麼做 › 規則本身 › 合起來的結果
  34. 第三幕 · 轉變 從 In the loop 走到 Out of

    the loop 階段 需求與規格 實作 測試 修錯 Review 合併 驗收 In the loop 人 人 人 人 人 人 人 Near the loop 人 Agent Agent 人介入 人 人 人 Out of the loop 人 Agent Agent Agent 人看結論 規則 人 人要親自處理的站:7 → 5 → 3(目標) Out of the loop 不是不管:需求、例外和最後的驗收,仍然是人的判斷。
  35. 第三幕 · 轉變 明天就能開始:從一條規則做起 1 2 挑一條最常被違反的規 則 寫成會失敗、會指向修 正的檢查

    例如 Handler 不得直接存取 DB 接上 pre-commit 與 CI 接著再補:Ticket 與 Gherkin、Repo 入口、事件串接、防繞過。 量測交付時間、人工介入、修正次數、交付後缺陷與維護成本——不是數裝了幾個工具。 3 換一個 Agent,再跑一次 都被擋下、都修到同一個驗收, 就成立了