跳到正文
Elaine Blog
返回

怎样设计一个好用的工具:名称、参数、结果与业务契约

更新于:
Tool Calling 与 MCP

一个叫 handle_order(data) 的工具,既能查订单又能退款。模型面对“看看订单能不能退”时,无法从名称判断应传什么,应用也很难识别这次只是咨询还是要执行写操作。

设计工具首先是设计一份交接契约。它既要让模型理解何时使用,也要让执行器能够拒绝不合法的输入,并让调用者理解输出。

名称和描述怎样帮助选择

可以拆成 get_orderget_refund_policycreate_refund_draftsubmit_refund。名称对应业务动作,描述解释输入前提、返回内容和副作用。

“操作订单”没有说明能力范围;“读取当前获准订单的签收日期与售后状态,不修改订单”更容易让模型理解。描述也应讲清不能回答什么,例如订单工具没有质量鉴定能力,不能证明用户报告的问题已经核实。

工具并非越细越好。如果查询一个订单必须连续调用五个几乎总是一起使用的字段工具,会增加往返和失败点。可以将一致性要求相同的只读字段放在一个结果里,将咨询与提交等不同权限边界分开。

SQL、Shell 等通用工具也有适用场景,例如受控的数据分析或开发环境。它们把更多选择权交给模型,需要更强的权限、资源限制与隔离;一个售后机器人不必为查询一张订单开放任意 SQL。

输入 Schema 能保证到哪一步

下面是一个输入契约。字段名称属于教学工具,Schema 使用 JSON Schema 表达。

{
  "type": "object",
  "properties": {
    "order_id": {"type": "string", "pattern": "^A[0-9]{4}$"}
  },
  "required": ["order_id"],
  "additionalProperties": false
}

这能表达订单号的结构和额外字段限制,不能验证数据库归属。A9999 符合格式,却可能不存在。模型传入 tenant_id=shop-b 时,最合适的做法通常不是使用这个值查询,而是拒绝未声明字段,并从可信身份确定租户。

类型也需要严格理解。Python 中 bool 是 int 的子类,金额校验如果仅用 isinstance(value, int),可能接受 True。业务要求整数金额时应明确拒绝布尔值。自动类型转换也可能把字符串变成数字,是否允许要由契约决定。

复杂工具还需控制字符串长度、列表长度和嵌套深度。合法 JSON 可以非常大,语法解析成功不代表资源成本可接受。

缺失、空值与默认值不是同一件事

假设退款草稿有 reason。缺失字段可能表示调用者未提供,空字符串可能表示提供了但没有内容,null 可能表示明确未知。若业务要求可追溯原因,不能随意把三者统一成“其他”。

默认值应只用于不会改变用户意图的情况。默认分页大小可以合理,默认退款金额为订单全额则可能扩大操作范围。缺少高影响参数时,应要求补充或通过受控业务规则计算,再让用户确认。

不同模型的结构化工具接口支持的 Schema 子集可能不同。MCP 输入 Schema 与模型参数格式也不应不经检查直接复制;适配层要保留语义,遇到不支持的约束仍在服务端执行。

金额和时间需要写明单位

amount: 299 到底是 299 元还是 2.99 元?草稿可以使用 amount_minor: 10000currency: CNY,本文约定人民币最小单位为分,即 100 元。币种的最小单位规则需要业务或支付接口提供,不能假设所有币种都除以一百。

取件时间应包含明确时区,或使用服务端生成的可用时段 ID。模型把“后天上午”直接传给执行工具,可能在恢复时得到不同日期。可以先由解释阶段产生候选,再由业务系统返回可选择时段。

金额上限、累计已退金额、商品是否可退属于业务校验,不是仅靠 Schema 的 minimum 和 maximum 就能完整表达。

输出应足够判断下一步

只返回“成功”会迫使模型猜测成功做了什么。订单查询可以返回订单 ID、签收天数、质量核实状态、来源版本;创建草稿则返回 draft_id、待确认参数和 draft_revision。

{
  "ok": true,
  "data": {
    "order_id": "A1042",
    "days_since_delivery": 10,
    "quality_verified": false,
    "source_revision": 12
  }
}

quality_verified=false 表示尚未确认,而不是确认不存在质量问题。字段语义必须在描述里说明。模型要据此回答“核实符合后由商家承担”,不能把它压成“已符合”。

错误结果应区分参数不合法、资源不可用、业务条件不满足和暂时故障。对外可将不存在和无权限合并成 order_unavailable,内部受控日志保留原因,减少接口泄露订单存在性。

运行时注入哪些值

认证主体、服务凭据、授权策略、追踪 ID 与业务数据库连接来自运行时,不出现在模型可填写的业务参数中。模型可以选择要查询的订单,但不能通过传入管理员角色扩大权限。

配套 tool_contracts.py下载 用普通 Python 实现明确的参数检查、身份范围和稳定返回。它采用服务端构造的 Principal,教学环境用固定主体,正式服务必须替换为认证中间件。

工具声明中的只读或幂等标记用于向调用者描述行为,不能防止一个错误实现执行写操作。工具实现、后端权限和观测记录仍然要与契约一致。MCP 对工具与 Schema 的具体要求见 Tools 规范

契约升级会影响已有任务

amount 从元改为分却保持同名,旧调用会产生严重歧义。破坏兼容的修改应有明确版本或新的工具名,未完成草稿与审批绑定原契约版本,迁移时重新确认。

新增可选输出字段通常比修改已有字段含义更容易兼容,但调用方可能限制额外字段,仍需检查。工具描述大幅改变也会影响模型选择,不能只把函数签名不变当成行为不变。

清楚的契约使后面的执行循环能知道“收到什么、允许什么、返回什么”。它没有替代循环,却让循环可以用程序规则工作,而不是到处猜测模型意图。

继续阅读

上一篇:Function Calling、Tool Calling 与 MCP:模型怎样使用外部能力

下一篇:一次工具调用怎样完成:执行循环、结果回填与多工具协作

下载文件、依赖与运行边界见配套指南下载


分享这篇文章:

上一篇
Function Calling、Tool Calling 与 MCP:模型怎样使用外部能力
下一篇
一次工具调用怎样完成:执行循环、结果回填与多工具协作