AI为什么能自己写代码?claude-code-from-scratch的Agent Loop核心循环原理深度解析
【免费下载链接】claude-code-from-scratchBuild your own Claude Code from scratch. 🔍 Claude Code 开源了 50 万行代码,读不动?用 ~5000 行 TypeScript / Python 从零复现核心架构,11 章分步教程带你理解 coding agent 精髓项目地址: https://gitcode.com/gh_mirrors/cl/claude-code-from-scratch
claude-code-from-scratch 是一个用约 5000 行 TypeScript / Python 从零复现 coding agent 核心架构的开源教程项目。本文深入解析其中最关键的Agent Loop(智能体核心循环)——AI 为什么能自己读代码、改文件、跑测试?答案不复杂:一个while循环加一条工具回路,就足以让"只会说话"的模型变成"能干活"的 AI 编程助手。
一、从"给建议"到"自己动手":AI 写代码的突破点
🤖 AI 辅助编程走过三个阶段:代码补全(Copilot 式)→ 聊天助手(Chat 式)→自主 Agent(Claude Code 式)。
前两个阶段有个共同的天花板:模型只能给建议,不能自己动手。让它修 bug,它能给出一段代码,但它跑不了测试、看不到报错、没法根据结果再改一版。
Claude Code 这类自主 Agent 迈过了这道坎:一句"给项目加用户注册",它会自己去搜路由、读数据库模型、写 handler、跑npm test,看到失败就改一版再跑,来回十几轮直到测试通过。它不是在补全代码,而是在执行一个任务。
做到这一点靠的不是魔法,而是一个循环:
while (true) { 调模型,拿到它的回复 回复里有工具调用?→ 执行工具,把结果喂回去,继续 回复只是文本? → 任务结束,退出 }注意这个"反转":传统程序里,下一步做什么是程序员用if/else提前写死的;而 Agent Loop 里,下一步做什么由模型决定,代码只负责把循环转起来、把工具递过去。这一反转,就是 coding agent 和普通聊天机器人的全部区别。
二、Agent Loop 核心循环解剖:一轮只做 4 件事
每一轮循环,引擎只做 4 件事,顺序固定:
| 步骤 | 做什么 | 关键点 |
|---|---|---|
| 1️⃣ 调模型 | 把消息历史 + 工具清单发给 LLM | 工具清单只需一行参数,却给了模型"手" |
| 2️⃣ 看回复 | 扫描回复里有没有tool_use块 | 有工具调用 = 模型想动手;没有 = 任务完成 |
| 3️⃣ 执行工具 | 逐个执行模型请求的工具(读文件、跑命令等) | 代码真正动手的环节 |
| 4️⃣ 喂回结果 | 把工具结果作为一条消息推回数组 | 模型"看到"结果后继续思考 |
第 1 章的最小实现里,让模型从"只聊天"变成"能动手",改动其实只有两处:请求里带上tools(模型才知道有哪些工具可调),外面套一个while(结果喂回去再问一轮)。
教学版循环完整写在 steps/canonical/ts/agent.ts,Python 镜像实现在 python/mini_claude/agent.py。
三、消息数组怎么长大:模型"记得"的真正秘密
很多人以为 Agent 有复杂的记忆机制,其实核心阶段它就是一个不断变长的数组。以"帮我修复 bug"为例:
第 1 轮: [用户请求] + [assistant: 要调 read_file] + [user: 文件内容] 第 2 轮: 上面 3 条 + [assistant: 要调 edit_file] + [user: 编辑成功] 第 3 轮: 上面 5 条 + [assistant: "已修复!" ← 无工具调用,循环结束]带工具的那几轮,数组通常多两条:一条 assistant(模型要调什么工具)、一条 user(工具结果)。模型每次都能看到从头到尾的完整历史——所谓"记忆",此刻不过是一个不断变长的数组。两个协议细节也值得记住:工具结果要用role: "user"装(API 协议要求),且每条结果靠tool_use_id认回它对应的那次调用。
四、Agent 和聊天机器人的分界线:谁在决定?
💡 给模型"读文件"任务前,它只会说"我没有办法直接读取你的文件,如果你把内容贴过来……"——不是它不肯,是根本没给它手:请求里没告诉它有哪些工具,也没有接住它、真去执行、把结果递回去的那一环。
装上工具回路后,整个循环里没有任何"如果用户想读文件就……"的分支代码。决定循环转不转的,从头到尾是模型,不是我们的代码:要不要动手、动手之后够不够、要不要再来一轮,全是模型自己判断。这也是本文开头那个"反转"的工程落地。
五、真实 Claude Code 比最小循环多做了什么?
真实 Claude Code 把同一个循环做成了生产级引擎,拆开看正好照出玩具循环与生产引擎的差距:
- 两层循环:外层管对话生命周期(用户输入、预算、Token 统计、会话恢复),内层管一次查询的执行(消息压缩、API 调用、工具执行、错误恢复),关注点分离;
- 七种"继续"情形:最小版只有"有工具调用就继续"一种,真实实现还有上下文折叠重试、强制摘要压缩重试、输出 Token 上限升级、续写重试、Stop Hook 拦截续跑、Token 预算续生成等 6 种恢复策略;
- 流式提前执行:流式响应一般有 5~30 秒窗口,真实实现中某个工具的参数 JSON 一旦拼完整就立刻开跑,不等整个响应收完,读文件、搜代码等只读工具与模型生成并行推进;
- 可恢复错误静默消化:输出被截断、上下文过长这类错误先"扣下"不抛给界面,内部恢复成功后用户完全无感。
完整对照分析见 docs/01-agent-loop.md,完整功能版循环(含流式执行、预算检查、权限拦截)在 src/agent.ts。
六、动手跑起来:一条命令看 Agent Loop 转起来
每个章节都配了能单独跑的最小实现,不用 API key(走本地 mock 模型)就能看到循环真的转:
git clone https://gitcode.com/gh_mirrors/cl/claude-code-from-scratch cd claude-code-from-scratch npm install node steps/run.mjs 1 # 跑第 1 章:Agent Loop 最小循环 node steps/run.mjs 1 --py # 换成 Python 版运行效果大致是:
you: Read the file greeting.txt and tell me what it says. → read_file({"file_path":"greeting.txt"}) greeting.txt says: hello from step one.模型收到"读 greeting.txt",先回"我要调 read_file";循环没停,而是真去读了文件、把内容喂回去、再调一次模型,这次才给出答案——两轮,正好走完上文的核心循环。想用自己的 prompt 连真实模型,加--live即可。跑测入口见 steps/run.mjs。
七、延伸学习路径
读完本文,你可以顺着教程线继续往下搭:
- 入门总览(项目做什么、5 分钟跑起来):docs/00-introduction.md
- 本章完整教程(含与真实 Claude Code 逐项对照):docs/01-agent-loop.md
- 下一章工具系统(13 个工具、mtime 防护):docs/02-tools.md
- 核心引擎源码(约 2169 行,含 4 层压缩、流式并行执行):src/agent.ts
- 循环相关集成测试:test/integration/streaming-loop.test.mjs
这个项目把 50 万行代码的 Claude Code 浓缩成约 5000 行可运行教学实现,每一步都对着真实架构讲清差异,就像用一台卡丁车理解汽车:引擎、方向盘、刹车都在,每一颗关键螺丝都拧得清清楚楚。
社区交流
对 coding Agent、Agent Loop 实现细节感兴趣,可以加入 AI Agent 工坊交流群交流:
【免费下载链接】claude-code-from-scratchBuild your own Claude Code from scratch. 🔍 Claude Code 开源了 50 万行代码,读不动?用 ~5000 行 TypeScript / Python 从零复现核心架构,11 章分步教程带你理解 coding agent 精髓项目地址: https://gitcode.com/gh_mirrors/cl/claude-code-from-scratch
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考