邊界到代碼評審的護(hù)欄實(shí)踐)
AI 編程代理AI coding agent進(jìn)入研發(fā)流程后團(tuán)隊(duì)最先感受到的往往不是效率提升而是代碼評審壓力的增加。Figma 工程師在 AI Engineer 相關(guān)分享中討論過同一個(gè)問題當(dāng)代理自動完成跨文件修改、自動執(zhí)行命令、自動生成測試時(shí)如何保證最終提交的代碼仍然是干凈、可維護(hù)、可回滾的。核心結(jié)論并不是“少用 AI”而是先用工程手段把 AI 約束在安全邊界內(nèi)。這篇文章不準(zhǔn)備逐句復(fù)述某一場演講而是把這一類實(shí)踐整理成一套可以在自己團(tuán)隊(duì)中復(fù)用的落地流程。整個(gè)過程會圍繞一條主線展開先理解 AI 編程代理為什么會產(chǎn)出質(zhì)量不可控的代碼然后從任務(wù)邊界、倉庫規(guī)則、自動化校驗(yàn)、代碼評審、線上監(jiān)控和回滾幾個(gè)環(huán)節(jié)建立護(hù)欄。每個(gè)環(huán)節(jié)都會給出可執(zhí)行的配置、命令和檢查清單盡量做到看完就能在自己項(xiàng)目里試點(diǎn)。1. 先理解 AI 編程代理為什么會寫出“垃圾代碼”1.1 輔助補(bǔ)全工具與自主代理的最大區(qū)別很多團(tuán)隊(duì)已經(jīng)習(xí)慣了 AI 補(bǔ)全工具的工作方式人寫函數(shù)名AI 補(bǔ)函數(shù)體人再手動修改。這種模式下修改方向和整體結(jié)構(gòu)都由人控制AI 只是加速了局部輸入。AI 編程代理不一樣。它接收的是一個(gè)任務(wù)描述而不是某一行代碼的上下文。它會自己搜索代碼庫、修改多個(gè)文件、執(zhí)行構(gòu)建命令、讀取測試結(jié)果甚至反復(fù)重試。人從“逐行寫代碼”退后到“發(fā)布任務(wù)和檢查結(jié)果”。這一變化帶來的風(fēng)險(xiǎn)是結(jié)構(gòu)性的人不再對每個(gè)修改點(diǎn)有直接感知。AI 可能為了滿足任務(wù)描述修改超出范圍的文件。AI 傾向于讓測試通過但不一定理解代碼庫的歷史約定和設(shè)計(jì)意圖。一旦任務(wù)描述模糊AI 會主動腦補(bǔ)業(yè)務(wù)規(guī)則產(chǎn)生“看起來合理、實(shí)際上錯(cuò)誤”的代碼。所以把 AI 編程代理接入倉庫第一步不是打開工具開關(guān)而是先理解它和補(bǔ)全工具完全不同的工作模式。1.2 “垃圾代碼”在代理場景下有哪些典型表現(xiàn)“垃圾代碼”不是一個(gè)籠統(tǒng)的貶義而是一類可以在評審和運(yùn)行時(shí)被識別的問題。在 AI 編程代理場景下最常見的是這幾種現(xiàn)象具體表現(xiàn)為什么容易發(fā)生表面可用但內(nèi)部混亂大量 if else 堆疊、復(fù)制粘貼式修改、命名隨意AI 優(yōu)化的是“讓測試通過”而不是可讀性錯(cuò)誤處理空白吞掉異常、空值不判斷、網(wǎng)絡(luò)錯(cuò)誤不重試任務(wù)描述里沒有提出錯(cuò)誤分支要求過度設(shè)計(jì)為一個(gè)簡單字段引入抽象接口和工廠AI 從訓(xùn)練數(shù)據(jù)中學(xué)習(xí)到“看起來專業(yè)的寫法”修改范圍失控改完目標(biāo)函數(shù)后順手改掉公共工具類代理在檢索上下文時(shí)發(fā)現(xiàn)“相關(guān)代碼”就會一并改測試失效測試斷言被調(diào)整成恒真條件或只覆蓋正向路徑代理為了自圓其說會修改測試來匹配實(shí)現(xiàn)隱性破壞調(diào)用方?jīng)]改、函數(shù)簽名變了、返回結(jié)構(gòu)變了代理只關(guān)注當(dāng)前任務(wù)覆蓋到的調(diào)用點(diǎn)這些問題的共同根源是代理在優(yōu)化一個(gè)局部目標(biāo)。它沒有項(xiàng)目全局視角也不清楚哪些代碼是核心資產(chǎn)、哪些代碼是臨時(shí)方案、哪些修改需要同步通知其他團(tuán)隊(duì)。1.3 先設(shè)護(hù)欄再談效率Figma 工程師在分享中反復(fù)強(qiáng)調(diào)的一點(diǎn)是把 AI 編程代理當(dāng)作“高速但經(jīng)驗(yàn)不足的工程師”來管理而不是當(dāng)成一個(gè)純生成器。一個(gè)剛?cè)肼毜墓こ處煿緯o他什么明確的任務(wù)邊界。倉庫結(jié)構(gòu)和編碼規(guī)范。構(gòu)建、測試、lint 命令。代碼評審機(jī)制。上線后的監(jiān)控和回滾手段。這些就是護(hù)欄。AI 編程代理同樣需要這套東西而且需要得更嚴(yán)格因?yàn)樗摹袄斫饽芰Α眮碜陨舷挛亩皇情L期記憶。如果倉庫里沒有明確的規(guī)則文件代理就會按照自己的默認(rèn)偏好寫代碼如果任務(wù)描述沒有邊界它就會把相關(guān)文件全改一遍如果合并前沒有強(qiáng)制校驗(yàn)它就能把編譯不過或測試失敗的代碼直接推進(jìn)主干。所以安全落地的核心不是“更聰明的模型”而是更完整的工程流程。后續(xù)章節(jié)按這個(gè)順序展開接入前準(zhǔn)備、任務(wù)拆分、自動校驗(yàn)、代碼評審、線上監(jiān)控、失敗復(fù)盤。2. 接入 AI 編程代理前確定邊界、規(guī)則和基線2.1 先回答三個(gè)問題做什么、不做什么、怎么算完成接入代理前團(tuán)隊(duì)需要先對使用場景達(dá)成一致。不是所有任務(wù)都適合交給代理也不是所有代碼庫都適合在第一天開放全部目錄。推薦先按任務(wù)類型做評估任務(wù)類型適合交給代理嗎風(fēng)險(xiǎn)等級說明生成單元測試適合中需要人檢查斷言是否有效代碼補(bǔ)全適合低人在當(dāng)前文件中掌握上下文Bug 修復(fù)視情況中高必須先有穩(wěn)定復(fù)現(xiàn)路徑跨模塊重構(gòu)謹(jǐn)慎高建議拆成小步執(zhí)行自動化腳本生成適合低獨(dú)立腳本影響范圍小底層公共庫修改不建議初期開放極高影響所有調(diào)用方這三個(gè)問題必須在試點(diǎn)前回答清楚這個(gè)任務(wù)允許代理修改哪些目錄和文件。這個(gè)任務(wù)禁止代理修改哪些目錄和文件。任務(wù)完成的驗(yàn)收標(biāo)準(zhǔn)是什么包括測試覆蓋率、構(gòu)建通過、無 lint 錯(cuò)誤等。沒有邊界判斷就放代理進(jìn)倉庫等于讓一個(gè)新工程師自己決定改哪里。區(qū)別是真人會問代理不會問。2.2 在倉庫根目錄建立規(guī)則文件把團(tuán)隊(duì)的編碼約束寫進(jìn)一個(gè)代理可讀、人也可見的規(guī)則文件。目前很多編程代理會主動讀取倉庫根目錄下的AGENTS.md或等價(jià)文件并把它作為系統(tǒng)的上下文注入。這個(gè)文件可以包括項(xiàng)目技術(shù)棧和關(guān)鍵依賴。構(gòu)建、測試、lint 的準(zhǔn)確命令。目錄結(jié)構(gòu)和職責(zé)劃分。編碼風(fēng)格約定。禁止修改的目錄和文件。提交信息規(guī)范。完成任務(wù)的 Definition of Done。下面是一個(gè)AGENTS.md示例可以直接作為起點(diǎn)# 項(xiàng)目規(guī)則 ## 技術(shù)棧 - Python 3.11 - FastAPI - SQLAlchemy 2.x - pytest ## 常用命令 - 安裝依賴: pip install -e .[dev] - 單測: pytest tests/ -x -q - 類型檢查: mypy app/ - 格式化: ruff format app/ tests/ - lint: ruff check app/ tests/ ## 目錄職責(zé) - app/api: 路由層只做參數(shù)解析和響應(yīng)封裝 - app/services: 業(yè)務(wù)邏輯層 - app/models: ORM 模型 - app/migrations: 數(shù)據(jù)庫遷移文件禁止手動改動 ## 禁止修改 - app/migrations/ - docs/ - gen/ ## 編碼約束 - 函數(shù)需要 docstring - 禁止裸 except必須捕獲具體異常類型 - 新增對外接口必須包含輸入校驗(yàn) - 錯(cuò)誤信息不允許直接暴露內(nèi)部堆棧 ## 提交信息 - 遵循 Conventional Commits - 示例: fix(api): handle empty user id ## 完成定義 - pytest 全部通過 - mypy 無錯(cuò)誤 - ruff check 無錯(cuò)誤 - 不修改任務(wù)范圍之外的文件注意不要把規(guī)則文件寫得像散文。代理對長文本的理解能力有限規(guī)則要短、要清晰、要可檢查。比如“保持代碼整潔”這種話沒有意義要寫成“函數(shù)長度不超過 50 行超出則拆分”。2.3 先把代碼庫基線跑穩(wěn)態(tài)在讓代理開始改代碼之前倉庫本身必須是健康的。否則會出現(xiàn)一個(gè)經(jīng)典的死循環(huán)代理跑出錯(cuò)誤你分不清是它造成的還是倉庫原本就有的。建議先完成# 本地完整執(zhí)行一遍 pip install -e .[dev] pytest tests/ -x -q mypy app/ ruff check app/ tests/ # 記錄執(zhí)行結(jié)果和時(shí)間 echo baseline done .ai_agent_baseline這道工序有幾個(gè)作用確認(rèn) CI 命令和本地命令一致避免代理在本地通過了、CI 卻失敗。確認(rèn)測試基線是綠的代理后續(xù)改動如果破壞測試可以直接定位到它。確認(rèn)構(gòu)建時(shí)間合理如果一次測試要跑 30 分鐘代理的每次嘗試都會很昂貴。如果倉庫里存在大量歷史遺留的失敗測試先把它們清理掉或者標(biāo)注skip再讓代理介入。否則代理會修復(fù)失敗測試作為“完成目標(biāo)”而不會關(guān)心這些測試是否應(yīng)該有。3. 任務(wù)拆分與上下文注入不要讓代理吃下過大的任務(wù)3.1 一個(gè)任務(wù)對應(yīng)一個(gè)可評審的變更集把 AI 編程代理想象成一個(gè)只會專注當(dāng)前 prompt 的工程師。給它一個(gè)“優(yōu)化整個(gè)訂單系統(tǒng)”的任務(wù)它會輸出一個(gè)幾百行甚至上千行的 diff。這種 diff 很難評審而且一旦產(chǎn)生問題很難定位是哪一步引入的。推薦的拆分粒度是一個(gè)任務(wù)只解決一個(gè)問題一個(gè)任務(wù)生成的變更集要能被人在 15 到 30 分鐘內(nèi)評審?fù)?。下面的任?wù)描述模板可以直接復(fù)制使用## 目標(biāo) 修復(fù) API 層在用戶 ID 為空時(shí)返回錯(cuò)誤碼的問題。 ## 范圍 - app/api/users.py - tests/test_api_users.py ## 禁止修改 - app/services/ - app/models/ - app/migrations/ ## 驗(yàn)收標(biāo)準(zhǔn) - 新增測試覆蓋 user_id 為 None 和空字符串兩種情況 - pytest tests/test_api_users.py -x -q 通過 - ruff check app/api/users.py 通過 - 不修改范圍之外的文件這個(gè)模板的關(guān)鍵是明確了邊界和驗(yàn)收標(biāo)準(zhǔn)。代理不需要猜測它只需要執(zhí)行。3.2 上下文越多不代表效果越好有些團(tuán)隊(duì)為了讓代理更“懂業(yè)務(wù)”會把整個(gè)技術(shù)設(shè)計(jì)文檔、需求文檔、歷史變更記錄全部塞進(jìn) prompt。這會導(dǎo)致幾個(gè)問題上下文過長后代理會把注意力分散到無關(guān)信息上。關(guān)鍵約束被淹沒在大量文本中間。每次請求的成本和時(shí)間都會上升。更合理的做法是分三層提供上下文上下文類型內(nèi)容示例全局規(guī)則倉庫級規(guī)則文件代理自行讀取AGENTS.md任務(wù)上下文當(dāng)前需求的背景和業(yè)務(wù)規(guī)則prompt/issue 描述局部參考類似功能的實(shí)現(xiàn)代碼或接口定義粘貼少量代碼片段在實(shí)際操作中不需要把整個(gè)業(yè)務(wù)背景都復(fù)制到 prompt 里。告訴代理“這個(gè)函數(shù)是給前端登錄接口用的user_id 來自 JWT token為空說明鑒權(quán)失效應(yīng)該返回 401”遠(yuǎn)好于貼三頁需求文檔。3.3 分支策略讓代理的錯(cuò)誤被隔離代理在執(zhí)行任務(wù)時(shí)可能會反復(fù)嘗試、提交失敗代碼。不要讓它在主干分支上直接工作至少在試點(diǎn)階段給每次任務(wù)開一個(gè)獨(dú)立分支。git checkout -b feat/ai-agent/user-id-validation如果需要多個(gè)代理并行處理不同任務(wù)命名規(guī)則可以用ai-agent/任務(wù)標(biāo)簽作為前綴方便后續(xù)統(tǒng)一 review 和清理。代理完成后的工作流# 拉取最新主干并合并到當(dāng)前分支 git fetch origin main git merge origin/main # 運(yùn)行完整校驗(yàn) pytest tests/ -x -q mypy app/ ruff check app/ tests/ # 查看最終變更范圍 git diff --stat main...git diff --stat main...這一步很重要它能讓你在合入前直觀看到代理到底改了哪些文件。如果出現(xiàn)大量與任務(wù)無關(guān)的文件應(yīng)該直接打回而不是手動挑揀。4. 從生成到合并強(qiáng)制自動校驗(yàn)和人工評審關(guān)卡4.1 合并前的自動化檢查不能只依賴“代理自測”代理在執(zhí)行任務(wù)時(shí)通常會自己運(yùn)行一遍測試但這個(gè)自測結(jié)果只能作為參考。它的測試目標(biāo)可能被污染它也可能因?yàn)榄h(huán)境差異在自己的沙箱里通過、在 CI 里失敗。所以倉庫必須有一套不依賴代理自身的強(qiáng)制檢查流程。最簡單的方式是在 CI 中增加一個(gè)獨(dú)立的 job專門校驗(yàn)代理分支name: ai-agent-check on: pull_request: types: [opened, synchronize] jobs: verify: runs-on: ubuntu-latest steps: - uses: actions/checkoutv4 with: fetch-depth: 0 - uses: actions/setup-pythonv5 with: python-version: 3.11 - run: pip install -e .[dev] - run: pytest tests/ -x -q - run: mypy app/ - run: ruff check app/ tests/ - run: ruff format --check app/ tests/ - name: check diff scope run: | # 如果任務(wù)只允許修改 app/api/則檢測是否出現(xiàn)其他目錄變更 if git diff --name-only origin/main...HEAD | grep -qv ^app/api/ ; then echo 發(fā)現(xiàn)代理修改了范圍之外的目錄 exit 1 fi這里的check diff scope是關(guān)鍵步驟。它做了一件代碼評審中最容易被忽略的事情確認(rèn)變更范圍是否越界。代理也許能通過所有測試但如果它改壞了app/models/下的數(shù)據(jù)模型AI 生成的測試根本無法覆蓋所有調(diào)用方的影響。本地同樣可以做一個(gè) pre-push 鉤子避免代理把明顯不合規(guī)的代碼推到遠(yuǎn)端#!/usr/bin/env bash # .git/hooks/pre-push 或項(xiàng)目內(nèi)的 pre-push 腳本 set -e echo running ai-agent pre-push checks... pytest tests/ -x -q mypy app/ ruff check app/ tests/4.2 人工評審的重點(diǎn)不是“讀代碼”而是“問問題”即使自動化檢查全綠也不能直接把 AI 生成的代碼合入。人工評審仍然不可省略但評審方式需要調(diào)整。AI 生成代碼的評審重點(diǎn)不是逐行檢查語法而是回答這幾個(gè)問題這個(gè)改動解決了任務(wù)描述里的問題嗎它有沒有修改任務(wù)范圍之外的文件錯(cuò)誤處理是否真實(shí)還是只是讓測試通過有沒有引入重復(fù)邏輯或新的抽象而這個(gè)抽象沒有明顯收益測試是否真的會失敗把關(guān)鍵斷言暫時(shí)改錯(cuò)測試是否變紅是否有并發(fā)、時(shí)間、數(shù)據(jù)一致性方面的問題依賴和數(shù)據(jù)庫遷移是否被無意修改可以把這些整理成評審模板合入每個(gè) AI 代理 MR 時(shí)使用評審點(diǎn)檢查內(nèi)容通過標(biāo)準(zhǔn)范圍控制與git diff --stat對比任務(wù)范圍無越界文件正確性能復(fù)述這次改動解決的業(yè)務(wù)場景理解與任務(wù)一致異常處理空值、異常、超時(shí)等分支有處理不吞錯(cuò)、不裸 except測試質(zhì)量故意破壞斷言測試是否失敗測試有實(shí)際約束力重復(fù)代碼搜索是否已有相似實(shí)現(xiàn)沒有重復(fù)邏輯修為接口公共函數(shù)簽名、返回結(jié)構(gòu)是否改變調(diào)用方已經(jīng)同步更新性能風(fēng)險(xiǎn)是否有循環(huán)內(nèi)查詢、N1、大對象復(fù)制明顯性能隱患已消除4.3 要求代理先完成自檢并通過 prompt 約束行為可以讓代理在生成代碼后自動執(zhí)行一系列檢查并把輸出結(jié)果帶回。比如在任務(wù)描述中追加## 提交前自檢 在生成最終結(jié)果之前你必須執(zhí)行以下命令 1. pytest tests/test_api_users.py -x -q 2. mypy app/api/users.py 3. ruff check app/api/users.py 如果檢查失敗繼續(xù)修復(fù)直至通過。如果無法通過需要說明具體原因和待確認(rèn)問題。這種方式相當(dāng)于要求代理輸出一份“自檢報(bào)告”。它不一定完全準(zhǔn)確但可以提升代理對錯(cuò)誤的關(guān)注程度也能幫你快速判斷代理卡在了哪個(gè)環(huán)節(jié)。要注意不要因?yàn)榇韴?bào)告“全部通過”就直接合入報(bào)告需要和 CI 結(jié)果交叉驗(yàn)證。5. 上線后的監(jiān)控與回滾質(zhì)量問題是運(yùn)行時(shí)才暴露的5.1 區(qū)分學(xué)習(xí)環(huán)境與生產(chǎn)環(huán)境的要求在本地試用 AI 編程代理時(shí)可以只關(guān)注“代碼能不能跑”。但一旦進(jìn)入生產(chǎn)環(huán)境AI 生成代碼的質(zhì)量判斷標(biāo)準(zhǔn)就要切換到運(yùn)行表現(xiàn)上維度學(xué)習(xí)環(huán)境生產(chǎn)環(huán)境驗(yàn)收標(biāo)準(zhǔn)編譯通過、本地測試綠錯(cuò)誤率、耗時(shí)、業(yè)務(wù)指標(biāo)無回退檢查手段IDE、手動測試日志、監(jiān)控、告警、鏈路追蹤問題處理改代碼重新跑先止血、再定位、再修復(fù)數(shù)據(jù)要求造數(shù)方便、無真實(shí)用戶需要考慮兼容和數(shù)據(jù)遷移回滾方式git revert功能開關(guān)、版本回滾、數(shù)據(jù)庫兼容方案如果團(tuán)隊(duì)正在用代理生成數(shù)據(jù)庫變更或涉及支付、權(quán)限的核心代碼上線前必須增加一層額外評審并且盡量讓變更可以在不重新發(fā)布代碼的前提下被關(guān)閉。5.2 上線后先看異常率再看耗時(shí)最后看業(yè)務(wù)指標(biāo)生產(chǎn)環(huán)境不會直接告訴你“代碼寫錯(cuò)了”它只會通過指標(biāo)異常間接表達(dá)。針對 AI 生成代碼建議上線后按這個(gè)順序觀察錯(cuò)誤率如果部署后錯(cuò)誤率出現(xiàn)明顯增長優(yōu)先懷疑新增邏輯的異常分支沒有處理好。耗時(shí)P50、P95、P99 是否上漲提示可能存在循環(huán)內(nèi)查詢、不必要的重試或無界緩存。業(yè)務(wù)指標(biāo)訂單成功率、接口調(diào)用量、轉(zhuǎn)化率是否有回退防止代理把業(yè)務(wù)邏輯改出偏差。下面是一個(gè)簡單的壓測對比方式用于上線前快速暴露代理改動的性能問題# 部署前在基準(zhǔn)版本上記錄指標(biāo) k6 run --summary-exportbaseline.json load-test.js # 部署代理分支后再次執(zhí)行 k6 run --summary-exportafter.json load-test.js # 對比 P95 耗時(shí) python -c import json with open(baseline.json) as f: base json.load(f) with open(after.json) as f: after json.load(f) b base[metrics][http_req_duration][values][p(95)] a after[metrics][http_req_duration][values][p(95)] print(fP95 baseline{b:.2f}ms after{a:.2f}ms) 如果 P95 從 300ms 漲到 500ms就要懷疑代理是否在高頻路徑里加了不需要的同步邏輯或重復(fù)查詢。5.3 回滾方案要在合入之前寫好AI 生成代碼合入之前應(yīng)該先回答一個(gè)問題如果線上出了問題怎么最快回到上一個(gè)穩(wěn)定版本。推薦三種回滾手段按速度排序手段速度適用場景功能開關(guān)秒級新功能可以整體關(guān)閉版本回滾分鐘級代碼變更和數(shù)據(jù)庫兼容補(bǔ)丁修復(fù)半小時(shí)以上問題定位明確、影響面小同時(shí)要注意數(shù)據(jù)庫回滾。如果代理生成的代碼包含數(shù)據(jù)庫遷移不能只回滾代碼而不回滾數(shù)據(jù)。例如新增了一個(gè)非空字段代碼回滾后舊代碼不會寫這個(gè)字段而數(shù)據(jù)庫又要求它非空就會出現(xiàn)線上寫入失敗。這類問題必須在評審階段提前規(guī)避盡量讓數(shù)據(jù)庫變更向后兼容。5.4 把線上問題反哺給規(guī)則文件每一次由 AI 生成代碼引發(fā)的線上故障都是規(guī)則文件迭代的素材。問題修復(fù)后應(yīng)回答這幾個(gè)問題規(guī)則文件里缺少了哪條約束任務(wù)描述模板里缺少了哪個(gè)驗(yàn)收標(biāo)準(zhǔn)評審清單里漏掉了哪個(gè)檢查點(diǎn)例如如果代理因?yàn)橥痰袅?Redis 連接異常導(dǎo)致緩存雪崩那就應(yīng)該把這條加入規(guī)則## 編碼約束 - 所有 Redis 調(diào)用必須設(shè)置超時(shí)時(shí)間 - Redis 異常必須記錄日志并返回降級響應(yīng)不允許吞掉異常規(guī)則文件不是一次性寫好的它是團(tuán)隊(duì)和 AI 協(xié)作過程的“沉淀物”。出現(xiàn)一次問題就補(bǔ)一條規(guī)則一段時(shí)間后代理能犯的錯(cuò)誤會明顯變少。6. 常見失敗模式與排查路徑6.1 問題現(xiàn)象、原因、檢查方式對照表實(shí)踐中AI 編程代理相關(guān)的問題通常集中在幾個(gè)固定場景。下面這張表可以直接用于團(tuán)隊(duì)內(nèi)部排查問題現(xiàn)象常見原因檢查方式處理建議代理生成大量無關(guān)代碼任務(wù)描述沒有明確禁止目錄用git diff --stat查看文件范圍補(bǔ)充禁止修改列表設(shè)定范圍檢查腳本測試全綠但線上出錯(cuò)測試斷言被改弱或沒有覆蓋真實(shí)業(yè)務(wù)分支抽查關(guān)鍵斷言故意破壞實(shí)現(xiàn)看是否變紅要求測試必須驗(yàn)證業(yè)務(wù)結(jié)果代理反復(fù)執(zhí)行命令失敗本地命令和 CI 命令不一致或依賴版本沖突對比AGENTS.md命令與 CI 配置統(tǒng)一命令先跑通基線代理一直修改同一個(gè)問題上下文里缺少錯(cuò)誤信息或根因提示查看代理的執(zhí)行日志和最后一次報(bào)錯(cuò)補(bǔ)充日志或錯(cuò)誤信息到任務(wù)上下文規(guī)則文件沒有生效文件名不在代理支持的范圍內(nèi)或路徑不對查看代理讀取的文件列表使用標(biāo)準(zhǔn)AGENTS.md文件名代理改壞公共函數(shù)對調(diào)用方感知不足檢查公共 API 變更 diff對公共模塊單獨(dú)設(shè)置評審人和保護(hù)分支6.2 典型排查示例代理完成任務(wù)但 CI 失敗假設(shè)你收到一個(gè)代理分支的 PRCI 報(bào)錯(cuò)顯示類型檢查失敗但代理在任務(wù)描述里聲稱“所有檢查通過”??梢园聪旅孢@條鏈路排查第一步確認(rèn)它改了哪些文件git diff --name-only origin/main...HEAD第二步檢查是否改動了AGENTS.md里聲明過的依賴或配置git diff origin/main...HEAD -- pyproject.toml requirements.txt第三步在本地用 CI 相同的命令復(fù)現(xiàn)rm -rf .venv python -m venv .venv source .venv/bin/activate pip install -e .[dev] mypy app/第四步如果本地能復(fù)現(xiàn)類型錯(cuò)誤讓代理重新修復(fù)時(shí)把錯(cuò)誤信息完整放到 prompt 中類型檢查失敗錯(cuò)誤如下 app/api/users.py:42: error: User has no attribute name 請修復(fù)類型問題不要修改 users.py 之外的文件。這個(gè)流程的關(guān)鍵是按順序排查先看輸入任務(wù)和規(guī)則再看環(huán)境依賴和命令最后看輸出代碼和錯(cuò)誤。不要一上來就懷疑模型能力大多數(shù)問題其實(shí)出在流程和上下文上。7. 從試點(diǎn)到制度化讓 AI 編程代理真正可控7.1 先在小范圍試點(diǎn)不要全團(tuán)隊(duì)鋪開AI 編程代理落地不適合“一刀切”。建議先挑選 2 到 3 個(gè)具備以下特征的項(xiàng)目有完整的自動化測試至少覆蓋核心用例。構(gòu)建時(shí)間相對短在 10 分鐘內(nèi)可以完成。技術(shù)棧統(tǒng)一依賴清晰。團(tuán)隊(duì)成員愿意接受新的評審方式。試點(diǎn)期間定義兩個(gè)核心指標(biāo)不要追求過度復(fù)雜的度量AI 分支被合入的比例反映代理產(chǎn)出是否有可用性。AI 分支引發(fā) CI 失敗或線上問題的次數(shù)反映代理是否穩(wěn)定。每周復(fù)盤一次重點(diǎn)看失敗案例而不是成功案例。成功案例只能說明流程沒被觸發(fā)失敗案例才能暴露流程缺口。7.2 將規(guī)則、模板和評審清單固化為團(tuán)隊(duì)規(guī)范當(dāng)試點(diǎn)驗(yàn)證有效后再把流程制度化把AGENTS.md納入倉庫根目錄評審范圍規(guī)則變更需要走 MR。把任務(wù)描述模板、評審模板上傳到團(tuán)隊(duì)文檔庫或 MR 模板中。在 CI 中增加代理分支專用的范圍檢查任務(wù)。讓團(tuán)隊(duì)每個(gè)成員都學(xué)會寫“可執(zhí)行的任務(wù)描述”而不是一句話需求。在評審 AI 生成代碼時(shí)要求提交者附帶代理的自檢日志。制度化不是為了增加流程負(fù)擔(dān)而是為了讓每一次代理使用都產(chǎn)生可追蹤、可復(fù)測、可改進(jìn)的記錄。沒有記錄的流程無法沉淀經(jīng)驗(yàn)。7.3 可復(fù)用的落地檢查清單下面是一份可以直接打印出來貼在工位旁的檢查清單也可以作為 MR 模板的一部分。接入前檢查[ ] 倉庫能穩(wěn)定通過 build、test、lint[ ]AGENTS.md已包含技術(shù)棧、命令、目錄邊界、禁止修改項(xiàng)[ ] CI 已有獨(dú)立的代理分支校驗(yàn) job[ ] 已知哪些任務(wù)類型適合代理哪些不適合每次任務(wù)開始時(shí)[ ] 任務(wù)描述包含目標(biāo)、涉及文件、禁止修改項(xiàng)、驗(yàn)收標(biāo)準(zhǔn)[ ] 任務(wù)粒度控制在可評審的 diff 范圍內(nèi)[ ] 代理在獨(dú)立分支上工作合并前檢查[ ] 對比git diff --stat確認(rèn)沒有越界文件[ ] 自動檢查全部通過[ ] 評審清單中的錯(cuò)誤處理、測試有效性、公共接口影響已確認(rèn)[ ] 數(shù)據(jù)庫變更確認(rèn)向后兼容[ ] 回滾方案已準(zhǔn)備好上線后觀察[ ] 錯(cuò)誤率、P95 耗時(shí)、核心業(yè)務(wù)指標(biāo)與基線對比[ ] 發(fā)現(xiàn)問題先回滾再定位根因[ ] 將根因和預(yù)防措施更新到AGENTS.md這一套流程做完AI 編程代理會在倉庫里留下大量高質(zhì)量代碼同時(shí)把風(fēng)險(xiǎn)控制在可接受的范圍。它不會自動寫出完美代碼但團(tuán)隊(duì)可以通過流程讓“垃圾代碼”很難通過每一道關(guān)卡。Figma 工程師的分享之所以值得借鑒不是因?yàn)?Figma 使用了某個(gè)特別的工具而是因?yàn)樗?AI 編程代理當(dāng)作系統(tǒng)中的一個(gè)組件來治理。任何團(tuán)隊(duì)都可以用同樣的思路先設(shè)置規(guī)則再開放權(quán)限先用小范圍驗(yàn)證再擴(kuò)大使用先保證能回滾再追求效率。方向?qū)α舜a質(zhì)量自然會向好的方向收斂。