六个月的“纯 Agent 编码”到底意味着什么?社区里对这个话题的看法一直很撕裂:一边是“AI 生成的东西只能当玩具”,另一边是“我把日常编码全交给 Agent,人只负责提需求和 review”。如果半年前有人告诉我他会“只用 Agent 写代码”,我大概率会觉得这是标题党。但 Agent 工具的迭代速度让这件事变成了现实。这篇文章不聊模型跑分,也不聊宏大趋势,只做一件事:把“用 Agent 写代码”从安装配置到日常协作的完整链路拆开,讲清楚它解决了什么问题、改变了什么环节、有哪些坑。如果你已经装了 Claude Code 或在 VS Code 里配置过 Agent,但还没找到一套稳定的工作流,这篇文章值得读完。
我先把结论放在前面:纯 Agent 编码真正改变的不是“谁写代码”,而是“人的工作从打字变成了定义问题和验收结果”。代码质量的下限不再取决于你敲键盘的速度,而是取决于你把需求说得多清楚、把验收标准定得多硬、把权限边界划得多严。
1. 半年只用 Agent 写代码,到底在写什么?
“只用 Agent 写代码”这句话,字面意思很容易被误解成“人完全不碰代码,AI 全自动交付”。真实情况不是这样。以功能开发为例,一个典型的 Agent 驱动工作日循环是:
- 人把需求和约束写成任务说明,交代仓库结构、入口文件、允许改动的范围。
- Agent 读取相关文件,给出实现计划,等人确认。
- Agent 开始改代码,跨文件修改、补充或修改测试。
- Agent 自己运行测试和构建命令,根据失败信息反复修正。
- 人检查 diff、跑回归、做安全审查,最后合入提交。
在这个流程里,人还是要写代码的——只不过写的是“需求说明”“review 意见”和“验收反馈”,而不是实现逻辑。偶尔你也会手改一两行,但那属于特例,不是常态。
这半年里比较大的变化不是工作效率的数字,而是思维方式的切换。过去写代码时,人的注意力在“怎么实现”上:函数怎么命名、分支怎么组织、边界条件怎么处理。切换到 Agent 模式后,注意力必须前置到“定义问题”:这个任务到底要解决什么?验收标准是什么?哪些文件绝对不能动?如果这些问题不清晰,Agent 就会用最“合理”的猜测把代码写完,然后你需要花更多时间在 review 里把它揪出来。从这个角度看,Agent 并没有让人变懒,它只是把工作量从编码期挪到了需求期和 review 期。
还有一个很容易被忽略的事实:Agent 模式的成立,依赖两个技术前提。一是模型的上下文窗口足够大,可以一次读入多个文件并记住跨文件的依赖关系;二是 Agent 具备执行命令和读文件的能力,可以在真实环境里自我验证,而不是只给出“看起来对”的代码。这两点缺一不可。如果你只拿到一个“对话框里生成代码片段”的工具,那还不是 Agent,最多算升级版补全。
2. 编程 Agent 的核心概念与能力边界
2.1 Agent 与自动补全的根本区别
很多人把 AI 编程工具都叫“AI 编程助手”,但自动补全和 Agent 是两种物种。
| 对比维度 | 自动补全 / 行内建议 | 编程 Agent |
|---|---|---|
| 输入方式 | 光标位置触发,逐行补全 | 接收一个完整任务描述 |
| 上下文范围 | 当前文件、当前函数 | 整个仓库、多个文件、执行结果 |
| 典型动作 | 补全一行或一个函数 | 读文件、改文件、跑命令、调测试 |
| 自我修正 | 基本没有 | 根据报错和测试结果循环修正 |
| 交付物 | 代码片段 | 一个可提交的变更集合 |
自动补全解决的是“下一个 token 写什么”的问题,Agent 解决的是“这个任务怎么完成”的问题。前者是键盘的延伸,后者是流程的参与者。理解这个区别很重要,因为很多人在第一次使用 Agent 时,还带着“逐行检查补全建议”的习惯,结果发现 Agent 一口气改了十几个文件,然后陷入恐慌。这不是 Agent 坏了,而是它的工作方式本来就是这样。
2.2 Agent 的工作闭环
一个规范的 Agent 工作闭环包含五个阶段:
- 规划:根据任务描述,列出需要读取的文件和修改步骤。
- 读取:读取项目结构、相关源码、配置文件、测试代码。
- 编辑:执行代码修改,通常是多文件操作。
- 执行:运行测试、构建、lint 等命令。
- 观察与修正:读取命令输出,定位失败原因,回到编辑阶段。
这五个阶段形成一个循环,直到测试通过或 Agent 决定向你提问。好的 Agent 工具会把每个阶段的操作和结果展示在界面上,你不需要盲猜它在干什么。这也意味着,Agent 的“可见性”直接决定了它的可用性:一个黑盒 Agent 你会不敢用,一个每一步都留痕的 Agent 你才敢让它连跑十轮。
2.3 Agent 的能力边界
半年下来我对 Agent 边界最深刻的体会是:它擅长“按明确要求执行”,不擅长“替你做模糊决策”。
- 不能把模糊需求变成业务逻辑:如果任务描述写“优化一下登录”,Agent 大概率会猜一个方向开始改。它猜得越快,你 review 的成本越高。
- 不能替你承担安全决策:涉及权限校验、加密、支付之类的逻辑,Agent 可以写,但最终审查责任必须由人承担,不能因为它“看起来对”就直接合入。
- 长任务会漂移:一个会话里塞太多任务,Agent 会在后面忘记前面的约束。关键约束必须落在文档里,而不是对话历史里。
- 会自信地幻觉 API:它可能写出并不存在的方法名,或者用错依赖的版本。这是当前所有代码生成模型的通病,只能靠测试和 review 兜底。
一句话总结:Agent 像一位学习能力很强但经验不足的同事。你能给它多清晰的指令,它就能给你多稳定的产出。
3. Claude Code 的安装与 VS Code 集成
3.1 环境准备
以目前社区讨论最多的 Claude Code 为例,安装前的环境要求并不高:
- 操作系统:macOS 或 Linux 均可;Windows 用户建议使用 WSL2。
- Node.js:需要 18 或更高版本,具体以官方安装要求为准。
- 包管理器:npm,用来安装 CLI。
- Git:仓库操作和 diff review 需要。
- 账号:Anthropic 账号,或可用的 API Key;也可以在首次启动时用官方登录流程完成认证。
如果本机已经有 Node.js,可以在终端里先确认版本:
node -v npm -v3.2 安装 Claude Code CLI
使用 npm 全局安装是常见的安装方式:
npm install -g @anthropic-ai/claude-code安装完成后,在任意项目目录里输入claude即可启动。首次启动时会走一遍登录或 API Key 配置流程。如果你使用 API Key,也可以通过环境变量传入:
export ANTHROPIC_API_KEY="你的API Key"需要提醒的是,模型名称和账号套餐对应的可用模型可能在不同时期有差异,不要照抄网上的命令参数,以你当前账号在官方界面里能看到的信息为准。最简单的验证方式是启动后输入:
/status这个命令可以查看当前会话的模型、上下文字数消耗和会话模式。
3.3 VS Code 集成配置
很多人在搜索“vscode 配置 claude code”,说明大家最习惯的场景还是在编辑器里用 Agent。在 VS Code 里接入 Agent 有两条路线:
第一条是直接在 VS Code 的集成终端里运行claude。这样做的好处是 Agent 天然继承了当前工作目录、Git 状态和终端环境,非常适合在真实仓库里操作。
第二条是安装官方 VS Code 扩展。安装后在活动栏会出现对应的图标,可以新建会话、查看权限请求、检查已生成的 diff。它和终端里的 CLI 共享同一套核心能力,只是界面更贴合编辑器习惯。
无论哪条路线,真正影响体验的是仓库级的权限配置。建议在项目根目录创建.claude/settings.json,把高频命令放进允许列表,把敏感文件放进拒绝列表:
{ "permissions": { "allow": [ "Bash(npm run test)", "Bash(npm run lint)", "Bash(git diff)", "Read(README.md)", "Read(src/**)" ], "deny": [ "Edit(**/.env)", "Bash(rm -rf **)", "Edit(secret/**)" ] } }不同版本的配置字段可能会有调整,以你安装版本的官方文档为准。但“允许安全命令、拒绝敏感路径”的原则是通用的。配置完之后,再在 VS Code 里新建一个会话,Agent 才会在既定的权限范围内干活,而不是每步都弹权限窗口。
3.4 会话启动与退出
在项目根目录启动会话时,建议保证仓库是干净的,至少你要知道当前有没有未提交的改动:
cd your-project git status claude会话中常用的斜杠命令包括:/clear(清空上下文)、/model(切换模型)、/status(查看会话状态)。退出会话直接输入/exit即可。
4. 核心工作流:让 Agent 稳定产出的四个步骤
工具装上只是第一步。真正让 Agent 从“偶尔能帮上忙”变成“可依赖的编码协作者”,靠的是一套稳定的工作流。
4.1 让仓库成为 Agent 的“可读上下文”
Agent 第一次进入项目时,对仓库是陌生的。它需要通过 README、目录结构、测试文件来建立认知。如果你的仓库 README 是空的,入口不清晰,Agent 就会花大量时间在错误的位置找代码。
更高效的做法是在仓库根部维护一份项目说明文档。Claude Code 这类工具通常会在每次会话时自动读取约定的说明文件。在文档里写清楚:
- 项目的技术栈和运行方式。
- 入口文件和核心目录的作用。
- 常用的 npm 脚本,比如测试、构建、lint 命令。
- 代码规范和命名约定。
- 禁止修改的目录或配置文件。
这份文档不仅是给 Agent 看的,也是给新同事看的,维护成本很低,收益却很大。
4.2 用“任务说明书”代替一句话指令
一句话指令是最低效的 Agent 用法。“帮我优化订单模块”这种描述,Agent 只能猜。实践中我习惯用一个固定的任务模板:
背景:订单模块目前使用同步接口,高峰期有超时风险。 技术栈:Node.js + Express + PostgreSQL。 相关入口:src/routes/order.js,src/services/orderService.js。 任务:将订单状态查询改为支持简单的 TTL 缓存,缓存时间 30 秒。 验收标准: - 单元测试覆盖命中缓存和缓存过期两个场景。 - 不修改订单创建和支付相关逻辑。 - 不允许引入新的核心依赖。 禁止改动:src/services/paymentService.js。这个模板的核心是“约束前置”。验收标准解决了“做到什么程度算完成”,禁止改动解决了“Agent 擅自扩大修改范围”的问题。在实际项目中,任务描述越具体,Agent 的返工次数越少。
4.3 先要计划,再允许执行
不要让 Agent 直接开始改文件。在会话里先发出指令:
请先读取相关文件,给出实现计划。计划必须包含: 1. 要读取哪些文件。 2. 计划创建或修改哪些文件。 3. 测试用例的设计思路。 4. 潜在风险点。 确认计划后再动手。这一步可以过滤掉大量“方向错误”的修改。如果 Agent 的计划里出现了你不认可的设计,直接指出来,让它重新规划。计划阶段的时间成本,远远低于修改完文件再 review 的时间成本。
4.4 测试先行,用失败结果驱动修正
计划确认后,让 Agent 先写测试,再写实现。这听起来有点反直觉,但在 Agent 模式里效果很好:
请先为上述需求补充测试用例,并运行测试看到失败。 然后根据失败结果实现功能,直到测试全部通过。测试先行有双重价值。第一,测试文件本身是对需求的二次确认;第二,Agent 在“看到测试失败再修复”的循环里,会减少凭空发挥的概率。如果 Agent 直接写出了大量实现,但测试文件几乎没覆盖关键分支,这类代码反而更危险,因为它看起来能跑,实际上没有验证过边界条件。
5. 完整示例:让 Agent 完成一个真实小任务
为了说明实际操作,这里用一个最小 Express 项目演示“任务说明书 + 测试先行 + Agent 迭代”的完整链路。
5.1 项目现状
项目目录结构如下:
my-app/ ├── package.json ├── src/ │ └── app.js └── test/ └── app.test.js现有src/app.js是一个简单的 Express 应用:
// src/app.js const express = require('express'); const app = express(); app.get('/hello', (req, res) => { res.json({ ok: true, pid: process.pid }); }); app.listen(3000);5.2 向 Agent 提出任务
在项目目录启动claude,输入:
背景:当前 Express 应用没有任何请求日志,线上排查问题很困难。 任务:在 src/middleware/requestLog.js 中新增一个请求日志中间件。 要求: - 记录 method、path、status、耗时(毫秒)。 - 不记录请求体,避免泄露敏感数据。 - 日志输出为 JSON 单行,使用 console.log。 - 在 src/app.js 中全局启用。 验收标准: - test/requestLog.test.js 中补充测试,覆盖正常请求和 404 两个场景。 - 使用 node --test 运行测试全部通过。 禁止改动:test/app.test.js。5.3 Agent 产出的实现
一次典型的 Agent 产出大致包含三个文件。中间件实现:
// src/middleware/requestLog.js function requestLog() { return function (req, res, next) { const start = process.hrtime.bigint(); res.on('finish', function () { const durationNs = process.hrtime.bigint() - start; const durationMs = Number(durationNs) / 1e6; const line = { time: new Date().toISOString(), method: req.method, path: req.originalUrl, status: res.statusCode, durationMs: Number(durationMs.toFixed(2)) }; console.log(JSON.stringify(line)); }); next(); }; } module.exports = requestLog;改造后的应用入口:
// src/app.js const express = require('express'); const requestLog = require('./middleware/requestLog'); const app = express(); app.use(requestLog()); app.get('/hello', (req, res) => { res.json({ ok: true, pid: process.pid }); }); module.exports = app; if (require.main === module) { const port = process.env.PORT || 3000; app.listen(port, () => { console.log(`listening on ${port}`); }); }对应的测试文件:
// test/requestLog.test.js const test = require('node:test'); const assert = require('node:assert/strict'); const http = require('http'); const requestLog = require('../src/middleware/requestLog'); const app = require('../src/app'); function withServer(expressApp) { return new Promise((resolve) => { const server = expressApp.listen(0, () => { resolve({ server, url: `http://127.0.0.1:${server.address().port}` }); }); }); } test('requestLog 输出结构化日志', async () => { const appWithLog = (req, res, next) => { next(); }; // 使用插桩方式捕获 console.log 输出 const logs = []; const oldLog = console.log; console.log = (line) => logs.push(line); const { server, url } = await withServer(app); const res = await fetch(`${url}/hello`); await new Promise((resolve) => server.close(resolve)); console.log = oldLog; assert.equal(res.status, 200); assert.equal(logs.length, 1); const parsed = JSON.parse(logs[0]); assert.equal(parsed.method, 'GET'); assert.equal(parsed.path, '/hello'); assert.equal(parsed.status, 200); assert.ok(parsed.durationMs >= 0); });这个测试示例里其实还有一个问题:appWithLog变量没有用上,这是 Agent 在生成代码时留下的小瑕疵。它不影响测试结果,但在 review 时应该被指出来。Agent 模式的一个常态是:它产出的代码大部分可用,但总有少量“不优雅的残留”,review 的价值就在这里。
5.4 运行与验证
在项目根目录执行:
npm install express node --test预期输出中,requestLog.test.js的测试应该通过。然后启动应用做一次手动验证:
PORT=3000 node src/app.js curl -s "http://127.0.0.1:3000/hello"应用终端会打印一条日志:
{"time":"2025-01-01T12:00:00.000Z","method":"GET","path":"/hello","status":200,"durationMs":0.85}到这里,这个最小任务就跑通了。
6. 运行结果与效果验证:如何判断 Agent 干得好不好
很多用户做完一个任务后只会看“测试过没过”,这在 Agent 模式下远远不够。完整的验证序列应该是:
- 测试是否真的跑了。Agent 可能只生成了测试文件,但没有真正运行。你需要看到
node --test的真实输出,而不是它告诉你“测试应该通过”。 - diff 范围是否可控。执行
git diff --stat,确认改动文件数量与任务预期一致。如果 Agent 顺手改了三个无关文件,立刻让它还原。 - 关键分支是否有测试覆盖。不要只看覆盖率数字,而是问自己:请求成功、请求失败、参数异常这三个分支,测试里有没有?
- 命令是否在正确目录执行。Agent 有时会在错误的路径下运行命令,导致测试通过是假象。
- 依赖是否被不必要地引入。检查
package.json的 diff,新增依赖必须说明理由。
如果任务中有任何一项验证不通过,正确的做法不是自己上手修,而是把失败信息完整贴回会话,要求 Agent 解释根因后再改。最忌讳的是“Agent 改一版,你手动修三处”,这样你会永远离不开手动兜底。
7. Agent 开发常见问题与排查方法
实际使用半年,下面这些问题是出现频率最高的,按现象、原因、排查、解决的顺序列出来:
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| Agent 修改范围超出任务预期 | 任务描述缺少“禁止改动”约束 | 执行git diff --stat查看改动文件列表 | 在任务模板中增加禁止改动目录;必要时回滚后重新执行 |
| 代码越改越乱,陷入修复循环 | 根因定位错误,缺少失败信息 | 回看最近几次命令的报错输出 | 把完整报错贴回会话,要求“先说明根因再修改”;无效则新开会话 |
| 前面说好的约束后面被遗忘 | 上下文过长,关键约束被稀释 | 查看会话上下文长度 | 将关键约束写入仓库说明文档;新开会话时重新引用 |
| 写出了不存在的 API 或方法 | 模型幻觉;对依赖版本不了解 | 看运行报错;检查依赖版本 | 要求 Agent 先查官方文档或读取本地依赖类型声明,禁止凭记忆猜 API |
| 权限弹窗频繁或命令被拒绝 | 权限配置过严 | 查看会话中的权限请求记录 | 在 settings.json 里按需 allow 安全命令;不要全局放行 |
| 测试通过但集成后失败 | 环境差异;测试覆盖不足 | 对比本地环境与目标环境 | 补充集成测试;在更接近生产的环境里重跑 |
| 登录或 API Key 认证失败 | 凭据过期或账号额度不足 | 查看claude启动时的输出 | 重新登录,或检查账号订阅与 API Key 状态;确认网络能正常访问服务所在域 |
排查时建议遵循一个固定顺序:先看 Agent 最后几条操作输出,再看当前 git 状态,确认它到底改了什么,然后手动重跑一次失败的命令拿到真实报错。大多数问题在“看到真实报错”的瞬间就能定位,难的是 Agent 有时候会自己把报错“处理”掉,让问题消失但根因还在。所以只要发现 Agent 开始用“应该是”来解释代码行为,就要提高警惕,让它给出可验证的证据。
8. 最佳实践与工程建议
8.1 把需求说明书当成一等公民
在纯 Agent 模式里,需求说明书就是源代码。任务描述的质量直接决定产出的质量。团队里可以沉淀一套任务描述模板,至少包含背景、相关文件、任务、验收标准、禁止改动五段。模板一旦固定,Agent 的产出质量会明显稳定。
8.2 一个任务一个分支
不要让 Agent 在一个会话里连续完成多个任务。更稳妥的做法是:每个任务新建一个分支,Agent 在分支上独立工作,人 review 通过后再合并。这样既方便回滚,也方便保留 Agent 的完整操作留痕。分支名可以直接用任务编号,例如feat/order-cache。
8.3 用测试当验收证据
“Agent 说做完了”不等于“做完了”。所有任务都以测试结果为准。如果项目本身测试覆盖很差,可以先让 Agent 补一个最小测试骨架,再开始业务开发。把“先有测试,再写实现”变成默认流程,而不是可选项。
8.4 权限最小化与敏感信息隔离
Agent 能够执行命令,这是一把双刃剑。生产环境、密钥文件、无备份数据这些场景,尽量别让 Agent 触碰。配置层面建议把.env、密钥目录、数据库凭据文件全部加入 deny 列表。同时,不要在对话里粘贴真实的密钥、Token 或敏感客户数据,因为你无法完全控制模型日志的存储策略。
8.5 明确哪些场景不适合 Agent
不是所有代码都适合交给 Agent。涉及支付、权限、加密等安全敏感逻辑,必须人工逐行 review,且最好由有经验的人把关。需求本身还没想清楚的探索性任务,也容易让 Agent 走进错误方向。还有一类场景是“只改一行”的紧急修复,直接手改通常比和 Agent 讨论更快。工具是加速器,不是所有流程都要硬套。
8.6 团队落地建议
团队引入 Agent 时,最容易踩的坑是“每个人各玩各的”。建议从三件事开始统一:第一,统一使用同一款 Agent 工具和相对固定的模型版本;第二,统一任务说明书模板;第三,统一 review 规则,比如测试必须是真实运行的、diff 必须在合并前人工确认、依赖变更必须说明理由。在此基础上,再逐步把 Agent 的常见失败案例沉淀成本团队的排查手册。
9. 总结与后续学习方向
六个月“只用 Agent 写代码”的模式,最终改变的不是代码量,而是整个开发的注意力结构。人在这个模式里真正花时间的地方,变成了需求定义、计划评审、diff review 和验收验证。Agent 能不能成为可靠的协作者,很大程度上取决于你愿不愿意把这些前置工作做扎实。
如果你还没有真正跑通过一个 Agent 任务,下一步可以这样开始:挑一个你非常熟悉的小需求,用本文第五节的任务模板写清楚,让 Agent 实现并配套测试,然后重点观察它读了你哪些文件、执行了哪些命令、在哪个环节开始偏离你的预期。第一次跑通后,你会发现真正的学习关卡不在安装,而在“如何把一个模糊想法翻译成 Agent 能执行的精确指令”。
建议收藏这篇文章,之后在 VS Code 里被 Agent 改崩代码时,再回来看第七节和第八节。祝你的第一个纯 Agent 任务顺利通过 review。