乐于分享
好东西不私藏

花两周读完 Claude Code 源码后,我总结了 6 个让你敢在生产环境用 AI Agent 的设计

花两周读完 Claude Code 源码后,我总结了 6 个让你敢在生产环境用 AI Agent 的设计

一个能自己执行 

rm -rf 的机器人,凭什么不让你害怕?

你也许在终端里试过 Claude Code:输入一句话,它就开始读文件、改代码、跑测试,甚至帮你 git commit
第一次见到这种场景,很多人会下意识紧张——它怎么敢的?它凭什么不会把我的项目毁掉?

答案藏在它的源码里。Anthropic 开源了 Claude Code 的全部 51 万行 TypeScript 代码。我花了两周时间,把核心模块啃了一遍。
这篇文章不讲概念,只说它到底用了哪些朴素但过硬的设计,才做到既强大又安全。


一、先从最核心的“脑子”说起:Agent 循环

Claude Code 不是一条写死的流水线。它的运行方式可以浓缩成 4 个动作:

看 → 想 → 做 → 看结果

用专业术语说就是:感知 → 决策 → 行动 → 观察。
这个循环会一直重复,直到它自己觉得“任务完成了”。

下面这段伪代码,基本就是它的骨架:

typescript

while(未达到最大轮数){const 上下文 =组装当前消息();const 响应 = 调用LLM({ 上下文, 可用工具 });const 要调用的工具 =从响应中提取();if(要调用的工具.length ===0){break;// LLM 主动结束}for(const 工具调用 of 要调用的工具){if(await权限检查通过(工具调用)){const 结果 =await执行工具(工具调用);      消息列表.push(结果);}}// 下一轮循环会带着新结果继续}

这里最反直觉的一点:循环停不停,不是由计数器决定,而是由 AI 自己判断。
只有当 LLM 觉得“不需要再动任何工具”时,它才会输出最终回答。这就是 Agent 的「自主性」来源。


二、工具系统:不是说“能做什么”,而是“怎么安全地做”

Claude Code 内置了 20 多个工具,比如 ReadWriteBashGrep
但比“有哪些工具”更关键的是每个工具都带了一张自检清单

每个工具注册时,会附上这些信息:

  • 参数格式(JSON Schema)

  • 是否需要用户确认

  • 风险等级(低 / 中 / 高)

  • 是否只读

  • 是否需要沙箱执行

拿 Bash 举例:

typescript

{  name:"Bash",  requiresPermission:true,  metadata:{    readOnly:false,    needsSandbox:true,    riskLevel:"high"},execute:async(params)=>沙箱里执行命令(params.command)}

执行一个工具的完整路径是:

text

请求 → 权限判定 → 参数校验 → 沙箱运行 → 结果返回

一旦遇到高危命令(比如 rm -rf /),沙箱和权限系统会双重拦截。
这种设计的好处是:每个工具都可以被独立测试、独立审计,而不是塞在一个巨大的 switch-case 里。


三、上下文窗口不够用?三层策略硬扛

大模型的上下文窗口再大,也扛不住几十轮工具调用。Claude Code 没有简单粗暴地“把最早的扔掉”,而是用了三层递进策略。

水位线
触发动作
< 70%
正常运转,不做干预
70% ~ 85%
对过大的单条工具结果做裁剪(保留头尾,切掉中间)
85% ~ 95%
对早期的对话生成摘要,释放空间
> 95%
强制丢弃最早的一批消息

还有一个非常聪明的优化:文件内容去重
如果同一个文件被读了好几次,第二次开始就不再重复塞入内容,只放一句引用:

text

[File already read at message #3]

这样能省下相当可观的 token。


四、让 AI 听懂项目规矩:CLAUDE.md 的三级覆盖

你是否遇到过这种烦恼:每次跟 AI 对话,都要重新说一遍“我们项目用 ESLint”“不要用 any 类型”?
Claude Code 用 CLAUDE.md 解决了这个问题。

它会从三个位置依次加载配置,后面的会覆盖前面的:

  1. 全局~/.claude/CLAUDE.md(你的个人习惯)

  2. 项目根目录<项目>/CLAUDE.md(团队规范,可以提交到 Git)

  3. 当前目录<当前路径>/CLAUDE.md(局部特殊规则)

优先级低的先加载,优先级高的后加载并覆盖。
合并后的内容被注入到 System Prompt 里。这样 AI 从一开始就知道你的项目约定,不用每次都唠叨一遍。


五、权限系统:宁可多问一次,也不擅自执行

AI Agent 的安全底线就两个字:确认
Claude Code 的权限系统把工具分成了三个层次:

  • 自动放过:只读操作(Read、Grep、Glob) → 不打扰你

  • 需要确认:写操作(Write、Edit) → 弹窗问一下

  • 严格模式:高危操作(Bash、网络请求) → 额外检查黑名单,并且强制你点头

黑名单里有什么?举个例子:

typescript

/rm\s+-rf\s+\//,// 删根目录/git\s+push\s+--force/,// 强制推送/mkfs\./,// 格式化磁盘

而且权限系统有一个“会话记忆”:如果你对某个操作选了「这次会话都允许」,后续同类操作不会再问。
这样既不用每次点“同意”,也不会让危险操作悄悄溜走。

终端里看起来是这样的:

text

Claude wants to run: git commit -m "fix: bug"  Allow?  > Yes (y)    Yes, and don't ask again for git commands (!)    No (n)

六、和 Cursor 对比:不是敌人,是搭档

很多人喜欢拿 Claude Code 和 Cursor 比谁更强。实际上它们的基因完全不同:

维度
Claude Code
Cursor
入口
终端
VS Code 插件
驱动模式
Agent 自主循环
IDE 事件驱动
优势场景
跨文件重构、复杂任务链、自动化流程
实时补全、日常编码、UI 交互
可编程性
高(CLI / SDK)
低(以 GUI 为主)

一个很实用的建议:日常写代码用 Cursor,遇到“把整个模块的 API 调用方式重构一遍”这种复杂任务,交给 Claude Code。它俩是互补的。


七、整套系统的三条底裤(设计哲学)

啃完源码,我发现 Claude Code 的所有设计都围绕三条朴素的原则:

  1. 安全第一
    沙箱、超时、黑名单、权限确认……怎么啰嗦都不为过。宁可打断用户的流畅感,也不给灾难留机会。

  2. 用户控制
    任何写操作你都可以拒绝。随时 Ctrl+C 中断。CLAUDE.md 让你给 AI 画好行为边界。AI 是工具,你永远是主人。

  3. 可预测行为
    同样输入 + 同样项目配置 → 同样输出。没有随机“灵光一现”,也没有黑盒般的错误。每个工具的失败都会给出明确建议。


八、避坑笔记(别人踩过的,你就别踩了)

常见坑
正确的做法
以为 Agent 循环是同步阻塞的
工具可以并行执行,必须处理竞态
上下文管理只会截断
用「裁剪 → 摘要 → 去重缓存」三级
权限做成全放行或全拒绝
分级 + 会话记忆才是正解
CLAUDE.md

 写了上千行
控制在 500 token 以内,只写关键约定
工具不是幂等的
设计成多次调用不会产生副作用

最后的话

如果你也在做 AI Agent,Claude Code 的这套设计非常值得借鉴:

  • Agent Loop 让 LLM 自己决定何时结束任务

  • 工具系统 把“能力”和“安全控制”绑在一起

  • 上下文管理 不是简单丢弃,而是分层压缩

  • CLAUDE.md 给了项目级 AI 配置一个优雅范本

  • 权限系统 把“用户控制”落实到每一行命令

以及最重要的一点:不要试图找一个“最强”的 AI 编码工具。理解不同工具的架构差异,在正确的场景选择正确的工具,才是工程师应有的务实态度。

如果你也在研究 AI Agent 源码,欢迎一起交流。

— 来自一个连续两周熬夜看 TypeScript 的工程师