Claude Code 架构设计深度剖析
Claude Code 架构设计深度剖析:从启动到多 Agent 扩展层
该文章由AI生成,仅供个人学习使用。
写在前面:这篇文章只做一件事——把 Claude Code 拆成几个真正决定系统质量的核心模块,逐层讲透其关键设计决策。不聊"怎么用",只聊"为什么这样设计"。
核心问题:为什么有些 Agent 一复杂就散架?
这两年大家都在写 Agent,但有一个尴尬的共识:Demo 阶段势如破竹,一旦加到三五个工具、几种运行模式、几类权限规则,系统就开始肉眼可见地变形——主循环越来越脏,工具一多就互相污染,后台任务和前台会话互相打架,扩展一接进来就满地特判。
模型能力固然重要,但真正决定一个 Agent 能不能长期活下去的,往往不是模型本身,而是围绕模型搭建起来的运行时(Runtime)。
Claude Code 值得深入拆解,不是因为它"功能很多",而是因为它已经在真正承接复杂度。它的价值不止于竞品分析,更是一个现成的架构参照物:哪些复杂度应该前置,哪些应该制度化,哪些必须通过架构收敛——而不能继续靠 prompt 和人肉兜着。
换句话说,这篇文章真正想回答的不是"Claude Code 有哪些功能",而是——"为什么有些 Agent 系统一复杂就散架,而它没有"。
总架构概览
在深入各层之前,先建立一个全局视角。Claude Code 的整体架构可以概括为 7 层运行时,每一层承接一种特定的复杂度:
接下来,我们逐层拆解。
1. 入口与启动链路:别急着拉起全世界
核心矛盾
一个成熟的 Agent 往往要同时支持本地交互、headless、SDK、remote、后台 session、会话恢复等多种运行模式。如果启动层不先把模式、边界、权限和上下文装配清楚,后面每个宿主都会偷偷长出自己的运行语义,最终系统会裂成几套互不兼容的分支。
很多系统的入口是一个越来越胖的 main,恨不得一上来就把全世界都拉起来。Claude Code 在这里反而很克制——它先做了一次非常关键的判断:先分流,再装配,最后才进入会话。
Claude Code 的解法
从源码看,启动过程大致分为三段:
第一段:入口分流。系统不急着把整个运行时拉起来,而是先判断这次到底是什么启动——本地交互、无界面运行、远程接入、后台会话管理,还是极简 fast path。很多路径都用动态加载,说明 Claude Code 从一开始就在控制启动成本,而不是先把全世界加载进来再说。
第二段:进程级初始化。这一层处理的是运行环境:配置、telemetry、远程设置、清理回调等全局设施。关键在于它刻意不碰当前会话语义——回答的是"进程能不能跑",而非"这一轮 Agent 该怎么跑"。
第三段:会话级准备。到这里才开始确定工作目录、会话身份、工具面、权限模式、扩展能力、系统约束、恢复方式等信息,最后决定由交互式宿主还是无界面引擎来承载。
两个关键的设计细节
这中间有一个容易被忽略、但对架构至关重要的细节:Claude Code 把"进程状态"和"交互状态"分开了。
像 cwd、projectRoot、sessionId、telemetry、token/cost 计数这类基础设施状态,沉在 bootstrap/state 一类全局状态里;而 tasks、MCP clients、plugin 状态、permission context、界面选择状态这类控制面状态,才进入 AppState。
这个分层让系统不会把 React state 误当成整套 runtime 的唯一真相,也不会把所有状态都做成不可控的全局变量。
为什么这样好
直接收益是:无界面运行、交互式运行、远程运行、后台运行可以共享同一套核心 runtime,而不是各自长一套逻辑。权限、工具、系统约束、扩展能力这些影响执行边界的要素,都能在第一轮请求前定型,后面的主循环不需要一边跑一边猜。
更深层的好处是:系统复杂度被前置了。很多项目把模式判断、权限边界、宿主差异拖到运行中解决,主循环因此越来越脏。Claude Code 把这类复杂度尽量压到启动层,运行时主链路反而更纯净。
我们怎么学
最值得吸收的不是"复杂入口",而是次序感——凡是会影响执行边界的东西,尽量在第一轮请求前定型。
如果还在单一交互模式阶段,不必照抄这么厚的入口层,但至少要先把三件事分开:启动模式、会话制度、宿主承载。如果已经同时有命令行、接口调用、后台任务、远程运行等多种方式,这一层就不能再含糊了——否则很快就会长成几套彼此不兼容的 Agent。
一个实用的起点:先把"启动时必须定型的边界"列成一张清单。
2. REPL / UI Orchestration:UI 不是传话筒
核心矛盾
很多团队把聊天 UI 理解成"显示消息的壳"——大模型吐什么,前端就渲染什么。Claude Code 明显不是这样。它的 REPL 本质上更像一个运行时控制台。
一旦 Agent 不只是聊天,而开始执行工具、弹权限、跑后台任务、动态接入扩展,UI 面对的就不再是"如何显示回复",而是"如何把一个复杂 runtime 变成用户可操作、可理解、可干预的系统"。这一层做不好,所有关键状态都会变成黑箱。
Claude Code 的解法
REPL 的启动层很薄,说明它不是启动中心,而是一个被装配好的宿主。真正值得注意的是,REPL 把输入、消息流、权限确认、任务、MCP 连接、插件状态、远程状态、后台 session 等全部编排到同一个控制面里。
这意味着 Claude Code 的 UI 不是"模型回复展示器",而是 runtime 的 orchestrator。一次用户输入进入 REPL 后,不是直接丢给模型,而是先经历一条完整的预处理链路:
也就是说,REPL 先把"这一轮在什么制度下运行"准备好,再把控制权交给推理循环。
能力面汇总 + 事件流归并
更具体地说,REPL 真正负责的是"当前能力面"的汇总——把本地 tools、MCP tools、plugin commands、动态 skills、任务状态、权限确认队列、MCP 连接状态、remote session 信息汇在一起,在用户提交输入的那个瞬间,生成一个完整的 turn-scoped 执行上下文。
这也是 REPL 显得很"大"的原因:它并不是一个 view component,而是在做控制面拼装。
另一层很重要的设计是,REPL 消费的不是纯文本,而是一串带语义的事件流。assistant message、tool progress、compact boundary、pending permission、task notification、API error——这些事件都会在这里重新归并成用户能理解的会话视图。
换句话说,REPL 既是 query 的入口,也是整套运行时事件的落点。
为什么这样好
最大的好处是"可控"。用户不是只看到一句模型回复,而是能看到系统正在执行什么、为什么停下来、当前有哪些能力、后台有哪些任务。对于需要权限确认、长时执行、工具调用的 Agent 来说,这种可控感往往比多一点模型智商更重要。
还有一个容易被忽略的收益:UI 不再只是消费文本,而是在消费统一事件协议。query、permission、tool runtime、task system 都可以通过结构化事件与 REPL 协作,而不是各自偷偷改 UI 状态。
我们怎么学
如果产品还停留在单轮问答,聊天 UI 足够。但只要系统进入了工具执行、权限确认、后台协作阶段,UI 就必须承担显式控制面的职责。
最容易学错的地方,是把"控制面"理解成堆更多面板。真正该学的是显式化运行时关键状态:当前能力面、当前任务、当前权限状态、当前失败与恢复状态。不是界面越花越强,而是用户越能理解系统在做什么,越容易信任并驾驭它。
一个好的起点:先把后台任务和权限状态显式展示出来。
3. Query Loop / QueryEngine:把单轮对话升级成运行时
核心矛盾
如果说前两层是在搭台子,那么 Query Loop 才是真正决定一个 Agent 像不像成熟 runtime 的分水岭。很多团队的 Agent 到了这里才开始真正分出高下。
只要 Agent 开始连续运行,系统就会立刻碰到几个硬问题:长上下文劣化、工具调用打断推理、模型输出截断、失败后是否恢复、工具结果如何回灌下一轮。这些问题如果还被当成"模型调用细节",系统就会在复杂场景里迅速失稳。
Claude Code 的解法
先分清两个对象:
- 无界面会话引擎:不是主循环本身,更像会话外壳
- Query Loop 本体:真正的 agent turn 内核
无界面会话引擎的职责很有代表性:先拉系统上下文,处理输入和命令,把用户消息写进会话记录,暴露当前能力面,然后才把处理后的消息流交给主循环。这说明 Claude Code 不把 query 理解成"收到输入就打一次模型",而是理解成"会话侧状态都准备好之后的最后一步"。
真正的核心在 Query Loop 本体。从状态组织方式就能看出来,这里维护的不是一次性请求参数,而是一组跨迭代的运行时状态:消息集、执行上下文、上下文压缩状态、输出恢复计数、轮数预算、任务预算等。
如果把源码里的状态骨架压到最小,会更容易看出它为什么已经是 runtime,而不是"模型调用封装":
state = {
messages,
toolUseContext,
maxOutputTokensOverride,
autoCompactTracking,
maxOutputTokensRecoveryCount,
hasAttemptedReactiveCompact,
turnCount,
pendingToolUseSummary,
transition,
}
这段骨架非常关键。一个普通 orchestrator 不会长期维护 autoCompactTracking、maxOutputTokensRecoveryCount、pendingToolUseSummary 这类对象;一旦这些状态都进入主循环,说明系统已经承认:一次 agent turn 会被压缩、恢复、工具回灌、预算和中断反复改写。
主循环的真实面貌
下图展示了 Query Loop 每一轮迭代的完整流程——从预取到流式推理,再到工具执行和结果回灌:
从运行顺序看,Claude Code 对 query 的理解非常"系统化":先处理记忆预取、能力发现、上下文预算、各种压缩与折叠,再进入流式采样;一旦模型发出工具调用,runtime 就接管执行,把结果整理成结构化反馈、附加材料和后续提示,再重新送回下一轮推理。
如果把主循环压成最小骨架:
while (true) {
prefetchMemoryAndSkills()
messagesForQuery = applyBudget(messages)
messagesForQuery = snipAndCompact(messagesForQuery)
assistant = streamModel(messagesForQuery)
if (!assistant.hasToolUse) return finishTurn(assistant)
toolResult = runToolUse(assistant.toolUse, toolUseContext)
state.messages = writeBack(messages, assistant, toolResult)
}
这和很多团队熟悉的"拿历史消息调一次模型,拿到结果就结束"完全不是一个层级。Claude Code 真正高明的点不是 while loop 本身,而是它把 prefetch、budget、compact、tool result write-back 这些原来容易散落在各处的逻辑,全部拉回了主循环正中央。
四个关键认知升级
Claude Code 在这一层最强的地方,是它把"一次请求"理解成一段运行,而不是一问一答。于是很多本该是运行时问题的东西,都被提升成了正式的 runtime 机制:
| 问题域 | 传统做法 | Claude Code 的做法 |
|---|---|---|
| 长上下文治理 | 靠提示词硬扛 | snip · microcompact · collapse · autocompact |
| 失败恢复 | 报错即停 | reactive compact · max output recovery · fallback model |
| 工具结果 | 视为终点 | 视为下一轮输入 |
| Memory / Skill 发现 | 同步阻塞 | 异步预取,藏在流式和工具执行的空隙里 |
还有一个很有工程味的细节:Claude Code 会尽量把耗时工作藏在空隙里。memory prefetch 和 skill discovery 不是每轮都同步阻塞,而是尽量叠在流式输出和工具执行期间。这种设计看起来只是 latency 优化,实际上传达的是更成熟的运行时观念——Agent 的体验不只由模型速度决定,还取决于你能不能把未来大概率要用到的信息提前安排好。
我们怎么学
最值得学的不是每一个 compact/recovery 细节,而是判断升级:当系统开始"连续运行"时,query loop 就不该只是模型调用封装,而应该被单独当成一层系统设计。
如果还在单轮问答阶段,不必马上复制完整恢复体系;但一旦进入多工具、多轮续跑、长上下文阶段,就要尽快把上下文治理、失败恢复、工具回灌提升为 runtime 机制。
别学错的地方,是把一堆恢复分支硬塞进业务代码;真正该复制的是"把失败路径也当主路径设计"的态度。团队动作上,可以先把"上下文治理"和"失败恢复"从 prompt 层挪到运行时层。
4. Tool Runtime:把野生工具变成系统调用
核心矛盾
很多 Agent 项目在工具层的默认心智是"给模型挂几个函数"。Claude Code 明显不是——它把工具层做成了一套受控执行协议。不是在"接函数",而是在设计"行动系统"。
工具一旦开始碰文件、命令、网络和副作用,问题就不再是"模型会不会调用函数",而是"这次行动是否合法、能否并发、如何上报进度、失败怎样表达、结果怎样回灌给模型"。这些问题一旦散落在每个工具里,系统很快就会失控。
Claude Code 的解法
Tool 在 Claude Code 里不是一个简单函数,而是一个带完整运行时语义的对象——有 schema、有输入校验、有权限关联、有并发安全声明、有中断语义、有结果回填规则。
真正的工具执行主链路,做的不是"找到函数然后调一下",而是四段式受控执行:
这说明 Claude Code 对工具层的理解很成熟:工具不是模型的外挂函数,而是 runtime 的受治理执行单元。
如果把 Tool 抽象的差别落到更微观的骨架上,对比会更直观:
// 很多团队的 Tool 抽象
type Tool = (input: unknown) => Promise<string>
// Claude Code 更接近的
interface Tool {
name: string
inputSchema: Schema
canRunInParallel: boolean
validate(input): ValidationResult
execute(input, context): AsyncIterable<ToolEvent>
toModelResult(output): StructuredResult
}
真正的差别不在 TypeScript 写法,而在系统观。前一种只是"模型能调一个函数",后一种才是"运行时知道这个动作该怎么被约束、观测、并发和回灌"。
两个关键工程判断
这层还有两个容易被低估的点:
第一:并发策略不由模型决定,而由工具语义决定。工具调度层不会简单 Promise.all,而是根据 isConcurrencySafe 区分哪些工具可并发、哪些必须串行——只读工具和有副作用的工具,本来就不应该用同一套并发策略。
第二:流式工具执行必须被认真建模。Claude Code 允许模型还在流式输出时工具就先开始执行,但又通过状态跟踪、结果缓冲、取消管理来保证正确性。它优化的不是"更快一点"这么简单,而是"边生成边行动"时系统如何不乱。
为什么这样好
最大的好处是:工具数量增长时,复杂度不会爆在调用点,而是沉到统一 runtime 里。参数校验、权限、并发、错误归一化、结果回填这些横切关注点,不再被每个工具重新发明一遍。系统因此既更稳定,也更适合团队协作。
流式工具执行则让 Claude Code 把"边生成边行动"做成了工程能力,而非 demo 特效——模型还在说话时,工具已经开始干活,但最终结果仍能按正确顺序、正确语义回到主循环。
我们怎么学
最值得借鉴的不是"工具很多",而是工具有制度。
如果现在只有少量只读工具,可以先保持轻量;但一旦工具开始碰文件、命令、网络、副作用,就应该尽快建设统一 Tool Runtime。别照抄过度抽象本身,真正该学的是把横切复杂度沉到公共层,让新增工具不再重复制造新的风险模型。
一个务实的起点:先把"校验、授权、结果格式"三件事统一起来。
5. Permission System:不是弹个框就完事了
核心矛盾
Claude Code 的权限系统值得研究,不是因为它更谨慎,而是因为它更像一条完整的执行链,而不是一个确认框。很多系统把权限做成了 UX 组件,Claude Code 则把它做成了运行时机制。
Agent 的权限问题从来不只是"要不要弹个确认框",而是四件事同时存在:逻辑上是否允许、自动化能否消化、用户何时必须参与、即使允许了进程边界到底被限制在哪。把这些问题揉成一个 yes/no,系统不是过度打断用户,就是安全形同虚设。
Claude Code 的解法
Claude Code 把权限拆成了四层,形成一条从规则到隔离的完整决策链:
这条链路最重要的地方,是它把两个常被混淆的问题分开了:
- 逻辑上允不允许(规则层 + 判定层)
- 进程层面到底能做到什么(执行隔离层)
很多 Agent 系统只做前者,权限像提示框;也有些系统只做后者,沙箱像硬隔离。Claude Code 的成熟之处在于,这两层是打通的。
如果把权限决策对象压成最小骨架:
type PermissionDecision =
| { behavior: 'allow'; updatedInput?; decisionReason? }
| {
behavior: 'ask'
message: string
suggestions?: PermissionUpdate[]
blockedPath?: string
pendingClassifierCheck?: PendingClassifierCheck
}
| { behavior: 'deny'; message: string; decisionReason: string }
很多团队的权限系统只有 boolean,最多再加一个"是否弹窗";Claude Code 则把 decisionReason、suggestions、blockedPath、pendingClassifierCheck 都提升成正式字段。也就是说,权限不再只是"过不过",而是"为什么过、卡在哪、下一步怎么处理、能不能先自动判一轮"。
两个现实主义细节
第一,Claude Code 会对 auto mode 做危险能力裁剪——不是默认"自动模式就尽量多放行",而是主动剔除过宽的 Bash、PowerShell、agent wildcard 等规则。
第二,沙箱不是独立附属物,而是 permission 的落地点:文件路径、网络域名、设置目录等真正执行边界,都会在这里被压实。前者解决"逻辑上别放太宽",后者解决"即使放行了,进程也别飞出去"。
为什么这样好
好处不只是更安全,而是更可解释。用户知道为什么被允许、为什么被拒绝、为什么需要确认;系统内部也知道这次决策来自规则、模式、classifier 还是显式同意。只有这样,权限才能成为可调试、可审计、可优化的系统,而不是一堆历史特判。
Claude Code 对 auto mode 的处理也很值得学——它没有把自动化理解成"尽量少问用户",而是理解成"在收紧危险能力后尽量自动"。真正能让用户信任自动化的,不是它敢做更多,而是它在边界内做得更稳。
我们怎么学
最值得学的是把权限设计成可解释的执行链,而不是弹窗机制。
不一定每个团队都要立刻上复杂 classifier,但至少应该尽快把"决策、理由、来源"建模出来,并把逻辑授权和执行隔离分开。别把"更安全"理解成"多弹几次框"——真正成熟的权限系统,是让自动化、用户体验和风险控制走同一条链,而不是互相打架。
团队动作上,先别急着优化弹窗,先把权限决策对象化。
6. Task / 多 Agent / 后台执行:多 Agent 的核心不是 prompt 分工
核心矛盾
Claude Code 的多 Agent 设计很克制。它不是先搞 manager-agent、worker-agent 那套叙事,而是先定义了统一的任务抽象。这个顺序看起来朴素,其实比大多数"智能体分工图"都更有工程含量。
多 Agent 真正难的地方,从来不是 prompt 怎么分工,而是系统里一旦出现多个可持续执行的执行体,状态怎么管理、进度怎么观察、结果怎么回流、上下文怎么隔离、失败怎么恢复。没有统一执行抽象,多 Agent 只会是一堆黑盒同时跑。
Claude Code 的解法
Claude Code 用 Task 这一统一抽象,表达了很多看起来截然不同的执行体:
这说明它对多 Agent 的理解不是"模型调模型",而是"系统里出现了多个可持续执行的执行体",所以先要有统一任务语义。
本地子 Agent 的实现很能说明问题。Claude Code 不是偷偷新开一轮 query 就算一个子 Agent,而是先把它注册成正式任务,再给它状态、进度、待处理消息、会话记录、前后台语义。换句话说,子 Agent 先是任务对象,才是智能体。
如果把本地子 Agent 的任务状态压成最小骨架,会看到它根本不是一个 Promise<string>:
type LocalAgentTaskState = {
agentId: string
prompt: string
progress?: AgentProgress
error?: string
result?: AgentToolResult
messages?: Message[]
isBackgrounded: boolean
pendingMessages: string[]
retain: boolean
diskLoaded: boolean
evictAfter?: number
}
这几个字段特别能说明 Claude Code 的取舍:
pendingMessages:子 Agent 不是一次性调用,而是带邮箱的执行体isBackgrounded:前后台切换是正式语义,不是 hackretain/diskLoaded/evictAfter:系统已经在认真处理"UI 是否还握着它、磁盘记录是否已回灌、什么时候该回收"这些长期运行才会出现的问题
为什么这样好
最大的好处是:多 Agent 不会把系统撕裂。不同执行体共享同一套生命周期、通知模型和回流协议,前台和后台的差别被降成了调度与可见性差异,而不是两套世界观。
Claude Code 在这里真正成熟的地方,是它把最容易被忽略的工程问题先做了:上下文隔离、结果回流、失败恢复、可观察性。这些问题做不好,manager/worker 架构再漂亮也只是 demo。
我们怎么学
如果系统开始出现后台执行、子任务协作、远程执行,就先把统一任务抽象做对,再谈 fancy 的多 Agent 结构。
最容易踩的坑是把多 Agent 理解成 prompt 分工问题。很多系统最后不是死在智能不够,而是死在没有状态、没有恢复、没有结果回流。Claude Code 这一层最值得吸收的,不是"支持更多 agent",而是先把任何可持续执行的事情都纳入统一执行体。
团队动作上:先把后台任务、子任务和远程执行统一到一张任务状态表上。
7. MCP / Skills / Plugins 扩展层:外部可以热闹,内部必须收敛
核心矛盾
Claude Code 的扩展层真正厉害的地方,不是支持了很多扩展来源,而是它努力把所有外部能力都收敛进少数内部对象。平台做到后面,拼的往往不是接入得快不快,而是收敛得稳不稳。
Agent 一旦走向平台化,扩展来源一定会变多:外部协议、用户自定义能力、插件市场、内建能力包。真正危险的不是来源多,而是每多一种来源,主系统就多一套能力模型、权限模型和 UI 暴露方式,最后 special case 爆炸。
Claude Code 的解法
先看 MCP。Claude Code 不是把 MCP 原生对象直接塞进系统,而是尽量翻译成已有的运行时模型:MCP prompt → Command,MCP tool → Tool,MCP resource → 资源/资源工具体系,必要时还会注入 auth tool。也就是说,MCP 接入的重点不是"连上服务器",而是"把外部能力吸收到本地运行时模型里"。
Skills 也不是简单的 prompt snippet。它的声明信息可以覆盖描述、适用场景、允许使用的工具、模型偏好、推理力度、hooks、执行上下文、代理身份等维度——已经接近一种轻量能力声明,而不只是提示词片段。
如果把 skills 实际解析的结构压成最小骨架:
type SkillDescriptor = {
description: string
allowedTools: string[]
whenToUse?: string
model?: Model
effort?: Effort
hooks?: Hooks
executionContext?: 'fork'
agent?: string
}
这段骨架直接说明了一件事:Claude Code 里的 skill 不是"顺手塞一段提示词",而是能约束工具权限、触发条件、执行上下文、模型偏好、推理力度,甚至决定是否 fork 执行。
外部动态,内部稳定
Claude Code 在扩展层上坚持的核心原则是"动态能力面,稳定内部对象":
外部连接可以随时重连、启停、刷新能力列表;插件可以来自市场、会话级目录、内建包;能力单元也可以来自用户、项目、插件和外部来源。外部世界动态而杂乱,但内部始终收敛到少数对象上。这种收敛,才是平台继续长大时不崩的根本。
为什么这样好
好处是平台可以长大而不碎。UI、permission、query loop、task system 都只需要理解少数内部对象,不需要为每种扩展来源重写一套适配逻辑。越到后期,这种内部收敛越像护城河——它决定了系统还能不能继续演进。
另一个重要收益是动态能力面终于可控了。MCP 连接可以变化、plugin 可以启停、skills 可以来自很多地方,但这些变化对主系统来说仍然是可解释、可管理的,因为底层对象没有失控。
我们怎么学
对想做 Agent 平台化的团队来说,这一层最值得学的不是"也去上更多扩展体系",而是先吸收一条更底层的原则:外部世界可以复杂,内部世界必须收敛。
最容易学偏的地方是先去堆更多扩展类型,而没有守住内部抽象数量。真正应该先做的是约束内部对象,再决定支持哪些外部来源。只有这样,扩展性才不是系统失控的开始,而是系统增长的方式。
团队动作上:先画出"系统内部只允许存在的那几种能力对象"。
8. 总结与总架构:把复杂度放在对的位置上
核心问题
为什么很多 Agent 项目功能点不少,但一进入真实复杂场景就开始散架?因为复杂度没有被放到正确的位置——边界问题混进主循环,权限问题混进工具调用,多 Agent 问题混进 prompt,扩展问题直接渗透到系统内部。
Claude Code 真正强的不是某个单点功能,而是它对复杂度的安放位置非常清楚:
| 层级 | 承接的复杂度 | 核心问题 |
|---|---|---|
| 启动层 | 会话边界问题 | 这次运行是什么模式、什么边界? |
| REPL | 人机协作问题 | 用户如何理解和干预系统? |
| Query Loop | 连续运行问题 | 长上下文、失败、工具回灌怎么办? |
| Tool Runtime | 行动协议问题 | 动作如何被约束、并发、回灌? |
| Permission | 风险治理问题 | 什么能做、谁来决定、边界在哪? |
| Task Runtime | 长时执行和并发问题 | 多个执行体如何共存不乱? |
| 扩展层 | 平台增长问题 | 外部能力如何不撕裂内部? |
三条主干链路
如果把这套设计再压缩一层,会发现 Claude Code 一直在做同一件事:把不稳定、概率化、容易失误的模型能力,装进一套稳定、可恢复、可解释、可扩展的工程运行时。
它不是靠某个神奇 prompt 变强的,而是靠一层层 runtime 把真实复杂度接住了。
Claude Code 的总架构可以收敛成三条主干链路,扩展层则横向为三条主链持续注入能力:
- 控制链(启动层 → REPL → Query Loop):回答"这一轮到底在什么制度下运行"
- 执行链(Tool Runtime → Permission → Sandbox):回答"模型一旦决定行动,系统如何把动作稳稳落到真实世界里"
- 任务链(Task Runtime → 后台执行/多 Agent → 回流):回答"如果这件事不是一口气做完,而要持续运行、分身执行,系统如何不乱"
为什么这套架构成立
这套架构成立,不是因为层数多,而是因为每一层都有明确职责,且职责之间的边界相对稳定。Claude Code 不是让所有层都去碰模型,而是让模型只处在该处的位置上;也不是让所有问题都在 query loop 里解决,而是让 query loop 只负责连续运行,把别的复杂度交给别的层。
这就是为什么它虽然复杂,但不显得散——复杂度没有被平均撒到全系统,而是被有意识地集中管理。
Claude Code 更值得借鉴的点在于:它没有追求"最少模块",而是追求"每种复杂度只在一个地方爆炸"——上下文和续跑问题只在 Query Loop 爆炸,副作用和权限问题只在执行链爆炸,并发和后台问题只在任务链爆炸,平台增长问题只在扩展层爆炸。
架构真正成熟的标志,从来不是没有复杂度,而是复杂度被放到了对的位置。
最后该带走什么
如果一定要把整篇文章压缩成几句最值得带走的话,我会留下这 5 条:
- 先定义执行边界,再发起第一轮推理
- 当 Agent 进入连续运行阶段,query loop 就必须升级成 runtime
- 工具一旦开始碰副作用,工具层就必须制度化
- 权限系统的核心不是确认框,而是可解释的执行链
- 多 Agent 的前提不是 prompt 分工,而是统一任务抽象
Claude Code 真正值得借鉴的,不是它"做了很多层",而是它知道每一层在承接哪一种真实复杂度。对做 AI Agent 的团队来说,这比抄任何单点功能都更有价值。
说到底,Claude Code 最值得学的,不是某一段实现有多巧,而是它始终在认真回答同一个问题——
当模型开始真的做事,系统准备在哪里把这些复杂度接住。

浙公网安备 33010602011771号