LAYER 06 · 动手扩展并交付
实战:添加一个工具
从参数 schema、执行与输出 schema,到作用域注册、展示和测试
defineTool → ctx.tools.register → prompt schema一个合格工具定义除了 name、description 和 execute,还必须考虑什么?
先建立直觉
工具定义是一份带质检的产品合同:输入规格、产出规格、最长交期、展示方式和出错类别都要与实际生产线一致。
MECHANISM
机制拆解
defineTool 把参数推导、JSON Schema 编译、运行时校验、output 校验和 presentation 绑定在同一份定义上;不支持的 schema 关键字会被拒绝。
注册到 agent.ctx 可提供局部能力,注册到根 ctx 提供部署能力;schemas() 只投影当前可见工具,执行仍走完整流水线。
第 1 步 / 共 5 步
定义参数与输出
参数、output 和错误保持 JSON 可表示。
INVARIANTS
无论怎么扩展,都不能破坏
- 参数与输出都经过运行时校验
- 工具 meta 必须 JSON 可序列化
- 工具业务逻辑不拥有跨工具安全策略
FAILURE MODES
最容易踩中的坑
- ×只写 TypeScript 类型而无运行时 schema
- ×handler 返回 class/Date/循环引用
- ×注册后忘记让插件生命周期拥有 disposer
● ● ●
h25-build-tool.ts TypeScriptexport const apply = (ctx: Context) => {
ctx.tools.register(defineTool({
name: "weather_lookup",
description: "Return a normalized weather snapshot.",
parameters: { city: { type: "string" } },
output: { summary: { type: "string" } },
async execute({ city }, runtime) {
runtime.signal.throwIfAborted()
return { summary: await lookup(city, runtime.signal) }
},
}))
}VERIFY IN SOURCE
不要相信结论,去源码里复核
以下链接固定到官方 deepseek-harness@47f9438;查看当前上游时请留意后续 breaking changes。
KNOWLEDGE CHECK
先停十秒,再揭晓答案
为什么工具 output 也要有 schema?
为什么下一章紧接在这里
工具是 capability consumer;下一章从另一侧设计一个可替换 Provider 和完整 seam。