乐于分享
好东西不私藏

Claude Code 源码十大亮点解读 02|语义化工具并发:为什么它既快又不乱

Claude Code 源码十大亮点解读 02|语义化工具并发:为什么它既快又不乱

Digital Strategy Review | 2026

Claude Code 十大亮点解读 02|语义化工具并发:为什么它既快又不乱

文 / 果叔 · 阅读时间 / 8 Min

写在前面

这一篇值得单独拆出来,是因为很多 Agent 一到真实代码库就会同时暴露两个问题:慢,或者乱。Claude Code 的处理很成熟,它不是盲目追求并发数量,而是把并发放进运行时语义里做。

01

语义化工具并发:为什么它既快又不乱

多工具 Agent 系统一旦进入真实使用,就会遇到一个非常现实的问题:

• 全串行执行,慢

• 全并发执行,乱

Claude Code 在这个问题上的答案很漂亮:不是拍脑袋决定并发,而是让工具自己声明并发语义,再由运行时按语义切批执行。

对应实现主要在:

• src/services/tools/toolOrchestration.ts

• src/tools.ts

• src/query.ts

02

一、问题到底出在哪里

在 coding 场景里,一轮推理常常会产生很多工具调用,比如:

• 搜文件

• 搜文本

• 读多个文件

• 查 MCP 资源

• 编辑文件

• 跑 shell

这些调用的性质非常不一样。

适合并发的

• Glob

• Grep

• FileRead

• 某些只读型 MCP 工具

不适合并发的

• 文件编辑

• 写文件

• 依赖最新上下文状态的工具

• 带副作用的 shell / powershell 调用

如果系统没有中间层来理解这些差别,就只能在两个坏选择之间二选一:

01 全部串行,保证安全但体验差

02 全部并发,追求速度但容易踩状态

Claude Code 选择了第三条路。

并发不是默认态,而是工具自己声明语义之后,运行时再做批次切分。

03

二、Claude Code 的做法:先让工具表达自己的并发语义

toolOrchestration.ts 的核心不是“开并发”,而是 partitionToolCalls(...)

它会做这些事:

01 遍历一轮 assistant message 里的 tool_use

02 找到对应工具定义

03 用工具 schema 解析输入

04 调用该工具的 isConcurrencySafe(...)

05 按顺序把工具调用划成若干批次

结果是:

• 连续且安全的工具调用会被归成一组,并发执行

• 其他调用会退回串行

这比简单的“读工具都并发、写工具都串行”更稳,因为判断权其实交给了工具实现本身。

04

三、为什么这套设计很高级

1. 它把复杂性从模型侧移到了运行时侧

大模型本身不擅长做精确并发控制。 你当然可以在 prompt 里告诉它“读操作可以并行”,但那只是建议,不是保障。

Claude Code 干脆不依赖模型记住这件事,而是让运行时在执行阶段自动完成安全编排。

这是成熟系统常见的思路:

• 模型负责表达意图

• 运行时负责保证执行策略

2. 它保留了顺序语义

注意这里不是把所有可并发工具打散成任意拓扑,而是按调用序列中的连续安全片段分批。

这非常重要,因为它保留了 assistant 原始推理的局部顺序。

也就是说,Claude Code 追求的是“尽可能安全地快”,而不是“极限并行地重排”。

3. 它天然适合代码探索场景

在代码探索阶段,一轮里最常见的就是大量只读调用。 这正是并发收益最大的地方。

因此这个设计对 Claude Code 这种 coding agent 特别合适:

• 搜索快得多

• 不容易破坏状态

• 模型不需要额外学习复杂执行规则

05

四、这个亮点和 query.ts 的关系

query.ts 负责从 assistant 输出里提取 tool_use,再调用 runTools(...)。 真正决定并发与串行策略的是 toolOrchestration.ts

这意味着 Claude Code 的主循环并不是简单“看见一个工具就执行一个工具”,而是:

01 先收集本轮工具调用

02 再在运行时层进行批处理规划

03 再把执行结果回灌回主循环

这使得工具系统从“即时反应式调用”升级成了“受调度的执行阶段”。

06

五、为什么这比简单线程池更有价值

有些系统也会说自己支持并发工具调用,但本质上只是:

• 异步发出去

• Promise.all

这种实现的问题在于,它对工具本身的语义视而不见。

Claude Code 的不同点是:

• 并发不是默认的,而是经过工具定义确认的

• 上下文修改不是乱序套用,而是有 contextModifier 收敛顺序

• 工具执行本身仍然在统一的权限、hook、telemetry 体系里

所以它不是一个“快一点的工具执行器”,而是一个有语义的调度器

07

六、这对用户体验有什么直接影响

1. 探索速度更快

当 Agent 需要搜很多位置、读很多文件时,响应明显更顺滑。

2. 不容易出现状态竞争

编辑类操作仍然保守串行,避免文件状态互踩。

3. Agent 更像“会做事的系统”

用户看到的是 Agent 能迅速展开一批只读探索,而不是机械地一个一个查。

这会让系统整体感觉更像熟练工程师,而不是单线程脚本。

08

七、这一设计的代价是什么

当然,这种设计也不是免费的。

1. 工具实现必须承担语义声明责任

每个工具都得正确实现自己的并发安全判断,否则调度器就无法做出正确决定。

2. 调试复杂度上升

一旦某些上下文修改来自并发工具,系统就必须更仔细处理 contextModifier 的套用顺序。

3. 需要谨慎处理“看起来只读、实际上有副作用”的工具

这类工具如果误标成 concurrency-safe,风险会很大。

但总体上,这个代价是值得的,因为收益直接作用在真实使用最频繁的探索阶段。

09

八、一张图看懂这件事

10

九、结论

Claude Code 这套“语义化工具并发”并不是 flashy feature,但它解决的是多工具 Agent 最现实、最频繁的性能与稳定性矛盾。

它的厉害之处在于:

• 不是把并发责任推给模型

• 不是靠硬编码列表粗暴分类

• 不是牺牲顺序语义换速度

而是把工具语义真正带进了运行时调度层。

简单说:

它让 Agent 的工具使用既像程序调度,又不失去大模型推理的自然性。