剪掉 AI Agent 写的平庸样板代码:工作环境配置指南
TuBrief 편집팀
2026년 7월 24일
0
Computing/Software원본 영상을 바탕으로 AI의 도움을 받아 작성했습니다. 원본 영상이 기준입니다.
커뮤니티의 다른 글
댓글 (0)
Log in to leave a comment
아직 작성된 글이 없습니다
원본 영상을 바탕으로 AI의 도움을 받아 작성했습니다. 원본 영상이 기준입니다.
Log in to leave a comment
아직 작성된 글이 없습니다
把 AI Agent 放到实际开发环境中,很快就会露馅。在不懂业务上下文的情况下,它往往机械地滥用工厂模式,或者源源不断地吐出毫无用处的工具函数。GitClear 在 2024 年发布了一份针对 6.23 亿行 Commit 的分析报告,报告显示在 AI 工具普及后,代码重复率上升了 81%,而清理已有代码的重构比例则从 25% 骤降至 10% 以下。由于上下文窗口的近因偏见(Recency Bias),Agent 为了规避风险,会不断逃向训练数据中最常见的标准模式。我们必须通过上下文文件显式声明团队共享的架构规则和同步逻辑,从而压制 Agent 的误操作。
要想管控各个开发工具中参差不齐的指令,首先需要在项目根目录下建立一个充当单一事实来源(Single Source of Truth)的 AGENTS.md。Cursor、Claude Code 等工具都会读取该规则。单个 .cursorrules 文件早已被废弃。我们需要将其拆分并放入 .cursor/rules/ 目录下的 MDC 文件中,而在 Claude Code 环境下,则通过在 CLAUDE.md 中引入 @AGENTS.md 来防止规则失效或失效扩散。
apps/api/src/common/dto.services/shared/uow.`
当上下文的总长度超过 800 行(约 2,000 个 Token)时,Agent 就会开始忽略写在顶部的约束条件。因此,AGENTS.md 中应该只保留绝不可妥协的禁止事项,而详细的架构决策记录(ADR)则应推送到 docs/context/ 目录下。
AGENTS.md,写明禁止单一实现接口、禁止防御性 try-catch 等条件。.cursor/rules/backend-constraints.mdc 位置配置目标文件路径(globs)和 YAML Frontmatter 约束。CLAUDE.md 中添加 @AGENTS.md 语法以适配环境。Agent 生成的看似合理的代码背后隐藏着陷阱。根据 Veracode 在 2024 年的研究结果,AI 建议的代码中有 45% 被发现存在 OWASP Top 10 级别的安全漏洞。相比人类编写的代码,AI 用 try-catch 敷衍地包裹可能失败的逻辑,随后抛出空对象或 null 来隐瞒错误的情况高出了 47%。此外,在 Read-Modify-Write 操作中漏掉乐观锁,或者在循环中频繁调用数据库的 N+1 问题也时有发生。
| 验证领域 | 详细验证项目 | 风险模式及 Agent 陷阱 | Merge 阻断标准 |
|---|---|---|---|
| 安全漏洞 | 是否使用 Parameterized Query、租户隔离、检查未经授权的包 | 基于字符串拼接的 SQL 注入、因幻觉生成的未经验证的包调用 | 缺少输入值验证、添加来源不明的外部分析依赖时阻断 |
| 性能瓶颈 | ORM 延迟加载、Hot path 内的嵌套循环、数据库索引 | 循环内针对单个实体的遍历查询、内存中全表过滤 | 循环内存在数据库及外部 API 调用时阻断、未应用分页时阻断 |
| 类型安全性 | Strict Type 验证、Boundary 异常处理、并发控制 | 滥用 as any、通过 Empty Catch 块隐瞒错误 |
存在 any 及无节制的 as 类型断言时阻断、日志缺失的 Catch 块阻断 |
Agent 编写的测试代码往往很容易沦为直接复制粘贴实现代码的同义反复测试(Tautological Test)。这种测试完全无法捕获实际的业务缺陷。必须严格执行“如果已存在现有工具函数,则删除 Agent 新创建的工具函数并复用现有代码”这一规则。
any 等检查项。as any 或循环内的 await 即打回 Commit。如果试图通过单个 Prompt 注入复杂的结算逻辑或基于状态机的订单处理,Agent 可能会陷入工具调用循环,或者只吐出徒有其表的花架子代码。这是因为尝试一次性处理 Schema 设计、API 接口、异常处理和业务规则会导致 Token 分配顺序混乱。
`
[第 1 阶段: 数据建模] -> 生成 DB 实体、Zod Schema
│
▼ (将输出结果作为上下文传递)
[第 2 阶段: 接口定义] -> 定义 API DTO、Custom Error、服务签名
│
▼ (将第 1+2 阶段的输出结果作为上下文传递)
[第 3 阶段: 业务逻辑实现] -> 完成事务、状态转移、并发控制
`
手动进行这一交互过程相当繁琐。编写 CLI 自动化脚本(scripts/agent-decomposed-build.ts),将前一阶段的产出物绑定作为下一阶段的输入上下文,是更明智的选择。
`typescript
import { execSync } from 'child_process';
import * as fs from 'fs';
interface TaskPipeline {
featureName: string;
stage1Prompt: string;
stage2Prompt: string;
stage3Prompt: string;
}
async function runDecomposedAgentPipeline(pipeline: TaskPipeline) {
console.log([Stage 1] Executing Data Modeling for ${pipeline.featureName}...);
const stage1Output = execSync(claude --print "${pipeline.stage1Prompt}").toString();
fs.writeFileSync(./tmp/${pipeline.featureName}_stage1.ts, stage1Output);
console.log([Stage 2] Executing Interface Definition...);
const stage2InputPrompt = ${pipeline.stage2Prompt}\n\nContext Models:\n${stage1Output};
const stage2Output = execSync(claude --print "${stage2InputPrompt}").toString();
fs.writeFileSync(./tmp/${pipeline.featureName}_stage2.ts, stage2Output);
console.log([Stage 3] Executing Business Logic Implementation...);
const stage3InputPrompt = ${pipeline.stage3Prompt}\n\nContext Models:\n${stage1Output}\n\nContext Contracts:\n${stage2Output};
const stage3Output = execSync(claude --print "${stage3InputPrompt}").toString();
fs.writeFileSync(./src/services/${pipeline.featureName}.service.ts, stage3Output);
console.log([Pipeline Complete] Business logic generated cleanly without cognitive stagnation.);
}
`
scripts/agent-decomposed-build.ts,使先前的输出能够作为下一个 Prompt 的上下文顺畅衔接。使用 AI 编码工具越多,缺乏“为什么这样写”这一理由的“只写代码”就会堆积得越多。未记录架构选择权衡(Trade-off)的代码,日后会变成人类难以维护的沉重负担。必须在 AGENTS.md 中强制要求 Agent 在生成代码时,将 TSDoc 标准注释写进源代码中。
`typescript
/**
`
为了防止不同开发者之间的 Agent 配置出现偏差,应当将 AGENTS.md 作为单一事实来源,并在 Commit 时运行脚本(tools/sync-agent-rules.ts)将其同步至 CLAUDE.md 和 .cursor/rules/global.mdc。
`typescript
import * as fs from 'fs';
import * as path from 'path';
const AGENTS_MD_PATH = path.join(__dirname, '../AGENTS.md');
const CLAUDE_MD_PATH = path.join(__dirname, '../CLAUDE.md');
const CURSOR_RULE_PATH = path.join(__dirname, '../.cursor/rules/global.mdc');
function syncRules() {
if (!fs.existsSync(AGENTS_MD_PATH)) {
console.error('Error: AGENTS.md does not exist.');
process.exit(1);
}
const baseRules = fs.readFileSync(AGENTS_MD_PATH, 'utf-8');
const claudeContent = # AUTOMATICALLY GENERATED FROM AGENTS.md - DO NOT EDIT DIRECTLY\n\n${baseRules};
fs.writeFileSync(CLAUDE_MD_PATH, claudeContent);
const mdcHeader = ---\ndescription: Global Agent Rule Sync\nglobs: **/*\nalwaysApply: true\n---\n\n;
fs.writeFileSync(CURSOR_RULE_PATH, ${mdcHeader}${baseRules});
console.log('Successfully synchronized AGENTS.md to CLAUDE.md and Cursor MDC rules.');
}
syncRules();
`