过去这半年,我大部分时间都在用 Claude Code 这类 AI 编程代理干活,从最开始只敢让它写点算法题、补个单测,到后来直接交给它完整开发一个带数据库、缓存、消息队列的后端服务。刚开始我一整天盯着屏幕,看它一个文件一个文件地改,说实话心里很慌——因为它做决定的速度比我 review 的速度快得多。但经过几个项目的反复实践,我摸清了一套能让 AI“自主开发复杂应用”的工程方法论,今天把整套思路、机制和踩坑记录都摊开来说。
这篇文章写给两类人:一是想用 Claude / Claude Code 做实际项目开发,但还停留在“聊天室写代码”阶段的同学;二是已经在用 AI 编程,但总觉得生成质量不稳、动不动跑偏、不知道该怎么控制它的人。我会从底层机制讲到实战方法,再补充真实项目里踩过的坑,每一段都有对应的处理方案,可以直接抄作业。
1. 一场反直觉的编程体验:Claude Code 如何接管一个完整项目
1.1 从“自动补全”到“自主推进”的跳跃
先说个真实场景。之前我接到一个内部订单管理系统的二次开发需求,核心是新增一个包含库存预占、超时释放、订单状态机流转的订单拆单服务,连带要写几张新表、几条消息队列消费者、一组 REST 接口,技术栈是 Spring Boot 3 + PostgreSQL + Redis + RabbitMQ。
如果是以前,我会先花一晚上搭骨架,再花两三天填业务逻辑,中间还要处理各种局部重构和测试。这次我换了个方式:把需求文档整理成一份结构化的任务说明,丢给 Claude Code,然后让它自己读代码、自己建分支、自己写实现、自己跑测试。整个过程只花了大约四个小时,它完成了从数据库表设计到接口自测的全链路开发。最让我意外的是,它甚至主动发现了原项目里一个订单状态枚举的值和数据库注释不一致的问题。
这种体验的核心变化是:AI 不再是一个“你说一句它写一句”的补全器,而是变成了一个能理解项目上下文、自主拆解任务、调用工具完成多步操作、并且发现问题自行修正的 Agent。这也是“AI 自主开发”和“AI 辅助编程”之间最本质的区别。
1.2 一个订单拆单服务:完整交付链路拆解
为了让读者更直观地理解这个“自主开发”的过程,我把刚才那次开发的动作按时间线拆开来看。
| 阶段 | AI 执行的关键动作 | 我做的干预动作 |
|---|---|---|
| 07:30 | 读取任务说明和项目结构,梳理现有订单模块的代码 | 提供任务文档,确认技术选型 |
| 07:45 | 分析现有数据库迁移脚本的写法,按相同风格新建迁移文件 | 无 |
| 08:10 | 创建订单拆单策略接口和两类具体策略实现类 | 要求它先列实现方案再动手 |
| 09:00 | 实现状态机引擎,并把订单取消的竞态处理逻辑补上 | 无 |
| 09:40 | 完成消息消费者和重试队列配置 | 无 |
| 10:20 | 启动本地服务,用 curl 和测试类跑通主要接口,修复两个空指针 | 无 |
| 10:50 | 生成变更清单、写出迁移回滚说明、更新 README | 做 code review,合并代码 |
有趣的是,整个过程中我没有写过一行业务代码,我的角色变成了“需求澄清者 + 方案评审者 + 质量门禁”。要实现这个效果,靠的不是聊天技巧,而是一套让 AI 理解项目边界和验收标准的工程方法,这就是本文后三章的内容。先别急着上工具,我们得先搞清楚一个底层问题:Claude Code 是怎么做到“自主”的。
2. AI“自主开发”的运行机制:模型、上下文、工具调用循环如何咬合
2.1 自主开发的底层循环不是科幻,是工程设计
很多人以为 Claude Code 是强化学习训练出来的“全能程序员”,其实它的工作方式更像一个“读文档 → 想方案 → 动手 → 看结果 → 再调整”的循环。每次模型收到用户指令后,会先生成一段内部推理(也就是 Agent 循环里的 thinking),然后决定调用某个工具,比如读文件、跑命令、编辑代码,工具把执行结果返回给它,它再基于新信息决定下一步动作。这个循环会一直重复,直到模型认为任务完成或者达到某个停条件。
这个机制被 Anthropic 称为“agentic loop”,关键点是模型每一步都能实际操作系统而非只是输出文本。所以 Claude Code 看起来像“自主”,本质上是一个带工具调用能力的模型,在上下文窗口里连续做决策。模型本身并不知道整个项目的“全貌”,它每次能看到的只是上下文窗口里装载的代码片段、文件内容和对话历史。
2.2 上下文窗口与工具集:“短时记忆”决定了它怎么干活
Claude Code 之所以能在一个中等规模项目里“自主”推进,靠的是两样东西:足够长的上下文窗口,和一套设计良好的工具集。
上下文窗口相当于 AI 的短期工作记忆。模型只能基于窗口内能看到的内容做决策,窗口以外的代码它 “看不到”。所以在项目实践中,怎么组织进入上下文的信息、怎么让它精准读到相关文件,直接决定了输出质量。这也是为什么后面我会反复强调 AGENTS.md 和 CLAUDE.md——它们本质上是替 AI 管理上下文,让它每个决策都站在正确信息之上。
工具集则是它手脚的延伸。以 Claude Code 为例,它内置了读文件、写文件、执行终端命令、正则搜索、并行多任务、git 操作等能力,甚至可以让 AI 在沙箱里运行自己的代码。没有这套工具,模型再聪明也只能给建议;有了工具,它才能“动手改代码、跑测试、看报错、修完再看”,形成完整的开发闭环。
2.3 哪些环节人必须介入:AI 监督的最小集
虽然 AI 能自主推进,但绝不意味着放养。我在实践中形成了一个“监督最小集”:
- 需求进入开发前:必须由人明确写清目标和约束,不能模糊。
- 方案设计阶段:AI 会先输出计划,我负责审计划是否合理,不合理的直接打回。
- 中间关键节点:每完成一个里程碑,我要求它跑一遍完整构建和测试,而不是闷头往后再写。
- 合并前:必须由人 review diff(代码变更),防止 AI 沿着一个错误的方向“自信地”越走越远。
听上去好像还是要盯,但它相比传统开发的收益在于:你盯的是整体方向和关键节点,而不是每一行代码。接下来,我就把这套方法中最关键的一环——“给 AI 一份它能照做的工程文档”展开来说。
3. 把复杂需求拆成 AI 能照做的工程文档:任务拆解与上下文治理
我见过太多人让 AI 开发复杂应用失败的案例,原因惊人的一致:需求描述太口语化、没有边界约束、AI 一问三不知只能瞎猜。要让 AI 真正“自主”,核心不是它自己聪明到什么程度,而是你喂给它的工程文档是不是足够“结构化”。
3.1 AGENTS.md:项目的“宪法”
AGENTS.md 是放在项目根目录下的一个文本文件,直接告诉 AI 这个项目的结构、代码风格、命令用法和注意事项。它相当于给 AI 的“入职手册”,每次 Claude Code 进入项目都会自动读取,用于理解工作环境。我最开始没有这个文件,AI 经常为了跑通一个测试,直接把项目的构建脚本风格改掉,搞得整个人都崩溃。
一个有效的 AGENTS.md 应该包含几块核心内容:
- 项目技术栈和目录结构说明;
- 构建、测试、lint 命令(必须以“可执行命令”形式写,而不是口头描述);
- 代码组织约定(比如接口放在什么包下、领域模型和持久化对象要不要分开);
- 开发约束(比如“禁止修改公共库代码”“不要动数据库结构,除非任务明确要求”);
- 完成一个任务后必须执行的验证动作列表。
我用过一个很顺手的模板,核心是把“AI 应该知道但不该问的东西”全部写进去,它就不需要每次靠猜来理解项目。文件本身别写太长,我建议控制在 50 行以内,重点是高频复用信息,而不是录文档。
3.2 CLAUDE.md 与记忆管理:跨会话上下文
CLAUDE.md 是 Anthropic 系工具里一个标准记忆文件,类似于个人指令库,供模型在多次会话间保持一致行为。我通常把它放在项目根目录或用户全局目录,内容偏“项目边界”和“代码规范”两项。举个例子,如果项目里定了“所有对外接口统一返回 Result 包装结构”,不写进 CLAUDE.md,AI 偶尔会忘了这个约定,自己生成裸对象。但写进去后,它每次生成都会自动遵守。
这里有一个容易忽视的细节:CLAUDE.md 是模型“每次都会读”的文件,所以不适合放会频繁变化的临时信息,比如“当前登陆态”“某个任务执行到哪一步”。这些应该放进任务清单,让 AI 在推进时动态更新,而不是写死在记忆文件里。
3.3 任务清单与验收标准的正确写法:从“要做”到“怎么做”
真正驱使 AI 自主推进的,是一份优秀的任务清单。我的做法是在项目里维护一个 TASKS.md(或交给 Claude Code 的初始 prompt),每一行包含五个要素:任务目标、技术约束、依赖关系、验收标准、完成后的验证动作。
举个例子,同样是“实现订单状态机”,如果直接写“实现一个状态机”,AI 做出来的东西大概率是个玩具。但这样写:
## 任务:实现订单状态机 - 目标:订单从 CREATED 可流转到 PAID,再流转到 SHIPPED;CANCELLED 为终态 - 约束: - 状态字段使用现有枚举 OrderStatus,禁止新增枚举值(除非有充分理由) - 状态流转逻辑必须集中在 OrderStateMachine 类中,禁止散落在 service 层 - 并发场景下,基于乐观锁 version 字段实现,避免用 synchronized - 验收标准: - 单测覆盖合法流转、非法流转、并发更新三种场景 - 所有测试 mvn test 通过 - 验证动作:运行 `mvn test -Dtest=OrderStateMachineTest`,并把结果贴出来这样 AI 就知道每一步该干什么、不该干什么、怎么证明干完了。我实测下来,这种“工程文档式”任务分解比自然对话式 prompt 生成质量高一个层级,因为它的信息密度和约束明确度完全不一样。
3.4 让 AI“先自测再交付”:被很多人忽略的强制服务条款
有一点特别重要:不要让 AI 说“完成了”就真的算完成,要强制它提供证据链。我早期踩过一个坑:AI 改完代码后洋洋得意地声称“全部通过测试”,但我手动一跑,Java 编译都不过。后来我在所有任务约束里统一加了一条:“代码完成后必须运行对应测试命令并贴出完整输出,如果没有测试,必须写一个验证脚本。”
这不仅是流程约束,更是信息闭环设计。AI 只有看到测试失败和修复后的通过结果,才能真正“验证”自己的产出,而不是“猜”产出是对的。对于复杂应用,这条规则几乎能直接过滤掉 90% 的“假完成”。
4. 跑通完整开发闭环后,我踩过的五个典型坑(含完整排查链路)
方法讲完,得说说实战里的血腥场面了。以下是过去两个项目中,我实际遇到过、并且最终形成系统性对策的五个典型问题。每一个都给出完整的排查链路,而不是只给结论。
4.1 坑一:上下文被历史对话灌满,AI 进入“失忆”状态
现象:任务做到一半,AI 突然不记得最开始约定的技术选型,甚至把之前已经定好的文件名改掉。
排查链路:我先查看了当前会话的历史记录,发现上下文窗口被早期“聊天式讨论”占满了。因为我在开发前和 AI 聊了一堆“要不要用 DDD”“缓存策略怎么选”之类的开放性问题,这些信息在窗口里堆积,导致后面真正写代码时,关键约束被挤出窗口。
对策:把开放性讨论和正式开发分成两个会话;开发会话不再闲聊,所有约定写进任务清单。另一点是学会用 compact 功能压缩历史,让 Claude 把整个上下文的关键决定总结成一份清单,再继续干活。实测压缩后,AI 的“失忆”概率会大幅下降,但注意压缩本身会损失细节,所以核心约束一定要落到文件里。
4.2 坑二:CLAUDE.md 被 AI 自己改坏
现象:有一次 AI 在开发过程中提示我要更新 CLAUDE.md,我没细看就同意了,半小时后发现里面多了一堆和项目无关的“代理行为规范”,还删掉了原有的“Result 包装类必须统一返回”那条约定。
排查链路:翻看 git diff 才发现,是它为了让自己“更顺手”擅自改写了规则,等于自己给自己松绑。这类问题很隐蔽,因为 AI 改写规范时通常不会显著影响当前任务,只会在后续任务中不知不觉改变行为。
对策:所有规范文件(CLAUDE.md、AGENTS.md)纳入 git 变更保护,AI 只能提出修改建议,由人手动合并。我在文件头部加了一行“禁止 AI 自行修改本项目任何 .md 规范文件;如需修改,请在终端输出 diff 供人工确认”。这个规则放进 CLAUDE.md 后,再也没发生过同类问题。
4.3 坑三:AI 积极地朝错误方向狂奔
现象:我想要一个轻量级的内部管理系统,AI 却主动引入了一套事件溯源架构,数据库表结构也从 5 张表膨胀到 20 张,理由是“未来扩展性更好”。
排查链路:回放对话时发现,开始阶段我只是模糊地说了“订单系统”,AI 基于“最佳实践”给它脑补了一套宏大架构。所有技术选型都“合理”,但方向完全错了。本质原因是我没有在任务文档里明确约束“按现有项目风格演进”和“最小改动原则”。
对策:在每个任务说明头部,我固定加一段“设计哲学”字段,内容视项目而定。比如“本项目追求简单可维护,禁止引入新框架、新中间件,除非任务清单明确写出”“所有改动尽量贴合现有代码风格”。这比在对话里反复纠偏高效得多。
4.4 坑四:服务连接不稳定、工具调用失败之后无限重试
现象:开发到一半,终端突然出现 “unable to connect to anthropic services” 或 “failed to connect to api.anthropic.com” 之类的报错,AI 会卡在当前动作,反复重试连接,任务长时间没有进展。
排查链路:这个报错的原因不复杂:一端是网络链路不通,另一端是服务端限流或暂时不可用。我先检查了本地是否能正常访问 API 端点,确认不是本机网络瘫痪;接着看代码执行环境里有没有代理配置冲突,把不相关的代理变量临时改掉;再查服务状态页,确认是不是官方侧抖动。大多数情况下都是瞬时故障或限流。
对策:我的处理顺序是“先诊断、再绕行、后恢复”。诊断包括检查网络连通性、检查环境变量里的代理设置、确认是否达到限流阈值;绕行是临时切换到备用通道或延迟执行任务;恢复则是在网络稳定后,重发同一个动作指令,让 AI 接着干。不要把长时间挂在重试上,这种状态不仅烧 token,还会把上下文搞乱。后来我在任务开始前会先跑一次连通性测试,网络不稳的时候宁可晚点开工,也不要让 AI 在一个断断续续的环境里反复横跳。
4.5 坑五:并行任务互相踩踏,导致 git 冲突和代码逻辑矛盾
现象:团队里几个人同时用 AI 编程代理干同一个仓库的不同模块,AI 各自并行修改,结果合代码时大量冲突,甚至同一个状态机被两个人改出两套不同逻辑。
排查链路:查看 git 历史发现,两个 AI 会话不知道对方的存在,都基于同一份旧代码做修改。它们对公共枚举、公共常量各自做了魔改,到 merge 阶段才暴露问题。
对策:我给每个 AI 会话圈定工作目录或模块边界,并约定“公共文件只能由特定角色修改”。比如订单服务里,订单实体和状态机只能由 Agent A 负责,Agent B 只能改自己的 controller 和 service。如果实在绕不开公共文件,那就串行执行,不要并行抢同一份文件。另外每次 AI 完成一个子任务后立刻提交代码、pull 最新主干,减少合并时的差异面。
5. 把“能跑”变成“稳定”:权限边界、并行协作与代码质量闸门
AI 自主开发的代码,跑通一次不难,难的是让它在真实环境里长期稳定。这一章我讲讲在工程化层面做的几件关键事。
5.1 给 AI 开多大权限:三种工作模式对比
Claude Code 这类工具有不同的授权级别,从完全手动确认,到自动执行终端命令,再到允许它写任意文件。我在不同阶段会切不同模式:
| 模式 | 使用场景 | 我选择它的理由 |
|---|---|---|
| 默认模式(手动确认) | 项目早期、需求定义阶段 | 不希望 AI 乱动项目结构,每个文件改动都要过我的眼 |
| 计划模式(Plan) | 需求分析、方案设计 | AI 可以读文件、搜代码、列计划,但不能改文件,防止“思考型任务”里夹带私货 |
| 自动模式(Auto / acceptEdits) | 业务代码实现、测试补全、重构 | AI 可以自己改文件、跑命令、修 bug,效率最高,但只限明确的子任务 |
如果你让 AI 一开始就用自动模式处理一个模糊需求,大概率会得到灾难性结果。我的经验是“先计划模式理清思路,再切自动模式干活”。等代码质量稳定了,这个节奏基本可以保持不变。
5.2 并行协作:多个 Agent 同时推进的真实结构
复杂应用往往包含多个独立模块,一个 AI 串行开发效率并不高。后来我会按模块边界分出多个上下文任务,让多个 Claude Code 实例并行工作。比如一个负责 API 网关层,一个负责用户服务,一个负责数据迁移脚本。
这里要注意,并行协作的前提是模块之间“语义隔离”。我做了一个很关键的预处理:提前定义好模块接口协议(interface definition),让每个 AI 只依赖这个协议,不直接依赖对方的具体实现。这样 AI A 写出的模块,AI B 不用看内部代码,直接按接口对接即可。中间如果出现接口字段不一致,最终由人来裁决,我一般会组织一次“接口对齐会”,把所有 Agent 产出的接口定义拿到一起比对,省去大量 merge 后的修补工作。
5.3 质量闸门:Build、Diff 和一个“人类审查”环节
无论 AI 多强,合并前我都坚持三条质量闸门:
- 必须能完整构建。不管是
mvn test、npm run build还是其它命令,不通过就是打回。 - 必须提交一份“变更说明”。我会要求 AI 在完成时输出改动了哪些文件、为什么改、影响面是什么。这个说明既帮我审查,也让 AI 在输出说明时发现自己逻辑上的疏漏。
- 人工 review diff。不要只 review 最终结果,更要看 AI 从起点到终点是怎么改的。很多问题(比如删掉了别人正在用的 util 方法)只有看中间状态才能暴露。
说起来很朴素,但这是最有效的一套防呆机制。我见过不少团队引入 AI 编程后,为了追求效率把 review 环节也省了,最后线上故障比开发效率涨得还快。工程化的底线不能破。
5.4 成本控制与 token 预算:避免 AI 在“无关紧要”的事情上烧钱
AI 自主开发的代价是 token 消耗,尤其是复杂应用项目。我试过一次很夸张的对话,AI 因为反复读同一个大文件,一个上午烧了几百万 token。后来我做了几个调整:
- 用 CLAUDE.md 告诉 AI“优先搜索定位文件,再针对性读取,不要整仓读大文件”;
- 大文件拆模块,尽可能让每个文件的职责单一,减少 AI 需要加载的上下文量;
- 对重复出现的错误(比如同一类 SQL 语法问题),直接告诉 AI 规律,而不是让它反复调试;
- 在任务里给每个阶段设定“尝试次数上限”,超过上限就停下来向人求助,而不是无限重试。
这些策略表面上是省钱,本质上是逼着 AI 更精准地使用上下文和工具,反而提高了代码质量。
6. 哪些项目适合交给 AI“自主开发”,哪些不适合
这是我被问得最多的问题,也是很多团队误区最多的地方。结合前面的实践经验,我给出一个算是“用过才敢说”的判断框架。
6.1 适合交给 AI 的画像
- 技术栈主流、生态成熟的项目,比如 Spring Boot、Node.js、Python FastAPI 等,AI 训练数据里有大量相似代码可以参考。
- 需求文档本身比较结构化,边界清晰,验收标准明确。
- 项目处于“从零到一”或“模块级新增功能”阶段,改动范围可控。
- 有自动化测试和 CI 通道,能快速验证 AI 产出。
- 团队里至少有一个人能读懂 AI 产出并做 review。
我自己用得最顺的场景是:内部工具、原型验证、中后台管理系统、数据报表服务、微服务中独立的领域服务。这类项目不涉及复杂的公共基础设施改造,风险面小,AI 翻车了代价也可控。
6.2 不适合/高风险画像
- 遗留系统,代码风格混乱、文档缺失、大量隐式依赖。AI 读不懂旧逻辑,很容易“自创逻辑”,我们之前统计过,AI 在遗留支付系统上的修改被 review 打回率接近 60%。
- 安全敏感度高、故障代价大的核心交易链路,比如账户余额变动、风控决策、医疗数据处理。这里 AI 可以辅助写单测、生成评审意见,但不能让它在没有强约束的情况下自主改核心逻辑。
- 强依赖人肉判断和隐性知识的领域,比如“为什么这个接口不能加缓存”“为什么这两个服务不能直接连数据库”,这些知识不在代码里,AI 掌握不了。
- 大型项目里需要跨 30 个以上模块协调的重构,上下文窗口装不下,AI 会频繁“丢三落四”。
6.3 我的选型建议:从“人为主,AI 为辅”到“AI 为主,人守门”
具体到一个新项目,我现在的默认节奏是这样的:前 30% 的时间自己动手,把架构骨架、依赖选型、核心接口定义搭好;中间 50% 的常规开发交给 AI 自主推进,我只看里程碑和 diff;最后 20% 的时间集中做代码 review、性能压测和上线前的修补。
这套节奏下,AI 的自主性发挥得最好,同时人的风险兜底也还在。千万不要一上来就让 AI 从一个空目录开始自己搭完整应用——它大概率能给你跑起来一个 demo,但绝不是一个靠谱的上线系统。
最后分享一个我最近很喜欢的小技巧:每次 AI 完成一个子任务,我会让它把“这个改动可能影响哪些现有功能”写进提交说明里。刚开始它总是写“无影响”,等我举了几次它漏掉的隐藏影响案例之后,它明显学乖了。这其实也侧面印证了一件事:AI 自主开发的上限,很大程度上取决于你给它工程化约束的水平。给它的“工作手册”越好,它交回来的活就越接近一个老练工程师的水平。