第 7 講:可寫型子代理的 permission 與 Edit/Write 配置骨架)
1. 可寫型子代理為什么最容易翻車Claude Code 的子代理體系里只讀型Read/Grep/Glob和可執(zhí)行型Bash 白名單都不會改變項目狀態(tài)跑錯了重跑一次就行??蓪懶妥哟硎堑谝粋€真正會改文件的類別——Edit 和 Write 工具一旦放開AI 就能直接修改源碼、覆蓋配置、誤刪測試。寫錯了不是重跑一下能解決的得 git revert 甚至手工修復(fù)。我在實際項目里踩過的坑是給子代理開了 Edit/Write 但沒配 permission 的 ask 機制結(jié)果它一次性改了 8 個文件彈窗彈了 8 次我嫌煩全點了放行事后發(fā)現(xiàn)其中一個改動把src/billing/下的金額計算邏輯改錯了。這就是批量寫的典型風(fēng)險——diff 太多人根本 review 不過來。所以可寫型子代理的落地核心不是能不能寫而是寫到哪、寫多少、誰來批。這篇聚焦三件事在settings.json里為子代理聲明 permission 白名單、開放 Edit/Write 并限定目錄、通過統(tǒng)一 Key/API 通道接入后觸發(fā)一次真實寫入并核對結(jié)果。適合已經(jīng)在用 Claude Code 做工程化、準備把子代理從只讀升級到可寫的開發(fā)者。2. 前置統(tǒng)一 Key/API 通道與子代理目錄在配 permission 之前先確認兩件事模型通道和子代理文件位置。模型通道方面我用的是 TaoToken 的統(tǒng)一接入方式一個 Key 走所有模型不用為每個子代理單獨配 endpoint。官網(wǎng)入口在 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 基址是 https://taotoken.net/api 這個不加 UTM。拿到 Key 后在環(huán)境變量里設(shè)好export ANTHROPIC_BASE_URLhttps://taotoken.net/api export ANTHROPIC_API_KEYsk-你的Key子代理文件放在項目的.claude/agents/目錄下每個子代理一個.md文件frontmatter 里聲明 name、description、tools、model。permission 則統(tǒng)一寫在.claude/settings.json里按工具名分組用file_path正則做目錄級限定。注意permission 是工具層的硬約束子代理 system prompt 里的我只寫 docs/是軟約束。軟約束會被 AI 的順手優(yōu)化繞過硬約束不會。兩層都要有。3. 可復(fù)制的 settings.json 骨架下面這份骨架是我在多個項目里驗證過的直接改路徑就能用。核心思路是三層deny 絕對禁止、ask 寫前彈窗、allow 文檔安全區(qū)。{ permissions: { Edit: [ {file_path: migrations/.*, permission: deny}, {file_path: .*\\.env.*, permission: deny}, {file_path: .*secret.*, permission: deny}, {file_path: .*credential.*, permission: deny}, {file_path: src/billing/.*, permission: deny}, {file_path: src/.*\\.py, permission: ask}, {file_path: tests/.*\\.py, permission: ask}, {file_path: config/.*, permission: ask}, {file_path: docs/.*\\.md, permission: allow}, {file_path: README\\.md, permission: allow}, {file_path: CHANGELOG\\.md, permission: allow}, {file_path: .claude/drafts/.*, permission: allow} ], Write: [ {file_path: migrations/.*, permission: deny}, {file_path: .*\\.env.*, permission: deny}, {file_path: src/.*, permission: ask}, {file_path: docs/.*\\.md, permission: allow}, {file_path: .claude/drafts/.*, permission: allow} ] }, limits: { Edit: { max_files_per_call: 3, max_diff_lines_per_call: 200, warn_above_files: 5 } } }幾個關(guān)鍵點解釋一下。Edit 和 Write 分開配因為 Write 只應(yīng)該創(chuàng)建新文件如果目標已存在就該拒絕并提示改用 Edit。src/billing/配 deny 是因為金額相關(guān)代碼寫錯代價太高寧可讓 AI 報無權(quán)限也不要它碰。limits里的max_files_per_call: 3是防批量寫的關(guān)鍵——超過 3 個文件觸發(fā)額外警告逼你更仔細地 review。子代理的 frontmatter 里 tools 要顯式聲明 Edit 和 Write否則即使 permission 配了也不會生效--- name: doc-writer description: Update README, generate API docs from docstrings. Use when I say 更新文檔. tools: Read, Grep, Glob, Edit, Write model: haiku ---4. 驗證觸發(fā)一次寫入并核對結(jié)果配好之后必須做一次真實寫入驗證光看配置不算數(shù)。我用的驗證動作是讓 doc-writer 更新 README 的版本號。第一步在項目里對 Claude Code 說用 doc-writer 把 README 里的版本號從 1.2.3 更新到 1.3.0。預(yù)期行為是子代理讀取package.json拿到新版本號然后對README.md發(fā)起 Edit。第二步觀察彈窗。因為README.md配的是 allow理論上不該彈窗。如果彈了說明你的 permission 正則沒匹配上——檢查是不是寫成了README.md而實際路徑帶前綴。第三步核對文件變更git diff README.md應(yīng)該只看到版本號那一行變化。如果 diff 里出現(xiàn)了src/下的改動說明子代理角色漂移了需要回到 system prompt 里加硬邊界。第四步測試攔截。故意讓子代理改src/billing/amount.py預(yù)期是直接被 deny 攔下報無權(quán)限修改該路徑。如果它成功改了說明 deny 規(guī)則沒生效檢查正則里的轉(zhuǎn)義——src/billing/.*里的點號要寫成\\.。第五步測試 ask 機制。讓子代理改src/utils/helper.py預(yù)期彈窗展示想改什么、改到哪、改了幾行。這時候你可以選放行、拒絕或編輯后再放行。這一步驗證的是逐次審批是否真的在工作。5. 本篇常見錯排查錯誤一給了 Edit/Write 但沒配 ask等于讓 AI 自由改代碼。最隱蔽的坑是 frontmatter 寫了tools: Edit, Writesettings.json 里也配了 permission但 Edit 的 permission 寫成了 allow 而不是 ask。結(jié)果 AI 能自由改任何文件。判斷標準可寫子代理的 Edit/Write 必須配 ask且 file_path 維度要有 deny 兜底。只有 allow 沒有 ask立即停用。錯誤二批量寫的風(fēng)險被低估。permission 配了 ask 但沒配max_files_per_callAI 一次 Edit 10 個文件彈窗彈 10 次用戶嫌煩全放行ask 形同虛設(shè)。解決就是在 limits 里加文件數(shù)和 diff 行數(shù)限制超過閾值觸發(fā)額外警告。錯誤三角色漂移寫文檔時順手改了源碼。用戶說用 doc-writer 更新 README它跑著跑著順手優(yōu)化了src/里的 import 順序。修正方式是在 system prompt 里寫死硬邊界白名單 黑名單同時 permission 對src/配 deny 而不是 ask——AI 看到 deny 觸發(fā)我無權(quán)限角色漂移被工具層堵死。錯誤四沒有 Audit 日志寫錯了不知道誰改的。出事故時發(fā)現(xiàn)某文件被改但不知道是 AI 改的還是人改的、什么時候改的。解決是在 PostToolUse Hook 里配 audit 記錄每次 Edit/Write 都寫一條到.claude/audit.log不進 git。審計時直接查日志。#!/usr/bin/env bash TOOL_NAME$1 FILE_PATH$2 USER_DECISION$3 TIMESTAMP$(date -Iseconds) if [[ $TOOL_NAME Edit || $TOOL_NAME Write ]]; then echo $TIMESTAMP | $TOOL_NAME | $FILE_PATH | $USER_DECISION .claude/audit.log fi exit 06. 接入通道與后續(xù)動作可寫型子代理的模型調(diào)用走統(tǒng)一 Key 通道一個 Key 覆蓋所有子代理不用為每個 agent 單獨配 endpoint。如果你還沒配好 Key先去 API Keys 頁面生成https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 接入細節(jié)看文檔https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。驗證階段想快速試模型對話行為可以用模型對話頁面https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。如果你要把可寫子代理長期跑在編碼流程里建議上 Coding Plan額度更穩(wěn)https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。最后補一句實操經(jīng)驗permission 配好之后先拿一個不重要的倉庫跑一周觀察 audit 日志里 ask 的觸發(fā)頻率和放行率。如果放行率超過 90%說明你的 ask 閾值太松該收緊 file_path 正則了。