模块定位
packages/core/tools 是工具注册和执行中心。它解决的不只是“模型调用函数”,而是工具 schema、权限、审批、超时、并发、输出校验、上下文附加、UI 展示、Code Mode SDK 这些问题。
源码入口:
packages/core/tools/src/index.tspackages/core/tools/src/schema.tspackages/core/tools/src/code-mode.tspackages/core/tools/src/presentation.tsdocs/tool-execution-pipeline.mddocs/tool-catalog.md
ToolDefinition 包含什么
一个工具定义通常包含:
namedescriptionparametersoutput.schemaoutput.renderexecute(args, exec)- 可选
timeoutMs - 可选
isConcurrencySafe(args) - 可选
presentCall() - 可选
presentResult() - 可选
finalizeContent()
重点是 canonical output。工具 body 返回 JSON value,registry 校验它符合 output schema,再通过 render 生成模型可见 content。这样程序消费值和模型读取文本被分开。
执行流水线
一次工具执行顺序:
1 | flowchart LR |
几个边界要分清:
tools/pre-execute可以 allow、ask、deny,但不能改 args。- guard 是单调拒绝。
tools/execute是 around-dispatch wrapper,适合 timeout、metrics、retry。tools/post-execute可以 block、替换 content、替换 value、附加 contexts。finalizeContent由工具定义拥有,保证最后的内容不变量。tools/result是 live observation;tool/result是 durable session event。
参数 schema 与输出 schema
defineTool() 提供 typed schema DSL。它支持 string、number、integer、boolean、null、array、object、oneOf、enum、const 等 JSON schema 子集。
输入错误不会直接 throw 到 loop,而会走正常 error-result path,变成 INVALID_ARGS。输出则由 registry 强制校验,工具不能返回不符合声明的值。
并发模型
工具可以声明 isConcurrencySafe(args)。只有返回精确 true 的调用才是 parallel。其他情况都是 exclusive,包括:
- 未声明 classifier。
- 参数无效。
- classifier throw。
- 返回非 true。
Loop 会让连续 parallel 调用进入 bounded rolling pool,exclusive 调用形成 barrier。这样读文件、搜索等可以并发,而写文件、shell、状态变更默认保守。
Tool-owned UI Presentation
工具可以返回 render intent,而不是让前端按工具名硬编码。
典型 card:
- generic
- terminal
- diff
- search
- read
- web
UI 在 live streaming 和 replay 时都可以调用 presenter,所以 presenter 必须是纯函数:只依赖 args 和 durable result,不依赖当前进程状态。
Code Mode
Code Mode 是这个工具系统最有启发的部分。它不把所有 end tools 都直接暴露给模型,而是暴露一个 run_code transport,再生成当前可见工具集合的 SDK。
模型写代码:
1 | const files = await tools.grep({ pattern: "SessionEventMap", path: "packages" }) |
每个 binding 调用仍然回到完整工具流水线。区别是中间值只在代码执行里流动,不进入对话历史;最终只有 console.log 和 return 的结果回到模型。
这适合:
- 多文件读取后聚合。
- 搜索结果过滤。
- 多工具中间计算。
- 避免把大量中间结果塞爆上下文。
常见坑
第一,timeoutMs 是声明元数据,真正 enforce 需要 timeout policy wrapper。
第二,tools/pre-execute 不能改 arguments,避免日志和实际执行不同步。
第三,content replacement 不是保密边界。如果程序消费者不能拿到值,要替换 canonical value 或 block。
第四,Code Mode 的中间 canonical values 不进 session log,不能用于 replay 重建。
继续读源码
packages/core/tools/README.mddocs/tool-catalog.mddocs/tool-execution-pipeline.mdpackages/code-runtime/README.md