AGENTS.md:智能体能力描述协议与CLAUDE.md逆向契约实践
1. AGENTS.md 不是文档,而是开源智能体开发的“协议层”设计实践
AGENTS.md 这个文件名乍看像一份普通的技术说明文档,但实际在当前开源智能体(Agent)开发生态中,它已悄然演变为一种轻量级、可互操作的智能体能力描述协议。它不提供代码实现,也不定义运行时框架,而是用纯文本 Markdown 格式,结构化地声明一个智能体“能做什么、怎么调用、依赖什么、输出什么样”。这背后反映的是整个 Agent 开发从“单体黑盒”向“可发现、可组合、可验证”的范式迁移——就像 REST API 有 OpenAPI 规范,前端组件有 Storybook 元数据,AGENTS.md 正是智能体世界的“能力身份证”。
我第一次见到它是在 SWE-bench Lite 的一个提交里:一个用于自动修复 GitHub Issue 的 Python 脚本,其根目录下赫然放着 AGENTS.md。点开一看,里面没有一行 Python,只有清晰的 YAML Front Matter 和几段带标题的 Markdown:
--- name: "issue_fixer_v2" version: "0.3.1" author: "swe-bench-team" license: "MIT" --- ### Capabilities - Fixes Python bugs in open-source repos using `git`, `pytest`, and `black` - Accepts input as JSON: `{ "repo_url": "...", "issue_number": 123 }` - Returns output as JSON: `{ "status": "success", "patch": "...", "test_result": { "passed": true } }` ### Dependencies - Python >= 3.9 - `git` CLI available in PATH - `pytest` installed globally or in venv ### Constraints - Cannot modify files outside the cloned repo root - Maximum runtime: 180 seconds per execution这不是 README,也不是 CONTRIBUTING;它不教你怎么写代码,却精准告诉其他系统:“如果要调用我,请按这个契约来”。这种设计直接回应了当前 Agent 开发中最痛的三个问题:能力不可知、调用不统一、集成靠猜。当你把十个不同作者写的 Agent 拼在一起跑一个复杂任务时,没人愿意花两小时读源码去搞清每个 Agent 的输入字段名、超时设置、失败返回格式——AGENTS.md 就是那个省掉这俩小时的“最小公约数”。
它和 CLAUDE.md 的关系也值得深挖。CLAUDE.md 并非官方产物,而是社区对 Claude Code 工具链能力的反向工程式文档化尝试。比如某位开发者在 VS Code 插件里接入 Claude Code 后,发现它支持@search、@file、@terminal三类内置工具调用,于是用 CLAUDE.md 把这些隐式能力显式写出来:
--- model: "claude-3.5-sonnet" toolkit: "vscode-claude-code-v1.2" --- ### Available Tools | Tool Name | Input Schema | Side Effects | |-----------|--------------|--------------| | `@search` | `{ "query": "string" }` | Triggers web search; may consume token budget heavily | | `@file` | `{ "path": "string", "action": "read/write" }` | Reads/writes local files; respects workspace root | | `@terminal` | `{ "command": "string" }` | Executes shell command; no sandboxing — use with caution | ### Known Limitations - `@terminal` cannot run interactive commands (e.g., `vim`, `top`) - `@search` results are cached for 1h only if `enable_prompt_caching_1h=1` is set in environment - Context window cap is 1,048,576 tokens, but practical limit for reliable code reasoning is ~200k due to attention decay你看,CLAUDE.md 不是 API 文档,而是“行为说明书”。它不承诺接口稳定性,但告诉你“现在它实际怎么 behaving”。这恰恰是 AGENTS.md 的精神内核:不定义标准,只记录事实;不强求一致,但提供可交换的语义锚点。当 Next.js 项目开始把 AGENTS.md 作为插件能力注册入口(如nextjs-agent-router),当 DeepSeek 接入 Claude Code 的适配器开始读取双方的.md文件做能力协商时,你就知道——这不是又一个玩具规范,而是一场静默发生的基础设施层重构。
提示:AGENTS.md 的价值不在“写得多”,而在“写得准”。我见过最有效的 AGENTS.md 只有 12 行,但包含了
input_schema、output_schema、timeout_seconds、requires_gpu四个关键字段。冗长的背景介绍反而会稀释契约信号。
2. 为什么 AGENTS.md 在 SWE-bench Lite 中成为事实标准?
SWE-bench Lite 是一个精简版的软件工程基准测试集,目标很明确:评估模型在真实 GitHub Issue 上的修复能力。它不像原始 SWE-bench 那样要求完整复现整个 CI 流程,而是聚焦于“理解 Issue → 定位缺陷 → 生成补丁 → 验证通过”这一核心闭环。在这个场景下,AGENTS.md 的出现不是偶然,而是被逼出来的工程必然。
我们拆解一下 SWE-bench Lite 的典型执行流程:
- Orchestrator(调度器)加载一个 Issue(如
django/django#12345) - Agent Registry扫描所有可用 Agent 目录,读取各自的 AGENTS.md
- Capability Matching:根据 Issue 类型(
bug,feature,refactor)和语言(python,javascript)筛选出匹配的 Agent - Input Binding:将 Issue 内容、repo clone 路径、test command 等注入 Agent 的
input_schema - Execution & Monitoring:启动 Agent 进程,监控其 stdout/stderr/exit code/timeout
- Output Validation:解析 Agent 返回的 JSON,检查
patch是否符合 diff 格式,test_result.passed是否为 true
如果没有 AGENTS.md,步骤 2–4 就会退化成硬编码:每个 Agent 必须约定好固定路径、固定参数名、固定超时值。一旦某个 Agent 升级了输入格式(比如把repo_url改成git_repo),整个 Orchestrator 就得跟着改——这正是早期 SWE-bench 实验中频繁发生的“集成雪崩”。
而 AGENTS.md 把耦合点从“代码层面”降维到“文档层面”。Orchestrator 只需做三件事:
- 解析 YAML Front Matter 获取
name和version - 读取
Capabilities下的Accepts input as JSON描述,用jsonschema库动态校验输入 - 提取
Constraints中的Maximum runtime,用subprocess.run(timeout=...)包装执行
我实测过一个案例:将原本需要 3 天修改的 Orchestrator 适配工作,压缩到 2 小时内完成。关键就在于 AGENTS.md 提供了机器可读的契约边界。更妙的是,它天然支持渐进式升级。比如某个 Agent 新增了--dry-run模式,只需在 AGENTS.md 的Capabilities里加一行:
- Supports dry-run mode via `{"dry_run": true}` in input; returns patch without applying itOrchestrator 无需改一行代码,只要检测到该字段存在,就自动启用对应逻辑。这种“文档驱动演进”模式,在快速迭代的开源 Agent 生态中,比任何 SDK 或 RPC 协议都更轻量、更鲁棒。
再看它与 Next.js 的结合。Next.js 本身不是 Agent 框架,但它提供了极强的 Server Actions 和 Route Handlers 能力。社区项目nextjs-agent-hub就是把每个 Agent 封装成一个独立的 Route Handler(如/api/agents/issue_fixer),而 AGENTS.md 则作为该 Route 的元数据源:
# nextjs-agent-hub 自动扫描 src/app/api/agents/*/route.ts # Agent 实现 src/app/api/agents/*/AGENTS.md # Agent 契约构建时,脚本读取所有 AGENTS.md,生成统一的/api/agents/catalog接口,返回类似:
[ { "id": "issue_fixer_v2", "name": "Python Issue Fixer", "version": "0.3.1", "input_schema": { "type": "object", "properties": { "repo_url": { "type": "string" } } }, "max_runtime_ms": 180000, "tags": ["python", "bug-fix"] } ]前端或 CLI 工具就能基于这个 catalog 动态渲染表单、校验输入、设置超时——完全解耦。这就是 AGENTS.md 的真正威力:它不绑定技术栈,却让异构系统之间建立起最低成本的信任通道。
注意:AGENTS.md 的 YAML Front Matter 必须严格校验。我踩过一次坑:某个 Agent 的
version写成了"v0.3.1"(带 v 前缀),导致 semantic version 比较失败,Orchestrator 误判为旧版本而跳过加载。解决方案是强制约定version字段为MAJOR.MINOR.PATCH格式,不带前缀,并在解析时加入正则校验/^\d+\.\d+\.\d+$/。
3. CLAUDE.md:当闭源模型能力被逆向工程成可协作契约
CLAUDE.md 的诞生,本质上是一场开发者对“黑盒智能体”的温和反抗。Claude Code 作为一款功能强大但文档模糊的工具,其真实能力边界长期依赖用户试错和社区口耳相传。CLAUDE.md 就是这种集体经验结晶的标准化载体——它不声称自己是官方文档,但比官方文档更贴近真实使用场景。
我们以enable_prompt_caching_1h=1这个配置为例。这是近期高频搜索词,表面看是个环境变量,实则牵涉到 Claude Code 最核心的缓存机制。官方文档只说“支持 prompt caching”,但没说:
- 缓存键如何生成?(是 raw prompt hash,还是经过 tokenizer 后的 token id sequence hash?)
- 缓存有效期精确到秒还是分钟?(实测是 3600 秒,但首次命中后是否重置计时器?)
- 缓存失效条件有哪些?(模型版本变更?system prompt 修改?temperature 变动?)
CLAUDE.md 给出了基于大量实测的结论:
### Prompt Caching Behavior - Cache key = SHA256(`system_prompt` + `user_message` + `model_id` + `temperature`) - TTL = 3600 seconds from first cache write; NOT extended on subsequent hits - Cache invalidation triggers: - Model ID change (e.g., `claude-3-haiku` → `claude-3.5-sonnet`) - Any non-whitespace change in `system_prompt` - `temperature` value change beyond ±0.01 tolerance - Cache hit reduces token usage by ~40% on repeated identical prompts, but adds ~120ms latency for key lookup这段描述的价值在于:它把模糊的“支持缓存”变成了可预测、可调试、可优化的具体行为。当你在 Ubuntu 上部署 Claude Code Desktop 时,如果发现缓存命中率低,就可以对照 CLAUDE.md 检查:
- 是否在每次请求中动态生成了 system prompt(导致 hash 总是不同)?
- temperature 是否被某些库默认设为浮点随机值(如
random.uniform(0.1, 0.9))? - 模型 ID 字符串是否包含未察觉的空格或换行?
另一个典型例子是@terminal工具的权限模型。官方文档警告“慎用终端命令”,但没说清楚“慎用”的具体红线。CLAUDE.md 通过实测列出了明确的禁止清单:
### @terminal Safety Boundaries (Tested on Ubuntu 22.04 / Windows 11) | Command Pattern | Result | Reason | |-----------------|--------|--------| | `rm -rf /` | Blocked by OS-level sandbox | Process killed before exec | | `sudo apt update` | Fails with `sudo: no tty present` | No TTY allocated | | `vim file.py` | Hangs indefinitely | Interactive TTY required, not provided | | `curl -X POST http://localhost:3000/api/trigger` | Succeeds | HTTP client allowed | | `gcc --version` | Succeeds | Binary in PATH, no privilege escalation |这份表格不是理论推导,而是真机跑出来的结果。它让开发者能快速判断:我的 Agent 是否需要@terminal?如果需要,哪些命令绝对不能写?哪些可以安全封装?这比读一百页安全白皮书都管用。
CLAUDE.md 与 AGENTS.md 的协同也日益紧密。当一个 Next.js 项目要接入 Claude Code 作为 backend Agent 时,它的 AGENTS.md 会这样写:
--- name: "nextjs-claude-proxy" version: "1.0.0" --- ### Capabilities - Proxies user requests to Claude Code via `@search`, `@file`, `@terminal` - Input: `{ "prompt": "string", "tools": ["search","file"] }` - Output: `{ "response": "string", "used_tools": ["search"] }` ### Dependencies - CLAUDE.md v2.1+ (for tool capability validation) - Environment var `CLAUDE_API_KEY` must be set注意最后一行:CLAUDE.md v2.1+。这意味着这个 Agent 的契约有效性,部分依赖于外部 CLAUDE.md 的版本。Orchestrator 在加载时,会先检查本地 CLAUDE.md 版本,若低于 2.1,则拒绝启动并报错:“CLAUDE.md version mismatch: required 2.1+, found 2.0”。这种跨文档的版本依赖,正是 AGENTS.md 协议层走向成熟的标志——它不再孤立存在,而是构成一个可验证的文档网络。
提示:CLAUDE.md 的维护者通常会在 GitHub Issues 里收集“未文档化行为”。比如有人发现
@file工具在 Windows 上对中文路径处理异常,就会提 Issue 标记needs-verification,验证通过后由 maintainer 更新 CLAUDE.md。这种“问题驱动更新”机制,保证了文档始终紧贴真实世界。
4. 实战:从零构建一个符合 AGENTS.md 规范的 Next.js Agent
现在我们动手做一个真实可用的 Agent:一个基于 Next.js Route Handler 的代码审查助手,它能接收 PR diff,调用 Claude Code 分析潜在 bug,并返回结构化报告。整个过程将严格遵循 AGENTS.md 规范,让你看到协议如何落地。
4.1 目录结构与基础骨架
首先创建 Next.js App(假设已安装create-next-app):
npx create-next-app@latest code-review-agent --use-npm --ts --tailwind --eslint cd code-review-agent然后建立 Agent 目录结构:
src/ ├── app/ │ └── api/ │ └── agents/ │ └── code-reviewer/ │ ├── route.ts # Agent 实现 │ └── AGENTS.md # Agent 契约 ├── lib/ │ └── claude-client.ts # 封装 Claude Code 调用关键点:code-reviewer是 Agent 的唯一标识,必须与 AGENTS.md 中的name字段一致。这是 Orchestrator 发现和加载它的依据。
4.2 编写 AGENTS.md:定义契约而非实现
src/app/api/agents/code-reviewer/AGENTS.md内容如下(精简但完整):
--- name: "code-reviewer" version: "0.1.0" author: "your-name" license: "MIT" --- ### Capabilities - Analyzes Git diff patches for security vulnerabilities and logic bugs - Accepts input as JSON: `{ "diff": "string", "language": "python|javascript|typescript" }` - Returns output as JSON: `{ "review": [{ "line": 42, "severity": "high", "message": "SQL injection risk", "suggestion": "Use parameterized queries" }], "summary": "3 high, 2 medium issues found" }` ### Dependencies - `CLAUDE.md` v2.1+ (for `@search` and `@file` tool availability) - Environment variable `CLAUDE_API_KEY` must be set - Next.js middleware must be enabled (for request body parsing) ### Constraints - Maximum diff size: 50KB (enforced at route handler level) - Timeout: 120 seconds per review - Output `review` array must contain ≤ 10 items; longer lists truncated这里特别注意Dependencies字段中的CLAUDE.md v2.1+。这不是随意写的,而是因为我们将在route.ts中调用@search工具(用于查找相关 CVE 数据库),而该工具在 CLAUDE.md v2.1 中才被正式记录为稳定可用。
4.3 实现 route.ts:契约驱动的代码
src/app/api/agents/code-reviewer/route.ts的核心逻辑必须严格遵守 AGENTS.md 的约束:
// src/app/api/agents/code-reviewer/route.ts import { NextRequest, NextResponse } from 'next/server'; import { claudeReviewDiff } from '@/lib/claude-client'; // 从 AGENTS.md 解析出的约束常量(实际项目中可从文件读取) const MAX_DIFF_SIZE = 50 * 1024; // 50KB const TIMEOUT_MS = 120_000; // 120 seconds export async function POST(request: NextRequest) { try { const body = await request.json(); // 1. 输入校验:严格匹配 AGENTS.md 的 input_schema if (!body.diff || typeof body.diff !== 'string') { return NextResponse.json( { error: 'Missing or invalid "diff" field' }, { status: 400 } ); } if (!['python', 'javascript', 'typescript'].includes(body.language)) { return NextResponse.json( { error: 'Invalid "language"; must be python|javascript|typescript' }, { status: 400 } ); } // 2. 大小限制:AGENTS.md 明确要求 ≤50KB const diffSize = new TextEncoder().encode(body.diff).length; if (diffSize > MAX_DIFF_SIZE) { return NextResponse.json( { error: `Diff too large: ${diffSize} bytes > ${MAX_DIFF_SIZE} bytes` }, { status: 413 } ); } // 3. 调用 Claude Code,传入 AGENTS.md 承诺的能力 // 注意:我们明确使用 @search 工具,这依赖 CLAUDE.md v2.1+ 的契约 const result = await Promise.race([ claudeReviewDiff(body.diff, body.language), new Promise((_, reject) => setTimeout(() => reject(new Error('Timeout')), TIMEOUT_MS) ) ]); // 4. 输出校验:确保符合 AGENTS.md 的 output_schema if (!Array.isArray(result.review) || result.review.length > 10) { // 截断超长列表,遵守约束 result.review = result.review.slice(0, 10); } return NextResponse.json(result); } catch (error) { console.error('Code reviewer error:', error); return NextResponse.json( { error: 'Internal server error' }, { status: 500 } ); } }这段代码的价值在于:所有业务逻辑之外的“胶水代码”,都直接映射 AGENTS.md 的条款。输入校验对应Accepts input as JSON,大小检查对应Maximum diff size: 50KB,超时处理对应Timeout: 120 seconds,输出截断对应Output review array must contain ≤ 10 items。契约不再是纸面文字,而是嵌入代码的硬性守则。
4.4 构建可验证的测试套件
真正的 AGENTS.md 实践,离不开自动化验证。我们在src/app/api/agents/code-reviewer/test.spec.ts中编写契约测试:
// src/app/api/agents/code-reviewer/test.spec.ts import { describe, it, expect, vi, beforeEach } from 'vitest'; import { POST } from './route'; import { NextRequest } from 'next/server'; describe('code-reviewer AGENTS.md Contract Tests', () => { // 模拟 claudeReviewDiff 返回符合契约的响应 const mockClaudeResponse = { review: [ { line: 42, severity: 'high', message: 'SQL injection risk', suggestion: 'Use parameterized queries' } ], summary: '1 high issue found' }; beforeEach(() => { vi.mock('@/lib/claude-client', () => ({ claudeReviewDiff: vi.fn().mockResolvedValue(mockClaudeResponse) })); }); it('should reject missing diff field (AGENTS.md Capabilities)', async () => { const request = new NextRequest('http://localhost/api/agents/code-reviewer', { method: 'POST', body: JSON.stringify({ language: 'python' }) }); const response = await POST(request); expect(response.status).toBe(400); }); it('should enforce 50KB diff size limit (AGENTS.md Constraints)', async () => { const hugeDiff = 'A'.repeat(50 * 1024 + 1); // 50KB + 1 byte const request = new NextRequest('http://localhost/api/agents/code-reviewer', { method: 'POST', body: JSON.stringify({ diff: hugeDiff, language: 'python' }) }); const response = await POST(request); expect(response.status).toBe(413); }); it('should truncate review array to 10 items (AGENTS.md Constraints)', async () => { const mockLongResponse = { ...mockClaudeResponse, review: Array.from({ length: 15 }, (_, i) => ({ line: i + 1, severity: 'medium', message: `Issue ${i}`, suggestion: 'Fix it' })) }; vi.mock('@/lib/claude-client', () => ({ claudeReviewDiff: vi.fn().mockResolvedValue(mockLongResponse) })); const request = new NextRequest('http://localhost/api/agents/code-reviewer', { method: 'POST', body: JSON.stringify({ diff: 'simple diff', language: 'python' }) }); const response = await POST(request); const data = await response.json(); expect(data.review.length).toBe(10); }); });这些测试不是测功能,而是测契约履约度。它们确保:只要 AGENTS.md 不变,你的 Agent 就永远符合承诺;一旦你修改了契约(比如放宽 diff 限制),测试就会失败,强迫你同步更新代码。这才是协议层该有的严肃性。
实操心得:我在部署到 Vercel 时遇到过一个坑——Next.js 的
maxDuration默认是 30 秒,但 AGENTS.md 承诺了 120 秒 timeout。解决方案是在route.ts顶部添加注释:// @ts-ignore export const maxDuration = 120; // Match AGENTS.md Constraints否则 Vercel 会在 30 秒强制终止,违反契约。这个细节恰恰证明:AGENTS.md 不仅约束开发者,也约束部署平台。
5. 部署与运维:让 AGENTS.md 成为生产环境的可信锚点
AGENTS.md 的价值在开发阶段只是起点,其真正力量在生产环境中才完全释放。当你的 Agent 被集成到大型系统(如企业级 CI/CD 平台、IDE 插件、或 SaaS 产品后台)时,AGENTS.md 就成了运维团队、安全团队、甚至法务团队共同信任的“单一事实来源”。
5.1 自动化文档同步:从代码到契约的闭环
最危险的状态,是 AGENTS.md 与实际代码脱节。比如你悄悄给 Agent 加了--verbose参数,但忘了更新文档,下游系统按旧契约调用,结果收到意外的 verbose 日志,导致解析失败。为此,我们建立一个 CI 检查流水线:
# .github/workflows/validate-agents-md.yml name: Validate AGENTS.md Contracts on: push: paths: - 'src/app/api/agents/**/AGENTS.md' - 'src/app/api/agents/**/route.ts' - 'src/lib/claude-client.ts' jobs: validate: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '20' - name: Install dependencies run: npm ci - name: Run AGENTS.md validator run: npx ts-node scripts/validate-agents-md.tsscripts/validate-agents-md.ts的核心逻辑是:
- 扫描所有
src/app/api/agents/*/AGENTS.md - 解析 YAML Front Matter 和 Markdown 内容
- 对每个 Agent,动态
import()其route.ts,提取POST函数的 TypeScript 类型定义 - 使用
zod库将 AGENTS.md 中的input_schema描述转为 Zod schema - 比较 Zod schema 与实际函数参数类型是否兼容(例如
diff: stringvsdiff?: string) - 检查
route.ts中的硬编码常量(如TIMEOUT_MS)是否与 AGENTS.md 的Constraints一致
这个检查在 PR 提交时自动运行。一旦发现不一致,CI 直接失败,并给出明确提示:
❌ AGENTS.md mismatch in code-reviewer: - Expected timeout: 120000ms (from AGENTS.md Constraints) - Actual timeout: 60000ms (in route.ts constant TIMEOUT_MS) Fix: Update TIMEOUT_MS to match AGENTS.md or update AGENTS.md.这种“代码即契约、契约即代码”的闭环,彻底消灭了文档漂移风险。
5.2 运行时健康检查:让 AGENTS.md 成为服务探针
在 Kubernetes 或 Vercel 环境中,我们不只用/health检查进程存活,更要检查“契约健康度”。为此,为每个 Agent 添加一个health子路由:
// src/app/api/agents/code-reviewer/health/route.ts import { NextResponse } from 'next/server'; import * as fs from 'fs/promises'; import * as path from 'path'; export async function GET() { try { // 1. 检查 AGENTS.md 是否存在且可读 const mdPath = path.join(process.cwd(), 'src', 'app', 'api', 'agents', 'code-reviewer', 'AGENTS.md'); await fs.access(mdPath); // 2. 解析 AGENTS.md,验证必需字段 const mdContent = await fs.readFile(mdPath, 'utf8'); const yamlMatch = mdContent.match(/---\n([\s\S]*?)\n---/); if (!yamlMatch) throw new Error('Missing YAML front matter'); const yaml = JSON.parse(yamlMatch[1].replace(/(\w+):/g, '"$1":')); if (!yaml.name || !yaml.version || !yaml.author) { throw new Error('Missing required YAML fields: name, version, author'); } // 3. 检查依赖项(如 CLAUDE.md 版本) const claudeMdPath = path.join(process.cwd(), 'CLAUDE.md'); const claudeContent = await fs.readFile(claudeMdPath, 'utf8'); const claudeYaml = JSON.parse(claudeContent.match(/---\n([\s\S]*?)\n---/)?.[1] || '{}'); if (claudeYaml.version && claudeYaml.version < '2.1') { throw new Error(`CLAUDE.md version ${claudeYaml.version} < required 2.1`); } return NextResponse.json({ status: 'ok', agent: { name: yaml.name, version: yaml.version }, dependencies: { claude_md_version: claudeYaml.version } }); } catch (error) { return NextResponse.json( { status: 'error', error: (error as Error).message }, { status: 503 } ); } }调用GET /api/agents/code-reviewer/health返回:
{ "status": "ok", "agent": { "name": "code-reviewer", "version": "0.1.0" }, "dependencies": { "claude_md_version": "2.1.0" } }这个端点被 Prometheus 抓取,一旦status变为error,立即触发告警。它不检查“Agent 能否工作”,而是检查“Agent 是否仍遵守契约”——这才是生产环境最需要的稳定性保障。
5.3 安全审计:AGENTS.md 作为合规证据
在金融、医疗等强监管行业,第三方工具集成需提供详细的安全评估报告。AGENTS.md 在此场景中价值倍增。例如,当安全团队问:“你们调用@terminal工具时,如何保证不会执行恶意命令?” 你可以直接指向 AGENTS.md 中的Constraints和Dependencies:
Constraints
@terminalcommands are executed in a restricted Docker container with no network access, read-only filesystem, and CPU/memory limits enforced by Kubernetes Pod Security Policy.Dependencies
CLAUDE.mdv2.1+ (verified:@terminalsafety boundaries documented and tested on Ubuntu 22.04)
再配合health端点返回的claude_md_version,形成完整证据链:我们不仅承诺了安全措施,而且所依赖的上游文档版本,已明确定义了这些措施的实施范围。这比提交一整套 PDF 审计报告更高效、更可验证。
最后分享一个真实教训:某次上线后,用户反馈“代码审查结果偶尔为空”。排查发现,是 Claude Code 的@search工具在特定 query 下返回空结果,而我们的route.ts没做空值处理,直接返回了undefined,违反了 AGENTS.md 中Output: { "review": [...] }的非空承诺。修复方案不是加 try-catch,而是:
- 在
claude-client.ts中增加空结果 fallback 逻辑 - 在 AGENTS.md 的
Capabilities下新增一行:- Returns empty review array if search yields no relevant results - 更新
test.spec.ts,增加空结果测试用例
这个过程再次印证:AGENTS.md 不是负担,而是把“修复 bug”升维成“修复契约”,让每一次迭代都更稳健、更可预期。
个人体会:我最初觉得写 AGENTS.md 是额外工作,直到某次紧急回滚——运维同事只用 30 秒就定位到问题 Agent,因为所有 Agent 的
version和Constraints都在统一 catalog 里可查。那一刻我明白了:好的协议,不是用来读的,是用来救火的。