跳转到内容

为 Agent 设计代码库

传统代码库为人类开发者优化。AI Agent 有不同的需求——它们擅长模式匹配,但在隐式知识和分散上下文方面会遇到困难。本指南介绍如何设计”Agent 友好”的代码库。


方面人类优化Agent 优化
注释稀疏,假设有上下文明确的”为什么” + 同义词
文件大小1000+ 行 OK在 500 行处拆分
架构文档独立的 Wiki/Confluence嵌入 CLAUDE.md + ADR
约定口头传统,部落知识书面、可发现、有标签
测试原型可选关键——Agent 遵循测试
错误消息通用具体且带恢复提示

Netlify 提出的”Agent Experience”概念,是 DX(开发者体验)的 Agent 版本:

  1. Agent 能找到它需要的东西吗?(可发现性)
  2. 它能理解设计决策吗?(领域知识)
  3. 它能验证自己的工作吗?(测试 + 防护栏)
  4. 它能高效工作吗?(Token 预算)

推荐优化

  • 绿地项目(从头设计 Agent 友好)
  • 高频修改文件(业务逻辑、API 路由)
  • 大量使用 Agent 的团队(>50% 提交)

不需要优化

  • 稳定的遗留代码(不要仅为 Agent 重构)
  • 小脚本(<100 行,Agent 处理没问题)

选择有主见的框架来减少 Agent 的决策空间:

方面自定义架构有主见的框架
文件组织Agent 必须学习你的结构标准约定(如 Next.js app/、Rails MVC)
路由自定义逻辑,需要文档基于约定(文件 = 路由)
数据访问多种模式可能单一模式强制
CLAUDE.md 大小大(必须记录一切)小(约定已知)

举例

# 自定义架构(500+ 行 CLAUDE.md)
## File Organization
- API routes in `src/endpoints/`
- Business logic in `src/domain/`
- Data access in `src/repositories/`
... (大量自定义模式文档)
# Next.js(50 行 CLAUDE.md)
## Project Context
We use Next.js 14 with App Router.
... (最少上下文,其余是框架约定)

在 CLAUDE.md 中编码深层领域知识:

CLAUDE.md
## Domain Context
**Product**: SaaS platform for event management (B2B, enterprise)
**Business model**: Subscription-based, tiered pricing
## Design Principles
1. **Idempotency First**: All API mutations must be idempotent
2. **Eventual Consistency**: Calendar sync uses queue-based reconciliation
3. **Graceful Degradation**: If external API fails, store locally + retry
## Domain Terms
- **Event**: User-created calendar entry (our domain model)
- **Appointment**: External calendar system's term (Google/Outlook)
- **Sync Job**: Background process reconciling our DB with external calendars
## Gotchas
- Google Calendar API has 10 req/sec rate limit per user
- Outlook timezone handling is non-standard → use normalizeTimezone()
- Event deletion = soft delete (set deletedAt) for compliance audit trail
// Get user by ID
function getUserById(id: string) {
return db.users.findOne({ id });
}

docs/decisions/ 中存储 ADR 并从代码中引用:

// Soft delete per ADR-007. Never use db.events.delete()
// due to compliance requirements (GDPR audit trail).
async function deleteEvent(eventId: string) {
await db.events.update(
{ id: eventId },
{ deletedAt: new Date() }
);
}

Agent 使用关键词匹配来搜索代码。如果你的变量名是 usr,Agent 搜索 “user” 时找不到。

function calcEvtDur(evt: Evt): number {
const st = evt.stTm;
const et = evt.etTm;
return et - st;
}
// User account record. Also called: member,
// subscriber, customer, client.
// In external calendar APIs, this maps to their
// "principal" or "identity" concepts.
interface User {
id: string;
email: string;
calendarToken: string; // aka "access token", "auth credential"
}

使用 JSDoc 风格的标签进行分类:

/**
* Process incoming webhook from Google Calendar.
*
* @domain calendar-sync
* @external google-calendar-api
* @rate-limit 100/min (Google's limit, not ours)
* @failure-mode Queues failed webhooks for retry
* @related syncEvents, refreshCalendarToken
*/
async function handleGoogleWebhook(payload: WebhookPayload) {
// implementation
}

在每个主要目录放置 README.md 解释其用途:

