Claude Code 源码泄露的消息上周在技术圈炸开之后,我第一时间把流出的核心模块过了一遍。长期做 Agent 开发的人,看到这份代码都会有个共同感受:这才是企业级智能体该有的样子。跟那些"一个 while 循环加一堆工具函数就声称是 Agent 框架"的开源项目相比,它完全不在一个量级。
这篇文章不聊事件本身的对错,也不做新闻复盘,只做一件事:把这份源码里值得参考的企业级 Agent 工程实践一条条拆给你看。我整理出 11 个点,覆盖 Agent 循环、工具设计、权限控制、上下文管理、可观测性、扩展机制六大层面。每个点我都会讲清楚"为什么这么设计",再给出"落到自己项目里该怎么改"。不管你是正在搭企业级 Agent 平台的架构师,还是想把个人项目从 demo 推到生产环境的开发者,这篇都值得读完。
1. 这次泄露的代码是什么:先看清 Claude Code 源码的含金量
1.1 流出的不是完整仓库,但核心运行时基本都在
先给没吃瓜的朋友补个背景:Claude Code 是 Anthropic 出的终端类编程 Agent 工具,你装好后在命令行里下任务,它会自己读写文件、跑命令、看测试结果,反复迭代直到完成。这次流出的代码,主要是这个工具的核心运行时,也就是驱动整个 Agent 跑起来的那部分逻辑。具体能看到的有:主循环实现、工具注册与调度器、权限判定模块、会话管理、多格式输出器,以及一部分钩子(hooks)定义。
需要说明的是,这不等于完整的官方私有仓库。像 MCP 服务端的一些商业组件、内部模型路由策略,并没有完整暴露。但对我们做 Agent 工程的人来说,核心运行时的设计已经足够有参考价值。很多人问"这东西值不值得逐行读",我的答案非常明确:值得,但重点不是一行行抠语法,而是读设计决策。这也是这篇文章的立脚点。
1.2 为什么生产级 Agent 的源码尤其值得学
市面上开源 Agent 框架其实不少,但问题在于绝大多数是教学级项目:代码漂亮、结构清晰,真跑到生产环境就崩。Claude Code 是被大量真实用户每天用来改真实代码库的产品,它的工程决策是为了处理真实世界的脏乱差做的。
我在代码里印象最深的一点,是工具调用的权限控制不是"一个 if 搞定",而是一整套规则引擎式的设计:区分自动放行、逐次确认、直接禁用,还能按目录和工具类型配置策略。这种设计背后是大量真实事故的沉淀。做 Agent 的人最缺的就是这种"被生产环境毒打过"的经验,这份代码恰好补上了这一课。
2. 先从源码看企业级 Agent 的四大骨架
在拆 11 个实践之前,我先把代码中体现的总体架构画个轮廓。Claude Code 的运行时大体分成四层:内核循环层、工具层、权限安全层、上下文管理层。四层各司其职,通过明确定义的数据结构和接口通信,而不是像很多项目那样所有逻辑搅在一个文件里。
2.1 内核循环层:思考-行动-观察的总指挥
内核循环层是 Agent 最核心的 while 循环:把用户指令和当前上下文组装成请求发给大模型,拿到响应后解析模型意图是继续说话还是调用工具;如果要调工具,就进入工具执行流程,把结果追加回上下文,再次发起请求,如此反复直到任务完成。
这层看起来人人都能写,但 Claude Code 的处理有两个关键细节值得注意。第一,循环是带状态的,每一轮都清楚知道自己在"等待用户确认""正在执行工具"还是"等待模型响应",而不是无脑轮询。第二,每一轮的思考、行动、观察(Thought-Action-Observation)都被完整记录。这些记录既服务于会话恢复,也服务于事后排查,相当于给 Agent 装了一个黑匣子。
2.2 工具层:能力边界从 Schema 开始
工具层管的是"Agent 能对世界做什么"。代码里内置了读写文件、编辑代码、运行 shell、搜索等工具,每个工具都有完整的名称、描述、参数 JSON Schema 和副作用等级。工具注册用数据驱动,所有调用先去 Schema 校验参数,非法输入在进入真实环境之前就被拦截。
这里有个很多项目会忽略的细节:工具描述本身也是"代码"的一部分。模型靠描述来决定什么时候用哪个工具,所以描述写得好不好,直接决定 Agent 的智能上限。这就像你给一个新同事写交接文档,写清楚了人家才办得对事。后面实践二我会专门展开。
2.3 权限安全层:能力不等于授权
工具层定义了"Agent 有能力做什么",权限层定义"Agent 被允许做什么"。同一个 Bash 工具,在自动放行模式下直接执行,在默认模式下弹确认框,在某些高危目录下直接拒绝。这个"能力与授权分离"的设计,是所有严肃 Agent 系统的核心,也是我最想让你抄走的一点。
说白了,能力是静态的,授权是动态的。两者混在一起,迟早出事。你项目的 Agent 能写文件,不代表它可以随便写生产环境的配置文件,这个边界必须由独立的权限层来守。
2.4 上下文管理层:决定模型记忆力的隐形功臣
上下文管理层负责在每次请求前,把系统提示词、项目记忆(类似 CLAUDE.md 的规则沉淀)、历史对话和工具结果裁剪成一份"刚好够用"的请求体。这里涉及 token 预算、消息裁剪、必要时做压缩总结。
很多 Agent 项目做到一定规模后性能骤降,用户以为模型坏了,其实是上下文被塞爆。Claude Code 的思路是预算提前算、压缩自动做,而不是等模型开始胡说八道再手工清理。做 Agent 平台的同学建议把 token 计数做成中间件,每次请求前统一处理,而不是在各个业务代码里零散维护。
3. 从源码拆出的 11 个 Agent 工程实践
这是全文的核心,我按"从内核到外围"的顺序把这 11 个点逐个展开。每个实践都先讲源码里的做法,再讲为什么,最后讲怎么落到你的项目里。
3.1 实践一:Agent 循环做成显式状态机,拒绝裸 while
先看很多开源框架的典型写法:
while not done: response = llm.chat(messages) if response.tool_call: result = execute_tool(response.tool_call) messages.append(result) else: done = True简洁是简洁,但上线就出问题:模型可能连续调用同一个失败工具几十次,可能绕过护栏反复执行破坏性命令,也可能在没获得用户确认的情况下就改了一堆文件。Claude Code 的循环是有显式状态的,能区分"等待用户确认"和"工具执行中",并且对工具调用有次数上限和失败回退逻辑。
落到你项目里,建议用状态枚举来约束转移路径:
VALID_TRANSITIONS = { "INIT": {"PLANNING", "WAITING_USER"}, "PLANNING": {"ACTING", "DONE", "FAILED"}, "ACTING": {"OBSERVING", "CANCELLED"}, "OBSERVING": {"ACTING", "PLANNING", "DONE"}, "WAITING_USER": {"ACTING", "CANCELLED"}, }循环体里只允许有限状态的合法跳转,异常直接终止或回退,而不是在混乱中继续。这个设计的价值在于,Agent 的行为变得可审计、可预测,这是生产环境的基础要求。状态机听起来多写了点代码,但排查问题时你会感谢它。
3.2 实践二:工具注册用 Schema 驱动,禁止 if-else 硬编码
我在不少 Agent 项目里见过这种写法:execute_tool 函数里一长串 if tool_name == "read_file" 的分支。新增一个工具就要改核心代码,参数校验散落在各个分支里,模型一旦吐出一个畸形参数,就直接穿透到真实环境。
Claude Code 的做法是把工具定义序列化成数据。每个工具包含 name、description、input_schema、副作用等级,调度器根据 name 找到实现,先用 input_schema 校验参数,通过才执行。简化示意长这样:
const tools: ToolDefinition[] = [ { name: "read_file", description: "读取指定路径的文件内容,用于理解当前代码", inputSchema: { type: "object", properties: { path: { type: "string", description: "文件绝对路径" }, }, required: ["path"], }, permissionLevel: "READ", }, ];这么做有三个直接好处。第一,新增工具不需要动调度逻辑,只用注册一份定义。第二,参数校验前置,模型幻觉生成的非法参数被拦在工具外面。第三,每个工具的能力边界一目了然,权限层可以直接根据 permissionLevel 做决策。这三个好处,任何一个都值得你把代码改成 Schema 驱动。
3.3 实践三:权限模型默认拒绝,危险操作逐次确认
这是整个源码里我最推荐抄的设计。Claude Code 的权限模型不是"要不要拦一下",而是默认不信任:工具能做什么是一回事,被允许做什么是另一回事。权限判定走的是一个可配置的规则链,支持三类结果:放行、询问、拒绝。
| 工具类型 | 默认策略 | 典型场景 |
|---|---|---|
| 只读工具(读文件、搜索) | 自动放行 | 代码理解、检索 |
| 低风险写工具(编辑文件) | 自动放行或询问 | 常规代码修改 |
| 高风险工具(shell、删除) | 询问或拒绝 | 执行命令、清理 |
落到你的项目里,最关键的一点是:默认值必须是"询问"或"拒绝",而不是"放行"。演示时觉得弹确认框很烦,但真实环境里,一次误删除或误执行的代价远超那点确认成本。我自己的平台里还加了一层策略:按目录配置白名单和黑名单,开发目录自动放行,生产目录一律拒绝,这个思路就是从这里来的。
3.4 实践四:上下文预算显式管理,压缩是常态不是应急
大模型的上下文窗口虽然越开越大,但真实 Agent 会话里塞进去的历史对话、工具结果、错误日志增长极快。Claude Code 的做法是显式管理 token 预算:请求前计算上下文长度,超过阈值就触发裁剪或压缩。裁剪是直接丢弃老的次要消息,压缩是把前面的对话交给模型做摘要再放回上下文。
这一点特别重要,因为很多 Agent 项目前期跑得很好,聊久了能力突然跳水。用户以为模型坏了,其实是上下文被塞爆了。Claude Code 的设计思路是:预算要提前算,压缩要自动做,而不是等问题出现再清理。我建议你把 token 计数做成一个中间件,统一拦截所有请求做上下文整理,包里带着预算、用了多少、还剩多少,三个字段一目了然。
3.5 实践五:用 Hook 事件机制做扩展,而不是 fork 源码
Claude Code 的扩展性设计非常典型:核心代码不开放给人乱改,但定义了完整的生命周期事件,比如用户提交 prompt 前、工具执行前、工具执行后、Agent 进入新轮次等。使用者通过配置回调或脚本响应这些事件,实现策略注入。
这个设计对企业来说是刚需。举个例子:团队要求代码 Agent 不能未经评审就修改某些核心模块。如果一个个去改 Agent 源码,升级一次就崩一次。用 Hook,你在 PreToolUse 事件里写一段策略脚本,检查工具类型和目标路径,命中高危规则就返回"拒绝",这比 fork 源码做定制干净得多,也经得起版本升级。
3.6 实践六:复杂任务交给 Subagent 分治,不让一个 Agent 干到底
一个 Agent 一把梭地处理复杂任务是很多项目的通病:超长任务把上下文撑爆,各种子任务目标互相干扰,模型越做越糊涂。Claude Code 的思路是把任务拆给 subagent 专业子代理。每个 subagent 只负责一个明确子任务,比如分析代码结构、跑测试、做代码审查,各自的系统提示词聚焦,上下文相对独立,最后把结构化结果返回给主 Agent。
用生活化的类比:你不会让一个全科医生包办所有手术,而是会让外科、麻醉、影像各司其职。Agent 也一样,分工细化能显著提升准确率和可控性。做这类实现时,关键在于每个 subagent 的输入输出协议要定义清楚,返回值要是结构化摘要而不是大段对话记录,否则上下文污染问题依旧存在。
3.7 实践七:流式输出是架构必需品,不只是体验优化
很多 Agent 项目用"攒完整响应再展示"的方式,用户盯着光标转圈,一等就是几十秒。Claude Code 把流式输出当成基础能力:模型 token 实时打印,工具执行状态实时更新,你甚至能看到它正在读哪个文件、跑哪条命令。
这个设计看起来是体验问题,其实是架构问题。长任务的 Agent 天然耗时,如果流程不流式化,一是用户完全无法判断 Agent 是不是卡死了,二是中间失败时没有任何可恢复的中间状态。落地建议:从架构上把所有 Agent 事件(模型输出、工具启动、工具完成、错误)设计成事件流,前端订阅事件流做渲染,后端订阅事件流做调度和观测,一套机制搞定多个需求。
3.8 实践八:会话持久化,中断之后能精确恢复
真实使用中,Agent 跑一半进程被杀、网络断掉、电脑重启,都是常态。Claude Code 会把整个会话的历史——消息、工具调用、结果、权限决策——完整持久化,支持断点恢复。你重新打开后可以接着上次的上下文继续对话,不用从头解释需求。
这个实践对构建可靠系统的价值怎么说都不过分。会话持久化不仅是用户体验,更是数据资产:每个会话都是一份完整的执行记录。我自己的做法是为每个会话生成独立 ID,所有事件按时间戳追加到会话存储里,恢复时按序重放,相当于给 Agent 装了"存档系统"。企业里做 Agent 平台,这个功能必须一开始就设计进存储模型,后期补非常痛苦。
3.9 实践九:输入输出用结构化契约,人机边界才清晰
Claude Code 的接口层有个很值得学的点:它同时提供面向人的可读输出和面向机器的结构化输出(比如 JSON 模式)。不管哪种模式,内部的工具调用请求和结果都走严格定义的结构化协议,字段有 schema、版本、类型校验。
这背后是一个很朴素的道理:Agent 系统不是只有大模型,它还要跟 CI 流水线、监控系统、其他服务协作。如果 Agent 输出全是自然语言散装文本,对接方只能用正则硬抠,必然又脆又乱。结构化契约让你的 Agent 可以被其他系统可靠地集成,这是走向企业级的关键一步。建议定义一套统一的事件对象模型,所有输出都从这上面渲染,而不是各写各的。
3.10 实践十:全量日志落盘,问题排查靠"回放"而不是猜
Agent 系统最难排查的问题是"它为什么这么做"。模型调用是黑盒,工具执行是分散的,如果没有完整日志,出了问题只能靠猜。Claude Code 把每一轮请求的 prompt、模型响应、工具输入输出、耗时、错误信息全部落盘,格式是 JSONL,方便按时间逐行回放。
这个实践我强烈建议任何 Agent 项目从第一天就做。日志记录的不只是结果,还有过程:模型看到了什么上下文、选择了哪个工具、工具返回了什么、它基于这个结果做了下一步什么决策。有了这些,调试 Agent 就像看回放录像一样,哪里偏离预期一目了然。在企业里,这份日志还能直接用来做评测集、回归测试和审计追溯,价值远超"排错"本身。
3.11 实践十一:MCP 接入先做协议收敛和鉴权,再谈扩展
MCP(Model Context Protocol)现在基本是 Agent 生态的事实标准,Claude Code 对 MCP 的支持也是这套代码里的亮点。但值得注意的设计是:MCP 服务器的工具并不会直接暴露给模型随便调用。接入层会先把 MCP 工具映射成内部统一的工具 Schema,做参数收敛,再经过权限判定,最后才进入调度器执行。
这一步非常重要。直接把外部 MCP 工具一股脑塞给模型,等于把五十个不受控的入口交给一个不可预测的调用方,安全隐患非常大。正确做法是在 MCP 边界做四件事:Schema 翻译、鉴权校验、速率限制、审计日志。外部工具再丰富,也必须过你的安全闸门,这个原则做 Agent 平台的团队越早建立越好。
4. 复刻这套 Agent 架构时最容易踩的 5 个坑
这节是我自己动手做过几个 Agent 平台之后总结的教训。源码可以抄,坑也可以提前避,下面几条几乎每个团队都会踩。
4.1 坑一:工具失败的反馈没有接回模型
很多实现的错误处理是执行工具 → 失败 → 记录错误 → 结束。模型根本没有机会看到"工具失败了、为什么失败、建议怎么换路"这些信息,于是只能反复用同一种错误方式重试,白白浪费 token 和时间。
正确做法是把工具执行结果(包括错误栈、退出码、关键输出片段)原样追加回上下文,让模型基于真实反馈做下一步决策。这相当于你教一个新同事:做错了不要闷头重试,先看看报错信息再调整策略。
4.2 坑二:权限体系全自动,上线必翻车
演示阶段为了效果,很多项目把权限全部设成自动放行。看着是敏捷了,一到生产环境,模型一个破坏性误操作就能让你后悔。权限默认值必须是"询问"或"拒绝",自动放行只留给明确验证过安全性的只读类工具。
我见过最惨的案例:Agent 在重构任务里误把生产配置目录当测试目录改写,因为没有确认环节,几千条配置直接改坏。全自动权限在演示时是爽点,上线时就是事故点。
4.3 坑三:工具描述写太敷衍,模型不知道该用哪个
很多项目的工具定义就一句话"执行命令"。模型拿到这种描述,根本不知道这个命令工具有没有危险操作、输出格式是什么、适用场景是什么。描述写得差,Agent 就不会在正确时机选择正确工具,这比代码写得差更隐蔽也更致命。
写工具描述有个小技巧:像教一个刚入职的开发一样,写明工具的输入输出、副作用、适用场景、不适用场景,甚至给一两个例子。模型是靠描述做决策的,描述就是工具的"说明书",花在打磨描述上的时间回报率极高。
4.4 坑四:参数校验放执行后,等于把炸弹交给模型
不少项目图省事,在工具实现内部才做参数检查,结果就是模型的错误参数已经穿透到文件系统或 shell 里了,这时候发现问题已经太晚。正确做法是在调度器里、工具执行前做严格的 Schema 校验,非法输入直接拒绝,不给它碰真实环境的机会。
4.5 坑五:不设计会话恢复,任务一断就前功尽弃
长任务执行中进程被杀是常态,如果会话不能恢复,用户要么重新解释一遍需求,要么接受半途而废的结果。会话持久化看似麻烦,其实是构建可靠 Agent 的底线。记住一点:所有关键事件都要落盘,恢复时要能还原出完整的上下文,否则生产环境的可用性无从谈起。
5. 抄代码容易,抄决策难:最后的个人体会
把这份源码拆完,我最大的感受是:技术细节其实不难抄,难的是背后那些决策逻辑。为什么权限默认拒绝?为什么工具要 Schema 驱动?为什么日志要全量落盘?这些问题的答案不是某个大神的灵光一现,而是生产环境一次一次事故换来的。
5.1 看完源码我做的最重要的两个调整
我自己搭 Agent 平台时踩过不少坑。看完这份代码后,第一件事是把权限模型整个重写了,从"全量放行加特例"改成"默认拒绝加白名单";第二件事是把上下文管理从前端页面里抽出来,塞进了中间件层,统一做 token 预算和压缩。改完之后,线上问题的定位时间从小时级降到了分钟级,这让我更确信:做企业级 Agent,别追求炫技,先保证可控、可观测、可恢复。
5.2 实操落地的优先级建议
如果你也想从这份源码里学东西,我的建议是别急着把 11 个实践全部抄一遍。先做日志落盘和会话持久化,这两个是可靠性的地基;再做权限默认拒绝,这是安全底线;然后才是 Schema 驱动工具和 subagent 分治这些能力增强项。每完成一项就上线验证,用小步快跑的方式逐步逼近企业级。
做内部效率工具,权限默认询问就够了;做对外 API 服务,可能需要更细粒度的 policy 引擎。把决策逻辑想通,代码怎么写都是对的。