Skip to content
预计 1 分钟右侧目录可快速定位

什么才是好 Tool:Contract、Granularity 与 Naming ​

前置:Model / Runtime Boundary;Structured Interaction / Schema Validation
核心问题:一个能力应该怎样切成 Tool,才能既让模型容易选对,又让 Runtime 能验证输入、副作用和权限?

send email 的 schema 可限制 recipient/body,但 Runtime 还需做 recipient policy、approval 和 idempotency。manage everything(action, payload) 太粗;为每个数据库字段做一个 tool 又太细。search issues / get issue / update issue 通常更自然。

Mental Model ​

text
Model ToolCall → Registry lookup → schema/domain validation → permission → executor → result policy → Observation

Tool definition 决定模型看到的 capability,ToolExecutor 决定系统实际发生的 I/O。两者中间必须存在 validation/policy,而不是模型一调用就直接执行。

Tool 是确定性系统与非确定性模型之间的 Contract ​

Tool 粒度决定模型要做多少 orchestration:粗工具减少调用但不透明,细工具可组合但增加 selection/plan 负担。优先让每个 Tool 有清晰、可验证的职责。

Tool contract 定义模型能请求什么、程序如何验证和执行、失败怎样表达。模型只产生调用意图,权限和副作用仍由确定性 Runtime 控制。

🔍 源码对照:协议 Tool 只是内部能力的投影 ​

完整源码与通用分析见 06-03 Tool Metadata / Dynamic Discovery。这里不重复代码;这里关注 contract boundary:协议发现结果只能投影成内部 ToolSpec,MCP / Provider 的协议类型不应泄漏进 Runtime Tool Contract。

源码说明

routed-mcp-bridge.ts 把内部 Tool 视为包含 name / providerIdentifier / toolName / description / inputSchema 的能力记录,再投影给外部协议。它提醒我们 Tool Contract 至少要同时服务两端:模型需要清晰的语义和 schema,Runtime 需要稳定 identity 与 provider binding。只设计一个“可调用 Python 函数”不足以覆盖这两个角色。

工程边界

该 bridge 的字段名和 provider 组织方式是产品实现;Shadow Harness 不需要复制 providerIdentifier,但必须有能够唯一解析执行目标的内部 identity。

Shadow Harness 对照

  • 区分 model-visible ToolSpec 与 runtime-only ToolBinding。
  • Tool rename/version upgrade 不应让历史 execution record 失去解析能力。

验证

注册两个显示名相同但 provider/version 不同的 Tool,验证模型侧名称策略与 Runtime 侧唯一 identity 不冲突。

Tool Granularity ​

Tool 粒度决定“多少 orchestration 交给模型,多少封装在确定性代码里”。

例如:

text
粗粒度:deploy_service(service, version)
细粒度:build_image → push_image → update_manifest → rollout → verify

粗粒度调用少、业务语义清楚,也更容易把事务/权限封装在 Tool 内;但内部过程对 Agent 不透明。细粒度更灵活、可组合,却增加 planning、tool selection 和中间失败面。

因此不要机械地“一个 HTTP API = 一个 Tool”。更合适的边界通常是:一个 Tool 完成一个可描述、可授权、可验证的用户意图。

Tool Naming / Description ​

Tool 名称和描述不是文档装饰,而是模型选择 capability 时看到的接口。

例如同时存在:

text
search_files(query)
search_symbols(query)

如果描述都只写“搜索代码”,模型很难知道什么时候该按文本找文件、什么时候该按 symbol 找定义。好的 description 应说明 能做什么、什么时候用、关键限制是什么;只有参数含义仍容易误解时再加正反例。

所以 Tool 可用性不仅取决于 executor 是否正确,也取决于模型能否在相近能力中稳定选对。

最小实现 / 数据结构 ​

python
class ToolExecutor:
    async def execute(self, call, ctx):
        tool = self.registry.require(call.name)
        args = tool.validate(call.arguments)
        self.policy.authorize(ctx, tool, args)
        return await self.runner.run(tool, args, deadline=ctx.deadline)

在 Shadow Harness 中怎么落地 ​

ToolDefinition/Registry/Executor/ResultPolicy 分层;Local、MCP、Shell、Agent-as-Tool 统一到内部 Tool contract。

关联源码 ​

自测 ​

  1. 一个 do_everything(task) Tool 把搜索、修改、部署都包在一起。为什么它对模型选择、权限和副作用审计都不友好?
  2. 设计 read_file 与 apply_patch 时,哪些 contract 信息必须让 Runtime 知道,不能只靠自然语言 Tool 描述?

Sources ​

AI Engineering · Agent · Harness · Backend Systems