# Services Layer
**Purpose**: Business logic and domain operations.
Services are framework-agnostic (no Express/HTTP concerns).
**Conventions**:
- One service per domain entity
- Services may call other services or repositories
- Services must NOT import from controllers/ (layering violation)
**Testing**: Unit test with mocked repositories.
See tests/services/ for examples.

llms.txt 是让文档对 LLM 可发现的轻量级标准。它类似于 AI Agent 的 robots.txt——一个简单的索引文件。

规范: https://llmstxt.org/

# MyProject
Enterprise SaaS platform for event management
## Getting Started
- Setup: docs/setup.md
- Architecture: docs/architecture.md
- API Reference: docs/api.md
## Common Patterns
- Authentication flow: src/services/auth-service.ts (line 78-125)
- Error handling: CLAUDE.md#error-patterns (line 150)
- Rate limiting: src/middleware/rate-limiter.ts (line 45)
## Domain Knowledge
- Event lifecycle: docs/domain/events.md
- Payment processing: docs/domain/payments.md
方面llms.txtContext7 MCP
用途静态文档索引运行时库查询
设置零配置(只是一个文件)需要安装 MCP 服务器
内容项目特定文档官方库文档
Token 成本低(仅索引,~500 tokens)中等
使用场景项目 README、架构React API、Next.js 模式

最佳实践:同时使用两者。


准则: 文件保持在 500 行以内。Agent 通常一次读取 200-300 行。

# 差:单体文件(1200 行)
src/services/event-service.ts
# 好:按关注点拆分
src/services/event/
├── event-service.ts (200 行:公共 API + 编排)
├── event-validator.ts (150 行:验证逻辑)
├── event-calendar-sync.ts (300 行:外部日历同步)
├── event-conflict-resolver.ts (250 行:重叠检测)
└── README.md (解释模块结构)
// Import React
import React from 'react';
// Import useState hook
import { useState } from 'react';
// Define Props interface
interface Props {
// User name
name: string;
// User age
age: number;
}

节省:从 ~150 tokens 减少到 ~80 tokens(47% 减少),不丢失关键信息。

export const DEBUG = process.env.DEBUG === 'true';
class EventService {
async syncEvent(eventId: string) {
if (DEBUG) {
console.log(`[EventService.syncEvent] Starting sync for ${eventId}`);
}
const event = await this.getEvent(eventId);
// sync logic
}
}

人类: 能从模糊需求推断意图,在实现过程中自我修正。

Agent: 严格按测试指定的内容实现。没有测试 = 没有功能。

# 差:
User: "Implement email validation and write tests for it"
# 好:先自己写测试
# tests/validation/email.test.ts 已手动编写
User: "Implement the email validation function to pass
all tests in tests/validation/email.test.ts"

原因:Agent 写的测试可能匹配其实现(循环验证),无法独立验证。

  1. 编写失败测试(你,人类)

    describe('EventService.createEvent', () => {
    it('prevents double-booking for same user + time', async () => {
    await eventService.createEvent({
    userId: 'user-123',
    startTime: '2026-01-21T10:00:00Z',
    endTime: '2026-01-21T11:00:00Z'
    });
    await expect(
    eventService.createEvent({
    userId: 'user-123',
    startTime: '2026-01-21T10:30:00Z',
    endTime: '2026-01-21T11:30:00Z'
    })
    ).rejects.toThrow('Scheduling conflict detected');
    });
    });
  2. 给 Agent 测试并附加实现约束

    User: "Implement EventService.createEvent() to pass
    the double-booking test. Requirements:
    - Check conflicts using conflictResolver.detectOverlap()
    - Throw SchedulingConflictError
    - See ADR-009 for conflict resolution algorithm"
  3. Agent 实现以通过测试

  4. 验证

    Terminal window
    npm test tests/services/event-service.test.ts
  5. 迭代(测试失败则 Agent 修复实现)

{
"jest": {
"coverageThreshold": {
"global": {
"statements": 80,
"branches": 80,
"functions": 80,
"lines": 80
}
}
}
}

Agent 在大量使用标准设计模式的代码库上训练。利用这一点。

// Singleton pattern (widely known)
class DatabaseConnection {
private static instance: DatabaseConnection;
private constructor() {}
public static getInstance(): DatabaseConnection {
if (!DatabaseConnection.instance) {
DatabaseConnection.instance = new DatabaseConnection();
}
return DatabaseConnection.instance;
}
}

流行框架和库有更多训练数据,Agent 表现更好:

