别把提示词塞进总 Prompt:让每个工具自己带着“使用说明”
做 Agent 时,很多人会写一大段总提示词:
你可以查询天气、搜索知识库、创建工单、发邮件……请根据情况合理调用工具。
看着没毛病,跑起来就开始闹心。
模型会把“查天气”和“查订单”搞混;该填城市时填了用户昵称;工具报错后,它还会一本正经地编答案。更惨的是,工具一多,总 Prompt 会膨胀成一锅粥,没人敢改。
有个更靠谱的设计思路:每个能力自己携带自己的 Prompt。
也就是把一个工具拆成三件套:
- Tool:它到底能干什么。
- Schema:调用时要传哪些参数,格式是什么。
- Prompt Guidance:什么场景该用它、怎么填参数、失败后怎么处理。
谁负责开发这个能力,谁就负责把这三件事讲明白。别把说明书丢给 Agent 框架的维护者,更别指望模型“自己悟”。
为什么总 Prompt 容易失控?
想象一下,你做了一个客服 Agent。
它有 20 个工具:查物流、退货、退款、查库存、改地址、创建工单、发优惠券……你把每个工具的规则全写进系统提示词里。
几周后,产品说:“退款工具新增一个 reason_code 参数。”
你得去改总 Prompt。
工程师说:“物流接口的状态码换了。”
你又得去改总 Prompt。
运营说:“赠券前要先判断用户是否符合活动资格。”
继续改。
很快,这份 Prompt 会出现三个问题:
-
规则离工具太远
工具接口变了,提示词常常没同步。线上报错才发现,真是经典节目。 -
上下文越来越脏
每次对话都塞入所有工具的细节。模型注意力被稀释,简单任务也可能选错工具。 -
职责没人认领
Agent 团队说接口文档不归自己管;业务团队说 Prompt 不是自己写的;问题出了,大家一起看日志发呆。
工具的使用规则,应该贴着工具放。就像电钻的安全说明印在电钻包装上,不该藏在仓库管理员的笔记本里。
一个工具该带哪些信息?
一个能稳定工作的工具定义,不该只有名字和参数。建议至少包含下面四层。
1. 能力描述:一句话说人话
别写:
用于执行订单相关操作
这句话等于没写。
改成:
查询指定订单的配送进度、承运商和最新物流节点。
不能用于修改收货地址、取消订单或发起退款。
模型需要知道“能做什么”,也需要知道“不能做什么”。边界写得越清楚,模型越不爱乱伸手。
2. 参数 Schema:把输入卡死
Schema 不只是给程序校验用,也是模型的操作表单。
{
"name": "get_order_logistics",
"description": "查询订单的配送进度和最新物流节点。仅在用户提供有效订单号,或系统上下文中已存在订单号时调用。",
"input_schema": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "订单号,格式示例:ORD202503080001"
}
},
"required": ["order_id"],
"additionalProperties": false
}
}
这里有几个实用细节:
- 参数名尽量直白。
order_id比id好懂得多。 description里给格式示例。模型对示例很敏感。- 该必填的就设为
required,别指望模型“看情况补”。 - 开启
additionalProperties: false,拦住模型自创参数。
3. Prompt Guidance:告诉模型什么时候动手
这一层才是灵魂。
Schema 解决“怎么填”,Guidance 解决“该不该填”。
调用条件:
- 用户明确询问订单到了哪里、何时送达、物流是否更新。
- 必须拿到订单号;如果上下文没有订单号,先向用户索要。
调用限制:
- 用户说“我要退货”时,不要调用此工具。
- 不要根据姓名、手机号片段猜测订单号。
结果处理:
- 若状态为“运输中”,回复承运商、最新节点和预计送达时间。
- 若状态为“无记录”,请用户核对订单号,不要编造物流信息。
- 若接口超时,可以建议用户稍后重试或转人工。
这几段话能省掉大量“模型为什么这样干”的排查时间。
4. 输出约定:拿到结果后怎么说
工具返回的数据通常很丑:字段名、状态码、时间戳,一坨 JSON。模型若没有输出规则,很可能把内部字段原样甩给用户。
给它一份明确约定:
面向用户输出时:
- 用自然语言转述物流状态。
- 时间统一转为北京时间,格式使用“3月8日 16:20”。
- 不展示 carrier_code、trace_id、internal_status 等内部字段。
- 预计送达时间为空时,直接说“暂未给出预计送达时间”。
别小看这一步。很多 Agent 看上去“笨”,根源只是没有人告诉它结果该怎么翻译成人话。
完整示例:给“创建工单”做一张工具说明书
下面这份定义,可以直接作为你们的设计参考。
name: create_support_ticket
purpose: 创建人工客服工单,用于处理模型无法直接解决的问题。
input_schema:
type: object
properties:
category:
type: string
enum:
- payment_issue
- logistics_issue
- refund_issue
- account_issue
description: 工单分类,只能从枚举值中选择。
summary:
type: string
description: 20 到 80 字的问题摘要,使用用户已确认的事实。
user_contact:
type: string
description: 用户确认可接收回访的手机号或邮箱。
required:
- category
- summary
additionalProperties: false
prompt_guidance: |
适用场景:
- 工具调用连续失败两次。
- 用户明确要求转人工。
- 遇到退款争议、账户安全、支付异常等高风险问题。
调用前检查:
- 先尝试使用已有的查询或处理工具。
- summary 中不得写入密码、完整银行卡号、身份证号。
- 用户未提供联系方式时,仍可创建工单,但不要虚构联系方式。
调用后回复:
- 告知用户工单已创建,并给出工单号。
- 不承诺具体解决时间,使用“客服会尽快跟进”。
result_handling: |
若返回 ticket_id,回复“已为你创建工单,编号是 {ticket_id}”。
若创建失败,说明当前无法提交,并建议用户稍后重试。
你会发现,工具开发者最了解失败码、参数限制和业务边界。让他们维护这份说明,远比让一个写总 Prompt 的人到处打听靠谱。
工具越多,越要做“按需挂载”
如果 Agent 有 50 个工具,别每轮对话都把 50 个工具连同说明一股脑丢给模型。
用户问“北京明天会下雨吗”,模型根本不需要看到“创建退款工单”的完整规则。
可以做一层工具路由:
用户问题
↓
识别任务类型
↓
只加载相关工具与 Guidance
↓
模型决策并调用
↓
根据结果回复或进入下一步
常见的拆分方式:
- 天气、时间、汇率:公共信息工具组
- 订单、支付、售后:电商服务工具组
- 文档搜索、知识问答:企业知识库工具组
- 发邮件、建日程、创建任务:办公自动化工具组
这么做有两个直接收益:
- 上下文更短,调用成本更低。
- 无关工具不露面,误调用会少很多。
别迷信“大而全”的工具清单。模型不是工具箱管理员,你给它一百把扳手,它真可能拿扳手去拧灯泡。
怎么做成会进化的系统?
“自进化”不是让模型偷偷改生产环境的 Prompt。那样很刺激,也很容易把线上服务送走。
靠谱的进化路径,是让每一次调用都留下可分析的记录,再由人或评测流程更新工具说明。
建议记录这些字段:
{
"user_intent": "用户想查询订单物流",
"candidate_tools": ["get_order_logistics", "get_order_detail"],
"selected_tool": "get_order_detail",
"tool_arguments": {"order_id": "ORD202503080001"},
"tool_result": "success",
"final_outcome": "wrong_tool_selected",
"review_note": "物流意图被错误路由到订单详情工具"
}
每周翻一遍失败案例,重点盯住三类问题:
- 工具选错了:补充调用条件和反例。
- 参数填错了:收紧 Schema,增加格式示例。
- 结果说错了:完善输出约定和异常分支。
举个真实感很强的例子:
用户说:“快递卡三天没动了。”
模型调用了 get_order_logistics,没问题。可它拿到“异常滞留”的状态后,只回复:“包裹正在运输中,请耐心等待。”
这时别急着怪模型。检查工具 Guidance,你多半没写异常状态的处理策略。
补上一条:
若物流状态为“异常滞留”且超过 48 小时,建议用户创建物流问题工单;不要使用“耐心等待”作为唯一回复。
下一轮评测,这类问题就会少掉一大片。
落地时最容易踩的坑 ⚠️
把 Guidance 写成产品宣传
“本工具功能强大,可高效处理各种订单需求。”
这种句子对模型没帮助,对人也没帮助。删掉。
写清触发条件、参数来源、禁用场景和错误处理,才叫说明。
参数描述太模糊
id、type、data 这种字段名,模型看了也头大。
把参数写成业务语言:order_id、refund_reason、delivery_address。描述里放格式和取值范围。
不写失败分支
接口一定会超时、没数据、权限不足、参数失效。模型遇到这些情况,没有剧本就容易瞎编。
每个关键工具至少写明:
- 无数据怎么办
- 参数不合法怎么办
- 接口失败怎么办
- 是否允许重试
- 何时转人工
让模型修改自己的正式规则
模型可以提出“建议修改点”,但别让它直接改生产 Prompt。
正确流程是:
调用日志 → 聚类失败案例 → 生成优化建议 → 自动评测 → 人工审核 → 灰度发布
规则更新也该像代码发版一样,有版本号,有回滚,有评测集。别靠一句“感觉这版更聪明了”。
一份可直接复用的工具设计清单
准备上线一个新工具前,拿这张清单过一遍:
- [ ] 工具名称能看出业务动作吗?
- [ ] 能力描述里写了明确边界吗?
- [ ] 每个参数都有类型、含义、格式示例吗?
- [ ] 必填参数是否被 Schema 强制校验?
- [ ] 写清了哪些用户意图可以调用吗?
- [ ] 写清了哪些场景禁止调用吗?
- [ ] 参数缺失时,模型知道该问什么吗?
- [ ] 接口无数据、报错、超时的处理方式齐了吗?
- [ ] 工具结果里的内部字段会被过滤吗?
- [ ] 是否有调用日志和失败案例回收机制?
把工具当成一个独立产品来设计,而不是一段顺手接上的 API。
当每个能力都带着自己的 Schema 和使用指南,Agent 的总 Prompt 会轻很多,工具维护也有了明确责任人。模型少靠猜,系统才会越跑越稳。