Claude Code 源码研究:一个 while(true) 循环让大模型自己干活

张开发
2026/4/6 18:00:40 15 分钟阅读

分享文章

Claude Code 源码研究:一个 while(true) 循环让大模型自己干活
2026 年 3 月 31 日Anthropic 因为一次 npm 发布事故把 Claude Code 的完整 TypeScript 源码泄露到了公网。50 万行代码、1900 个源文件一览无余。韩国开发者 Sigrid Jin 将这批源码整理并上传至 GitHubhttps://github.com/instructkr/claude-code随后又基于原始架构做了 Python clean-room 移植 。这是一次罕见的机会我们终于可以打开一个顶级 AI Agent 的引擎盖看看里面到底装了什么——01Claude Code 是什么Claude Code 是 Anthropic 做的一个终端 AI 助手。注意不是网页聊天框是你打开终端、敲命令行用的那种工具。你在终端里对它说帮我把项目里所有 console.log 换成 logger.info它就会自己去搜代码、读文件、改文件、跑测试——全程像一个真人在操作你的电脑。你不需要手把手告诉它每一步做什么它自己规划、自己执行、自己验证。虽然它目前主要用于编程场景但其底层架构并不局限于写代码。读文件、执行命令、搜索网页、调用外部服务——这套机制可以驱动 AI 完成任何需要多步操作的复杂任务。编程只是它最先落地的场景。这就是所谓的 AI Agent。和普通聊天机器人的区别在于聊天机器人只能说Agent 能做。02一个“死循环”撑起的自主决策Claude Code 的核心引擎叫 Agent Loop实现在一个叫query.ts 的文件里从第 303 行写到第 1729 行一千四百行代码。但把所有细节剥掉骨架只有一句话while (true) {调用 API把用户需求和工具列表发给 Claude 模型收到模型回复if (回复里没有工具调用请求) → 退出循环else → 执行模型要求的工具把结果塞回对话历史继续循环}就这。一个 while(true) 无限循环一个 needsFollowUp 布尔标志。每一轮循环做的事情是把当前的完整对话历史包括用户的原始需求、之前每一轮 AI 的回复、每一次工具执行的结果打包发给 Claude 模型的 API。模型返回的内容里可能包含三种东西文字text——要对用户说的话思考thinking——内部推理过程以及工具调用请求tool_use——请帮我执行这个操作。关键判断就在这里如果回复中包含任何 tool_use循环继续如果一个 tool_use 都没有循环结束。源码里的实现非常直白if (msgToolUseBlocks.length 0) {needsFollowUp true}以及if (!needsFollowUp) {return { reason: completed }}没有复杂的状态机没有花哨的流程编排。循环继不继续完全取决于模型自己的输出里有没有工具调用请求。为什么没有 tool_use就意味着结束这不是 Claude Code 团队拍脑袋定的规则而是 Anthropic Messages API 的 Tool Use 协议本身的语义。当 Claude 模型觉得还需要获取信息或执行操作才能完成任务——它在回复里放一个 tool_use block意思是我需要这个操作的结果才能继续。当模型觉得信息已经足够可以给出最终答案——它只返回文字不再请求任何工具。换句话说退出循环不是代码的决策是模型的决策。 Claude Code 只是忠实地执行了这个决策。这是整个架构中最精妙的地方一个看似简单的布尔判断把任务是否完成这个极其复杂的判断完全委托给了大模型的推理能力。代码不需要理解任务是什么不需要定义完成长什么样——模型自己知道。上下文的雪球效应每一轮循环结束后本轮模型的回复和工具执行结果都会被追加到消息历史中。下一轮发给 API 的消息比上一轮多了一段……像滚雪球一样模型在每一轮都能看到自己之前做了什么、得到了什么结果从而做出连贯的下一步决策。这也是 Agent 能记住自己在做什么的根本原因——不是因为它有记忆而是因为每次决策时所有历史都摆在它面前。代价当然也很明显token 消耗逐轮递增。Claude Code 为此实现了一整套上下文压缩机制——自动摘要、渐进折叠、紧急压缩——来应对雪球越滚越大的问题。但这是工程细节不影响核心架构的理解。03不是代码而是模型在选择工具Claude Code 内置了大约 40 个工具Bash执行命令、FileRead读文件、FileEdit改文件、Grep搜索代码、WebFetch抓网页、AgentTool派生子 Agent……覆盖了从日常开发到系统运维的绝大多数操作场景。一个自然的问题是模型怎么知道该用哪个工具答案可能再次出乎意料Claude Code 的代码里没有任何工具选择逻辑。没有 if-else没有决策树没有规则引擎。选哪个工具、传什么参数百分之百是 Claude 模型自己在推理过程中决定的。40 本说明书Claude Code 做的事情是给每个工具写了一份详细的自然语言说明——像产品说明书一样。每次调 API这 40 份说明书会被一起塞进请求里。以 BashTool 为例它的说明长达数百行不只告诉模型这个工具能执行 shell 命令还包括什么时候该用它执行构建、测试、安装依赖什么时候不该用它不要用 cat 读文件用 FileRead不要用 sed 改文件用 FileEdit安全红线不要 force push 到 main 分支超时限制、参数格式、沙箱规则……模型读完这 40 份说明书结合用户的需求和当前的上下文自己判断下一步该用哪个工具。这就像你给一个经验丰富的工程师一份工具清单和操作手册。你不需要告诉他现在请用扳手拧第三颗螺丝——你只要把手册给他他自然知道什么场景用什么工具。软引导而非硬编码Claude Code 无法强制模型的选择但可以通过说明书的措辞来施加影响。BashTool 的说明里有这么一段IMPORTANT: Avoid using this tool to run cat, head, tail, sed, awk, or echo commands. Instead, use the appropriate dedicated tool...这不是代码层面的限制——就算模型非要用 Bash 执行 cat代码也会照样运行。但这段自然语言描述会影响模型的推理过程让它更倾向于选择专用工具。这是一种通过语言塑造行为的引导方式。不是铁栅栏是路标。模型有完全的自由意志但精心撰写的说明书会让它大概率做出更合理的选择。某种意义上Claude Code 团队最重要的工作之一不是写循环逻辑而是写好这 40 份说明书。工具说明的质量直接决定了模型行为的质量。04一个执行轨迹实例把上面的原理串起来看一个具体的例子。用户输入帮我把项目里所有 console.log 替换成 logger.info确保能正常运行。Agent 的执行轨迹如下第 1 轮模型读到需求决定先摸清状况。返回两个工具调用——用 Grep 搜索所有包含 console.log 的文件用 FileRead 看 package.json 了解项目结构。第 2 轮模型看到 Grep 结果5 个文件命中再发一个 Grep搜索项目里有没有现成的 logger 模块。第 3 轮发现项目已有 src/utils/logger.ts。模型一口气返回 5 个 FileEdit 调用逐个文件替换。第 4 轮5 个文件全部编辑成功。模型返回一个 Bash 调用npm test。第 5 轮测试全部通过。模型只返回一段文字全部完成替换了 5 个文件所有测试通过。没有 tool_use。循环结束。五轮循环从搜索到发现到修改到验证每一轮调用的工具种类和数量都不同全部由模型根据当时的上下文自主决定。没有任何预设的流程图没有人告诉它第一步搜索、第二步确认、第三步修改——它自己推理出了这个序列。05架构的简洁之美读完 Claude Code 的源码最大的感受不是这代码真复杂而是这个架构选择真大胆。把任务完成了吗这个判断交给模型把该用哪个工具这个选择交给模型把下一步做什么这个规划交给模型——Claude Code 的代码本身几乎不做任何业务决策。它只做三件事传话、跑腿、反馈结果。这是一个深刻的架构哲学当模型足够强时最好的 Agent 框架不是替模型做决定而是给模型最好的决策环境。40 份精心撰写的工具说明书就是这个决策环境的核心。不是用代码约束模型的行为而是用语言塑造模型的认知。这让我想到一个更大的命题。过去我们构建软件系统核心工作是编写逻辑——if-else、状态机、流程引擎。而在 Agent 的世界里核心工作变成了编写描述——用自然语言告诉 AI 它有什么能力、什么该做、什么不该做。代码从控制流变成了信息流。工程师从逻辑的编写者变成了上下文的策展人。这大概就是 AI Agent 真正带来的范式转移。不在于 while(true) 有多精巧而在于我们开始用一种全新的方式构建软件——不是编程让机器执行而是描述让智能体理解。今天它在写代码明天它可以在做任何事。循环是同一个循环说明书换一套就行。欢迎关注微软智汇AI官方账号一手资讯抢先了解喜欢就点击一下在看吧~

更多文章