框架/库GitHub 仓库数Agent 表现
React10M+优秀
Express5M+优秀
Vue3M+良好
Svelte500K一般
自定义框架<1K

建议: 除非有充分理由,否则使用主流技术。


使用 Hook 强制代码库约定:

.claude/hooks/PreToolUse.sh
#!/bin/bash
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool.name')
if [[ "$TOOL_NAME" == "Edit" ]] || [[ "$TOOL_NAME" == "Write" ]]; then
FILE_PATH=$(echo "$INPUT" | jq -r '.tool.input.file_path')
# 阻止 controller 直接调用 repository(层级违规)
if [[ "$FILE_PATH" == *"/controllers/"* ]]; then
CONTENT=$(echo "$INPUT" | jq -r '.tool.input.new_string // .tool.input.content')
if echo "$CONTENT" | grep -q "Repository\\."; then
echo "Layering violation: Controllers must call Services, not Repositories" >&2
echo "See ADR-011 for architecture rules" >&2
exit 2 # Block
fi
fi
fi
exit 0 # Allow
层级捕获内容速度自动化
Hooks执行前(密钥、反模式)即时100%
Linter语法、风格违规<10s100%
类型检查类型不匹配<30s100%
测试逻辑错误、功能破坏<2min100%
CI 检查覆盖率、TODO、架构<5min100%
人工审查意图、安全、上下文小时级手动

src/services/event-service.ts
/**
* Event management service.
*
* Related modules:
* - src/services/calendar-sync-service.ts (external calendar sync)
* - src/services/conflict-resolver.ts (overlap detection)
* - src/repositories/event-repository.ts (data access)
* - src/jobs/reminder-sender.ts (event reminders via queue)
*
* See also: ADR-007 (event deletion), ADR-009 (conflict resolution)
*/
class EventService {
// implementation
}

将文档放在代码附近,而非独立 wiki:

src/integrations/google-calendar/
├── google-calendar.ts
├── google-calendar.test.ts
├── README.md ← "How to use integration"
├── RATE_LIMITS.md ← "API rate limits + handling"
└── TROUBLESHOOTING.md ← "Common errors + solutions"

/**
* Validate email address format and uniqueness.
*
* Checks:
* 1. Valid email format (RFC 5322 compliant)
* 2. Not a disposable email domain
* 3. Not already registered in database
*
* @param email - Email address to validate
* @returns Promise resolving to true if valid
* @throws {ValidationError} If format invalid
* @throws {DuplicateEmailError} If already registered
*
* @example
* await validateEmail('user@example.com'); // Returns true
*
* @example
* await validateEmail('invalid-email');
* // Throws ValidationError: "Invalid email format"
*/
async function validateEmail(email: string | null): Promise<boolean> {
// implementation
}
// 最小用法(应用默认值)
const client = new GoogleCalendarClient(credentials);
// 仅覆盖需要的选项
const client = new GoogleCalendarClient(credentials, {
timeout: 60000 // 只覆盖 timeout
});

领域知识(满分 5)

  • CLAUDE.md 包含业务上下文、设计原则、领域术语
  • ADR 记录关键决策
  • 注释解释”为什么”
  • 交叉引用链接相关模块
  • 目录 README 解释模块用途

可发现性(满分 6)

  • 使用完整术语(userusr
  • 注释包含同义词
  • JSDoc 标签(@domain@related
  • 主要目录有 README
  • CLI 工具有 --help 和示例
  • 嵌入式文档在代码附近

Token 效率(满分 4)

  • 文件在 500 行以内
  • 移除显而易见的注释
  • 调试输出由详细标志控制
  • 大型生成文件通过 .claudeignore 排除

测试(满分 5)

  • 测试手动编写(不委托给 Agent)
  • TDD 工作流
  • UI 功能有 E2E 测试
  • CI 中测试覆盖率 >80%
  • 测试覆盖边界情况

评分标准

  • 25-33: 优秀的 Agent 友好度
  • 18-24: 良好,有改进空间
  • 10-17: 一般,存在明显差距
  • <10: 差,需要大幅重构
  1. 添加 CLAUDE.md(30 分钟)
  2. 添加目录 README(每个目录 15 分钟)
  3. 为热点文件添加交叉引用(每个文件 10 分钟)
  4. 拆分一个大文件(30 分钟)
  5. 在 CI 中启用测试覆盖率(15 分钟)