Agent 总用错工具:工具描述就是提示词避坑复盘

我们做了一个能调用几十个内部工具的 AI 客服 Agent,查订单查物流查商品改地址申请退款,几乎把后台能力都包装成工具挂上去,满心期待它像个全能客服自动调对应工具去办事。可上线一测问题百出:用户问我的订单到哪了它却去调了搜索商品的工具,用户想退款它调了查询物流,有时明明有专门工具能干这事它偏不用反而自己瞎编参数去调不相干的工具。它不是不工作,而是频繁地自信地用错工具。我一开始以为是大模型太笨,又是换模型又是在系统提示词里苦口婆心教它什么情况用什么工具,效果甚微。直到我静下心把那几十个工具的描述一个个拎出来看才猛然醒悟:问题根本不在大模型,而在我们自己——给这几十个工具写的描述要么含糊不清比如一句查询数据,要么彼此边界模糊互相重叠,而这些描述恰恰是大模型用来判断该调哪个工具的唯一依据,我们给了它一堆写得乱七八糟的说明书却怪它选不对工具。这篇文章从这次 Agent 频繁用错工具的事故出发,讲透 Agent 工具设计避坑:工具描述本质是写给大模型的提示词要当一等公民来写、工具不是越多越好要控制数量与分层路由、工具设计要单一职责参数枚举化返回清晰对大模型友好、用评估集量化工具选择准确率,以及一个根本认知——Agent 的能力一半在模型一半在你给它搭建的工具与指令环境,先查工具再怪模型。

我们做了一个能调用几十个内部工具的 AI 客服 Agent——查订单、查物流、查商品、改地址、申请退款……几乎把后台的能力都包装成工具挂了上去,满心期待它能像个全能客服一样,听懂用户需求、自动调对应的工具去办事。可上线一测,问题百出:用户问"我的订单到哪了",它却去调了"搜索商品"的工具;用户想退款,它调了"查询物流";有时候明明有一个专门的工具能干这事,它偏不用,反而自己瞎编参数去调另一个不相干的工具。它不是"不工作",而是频繁地、自信地用错工具,办出一堆驴唇不对马嘴的事。

我一开始以为是大模型"太笨"、理解能力不行,又是换模型、又是在系统提示词里苦口婆心地教它"什么情况该用什么工具"。可效果甚微。直到我静下心来,把我们写的那几十个工具的"描述(description)"一个个拎出来看,我才猛然醒悟:问题根本不在大模型,而在我们自己——我们给这几十个工具写的描述,要么含糊不清(比如一个工具的描述就一句"查询数据"),要么彼此边界模糊、互相重叠;而这些描述,恰恰是大模型用来判断"该调哪个工具"的唯一依据。我们给了它一堆写得乱七八糟的"说明书",却怪它选不对工具——这不公平,也不可能选对。这篇文章,就从这次"Agent 频繁用错工具"的事故讲起,聊聊做 AI Agent 时一个被严重低估的关键:工具的设计与描述,本质上是写给大模型看的"提示词",它的质量,直接决定了 Agent 靠不靠谱。

故障现场:一个"看不懂说明书"的 Agent

先理解 Agent 是怎么"选工具"的。当用户提出一个需求,Agent(背后的大模型)会拿到一份"工具清单"——清单里每个工具,都有一个名字、一段描述(description)、和一份参数说明。大模型就是纯粹依据这些文字描述,来判断"用户这个需求,该调用哪个工具、传什么参数"。它看不到工具的内部实现,它能依据的,只有你写的那段描述。

# 反面: 工具描述含糊、边界不清, 大模型根本没法准确选择
tools = [
    {"name": "query_order", "description": "查询订单"},        # 查什么?按什么查?
    {"name": "search", "description": "搜索数据"},             # 搜什么数据?太宽泛
    {"name": "get_info", "description": "获取信息"},           # 什么信息?和上面有啥区别?
    {"name": "query_logistics", "description": "查询物流信息"},
    # ... 还有几十个, 描述都这么含糊, 彼此边界重叠不清 ...
]
# 大模型面对"我的订单到哪了": query_order? search? get_info? query_logistics?
# 它也懵: 这几个描述听起来都沾边, 我到底该用哪个?? → 于是经常猜错

看出问题了吗?当用户问"我的订单到哪了",大模型看着这份清单犯了难:query_order(查询订单)?query_logistics(查询物流)?还是那个万能的 search(搜索数据)、get_info(获取信息)?这几个工具的描述都那么含糊、那么互相重叠,以至于"查订单到哪了"这个需求,听起来跟好几个工具都沾边——大模型没有任何清晰的依据去区分它们,只能连蒙带猜,自然经常猜错。这不是大模型笨,这是我们给它的"说明书"写得太烂——换成一个人类新员工,拿着这么一份含糊重叠的工具清单,他也一样会用错。

我那时才意识到一个被我严重忽视的事实:在 Agent 系统里,工具的"描述",根本不是给人看的注释,而是给大模型看的、决定它行为的"提示词"。大模型选不选得对工具,几乎完全取决于这些描述写得清不清楚。我们花了大力气去打磨那个面向用户的系统提示词,却把这几十个同样关键、甚至更关键的"工具描述",当成了无关紧要的注释草草了事——这才是 Agent 频繁用错工具的真正根源。

第一件事:工具描述是"提示词",要当一等公民来写

这次事故纠正了我的第一个、也是最重要的认知:工具的描述(以及工具名、参数说明),是 Agent 提示工程里和系统提示词同等重要、甚至更高频被使用的部分。它不是代码注释,而是大模型每一次做决策时都要逐字研读的"操作手册"。所以,你必须像打磨核心提示词一样,郑重地、字斟句酌地去打磨每一个工具的描述。

# 正面: 描述清晰、边界明确, 告诉大模型"这工具是什么、何时用、何时不用"
tools = [
    {
        "name": "query_order_status",
        "description": (
            "根据订单号, 查询单个订单的当前状态(待付款/已付款/已发货/已完成/已取消)"
            "及其物流进度。当用户询问'我的订单到哪了'、'订单什么状态'、"
            "'发货了吗'这类关于【具体订单进度】的问题时使用。"
            "注意: 本工具不用于搜索商品, 也不用于退款操作。"
        ),
        "parameters": {
            "order_id": {"type": "string", "description": "订单号, 形如 ORD20240101001"}
        },
    },
    # 每个工具的描述都这样: 干什么 + 何时用(给例子) + 何时不用(划边界)
]

对比一下就知道差别有多大。一个好的工具描述,应该清楚地回答大模型心里的几个问题:这个工具是干什么的(功能)?什么情况下该用它(给出典型的用户问法作为例子)?什么情况下不该用它(明确划清和其它工具的边界)?它需要什么参数(每个参数的含义、格式)?把这些都写清楚,大模型选起工具来就有了明确的依据,准确率会立竿见影地提升。记住这个心法:写工具描述时,想象你是在给一个聪明但对你业务一无所知的新员工写操作手册——你写得越清晰、边界越明确、例子越具体,他(大模型)就用得越准。那种"查询订单"四个字的描述,等于什么都没说。

第二件事:工具不是越多越好,要控制数量

除了描述含糊,我们还犯了第二个错:工具太多了。我们一股脑挂了几十个工具,觉得"能力越全越好"。可这恰恰是另一个误区:给大模型的工具越多,它的"选择负担"就越重,选错的概率也越高。这和人是一样的——给你 5 个选项,你能轻松选对;给你 50 个边界还互相重叠的选项,你也会挑花眼、选错。大模型在"从一长串工具里精准挑出那一个"这件事上,能力是有上限的。

工具数量与选择准确率的关系(经验性):
  几个工具(<10):     大模型选择准确, 表现优秀
  十几个工具:         开始吃力, 边界相近的容易混淆
  几十个工具:         显著下降, 频繁选错(我们踩的坑)

应对思路:
  1. 精简: 砍掉不常用的、合并功能重叠的工具
  2. 分组/分层: 用"路由"思路, 先粗分大类, 再在小范围内选具体工具
  3. 按场景动态裁剪: 不同对话场景, 只给大模型当前可能用到的那几个工具

解决"工具过多"的思路有几个:最直接的是"精简"——砍掉那些极少用到的工具,合并功能高度重叠的工具(我们那几个 searchget_info 其实功能重叠,完全可以合并)。更进阶的是"分层路由"——当工具确实很多、无法精简时,别把几十个工具一次性全丢给大模型选,而是设计一个两层结构:先让大模型在几个"大类"里做粗选(比如"这是订单相关、还是售后相关、还是商品相关?"),确定大类后,再只把这个大类下的少数几个具体工具拿给它精选。本质上,是把一个"从几十个里选一个"的难题,拆解成了两个"从少数几个里选一个"的简单问题。这和软件设计里"分而治之""分层"的思想完全一致。还可以"按场景动态裁剪"——根据当前对话的上下文,只把这一刻可能用得上的那几个工具暴露给大模型,而不是永远把全集都摆出来。

第三件事:工具的设计本身,也要"对大模型友好"

除了描述和数量,工具本身怎么"切分、设计",也大有讲究。我后来总结出几条"对大模型友好"的工具设计原则,它们能从源头上降低大模型用错、用不好工具的概率。

# 对大模型友好的工具设计
# 原则1: 一个工具只干一件清晰的事(单一职责), 别设计"万能工具"
# 反面: 一个 manage_order(action, ...) 用 action 参数区分增删改查 —— 大模型易传错
# 正面: 拆成 query_order / cancel_order / update_order_address 等, 各司其职

# 原则2: 参数尽量简单、明确, 能用枚举就别用自由文本
def refund_order(order_id: str,
                 reason: str):   # reason 若是自由文本, 大模型可能乱填
    ...
# 更好: reason 用枚举, 约束大模型只能从有限选项里选
def refund_order(order_id: str,
                 reason: Literal["质量问题","不想要了","拍错了","其他"]):
    ...

# 原则3: 工具的返回也要清晰, 必要时带上"下一步提示", 帮大模型接着决策
# 返回 {"status": "success", "data": {...}, "hint": "可据此回复用户订单已发货"}

这几条设计原则的核心,都是"降低大模型理解和使用这个工具的难度":原则一(单一职责)——一个工具只干一件清晰的事,别设计那种用一个 action 参数区分增删改查的"万能工具",因为参数越复杂、职责越混杂,大模型越容易传错;把它拆成几个职责单一的小工具,每个都简单明了。原则二(参数简单明确)——参数能用枚举(给大模型几个固定选项)就别用自由文本(让它自由发挥容易乱填),参数的命名和说明也要清晰。原则三(返回清晰)——工具的返回结果也要结构清晰、易于大模型理解,必要时甚至可以在返回里带上对下一步的提示,帮它更好地接着决策、组织给用户的回复。一言以蔽之:你在设计工具时,心里要始终装着那个"使用者"——它不是人类程序员,而是大模型;凡是能让大模型用起来更省心、更不容易出错的设计,都是好设计。我把工具设计的关键原则画成图:

这张图汇总了"对大模型友好的工具设计"的五个支柱:描述清晰、职责单一、参数简单、返回清晰、数量克制。它们共同指向一个核心理念——在 Agent 系统里,工具是大模型的"手脚",而工具的描述和设计,是连接"大模型的大脑"和"这双手脚"的接口;这个接口设计得好不好,直接决定了 Agent 能不能把事办对、办好。

第四件事:工具选对没有,要能"量化评估"

把描述、数量、设计都优化了之后,还有最后一个关键问题:你怎么知道改好了?改完到底准了多少?我那次最初的窘境,就是只能凭感觉"好像选对的多了点",无法量化。真正让优化走上正轨的,是我们建了一套工具选择的评估集——准备一批"用户问法 → 期望调用的工具"的标准样例,每次改完描述/工具,就跑一遍,看选对的比例。

# 建一个评估集, 量化"工具选择准确率", 让优化有据可依
eval_cases = [
    {"query": "我的订单到哪了",       "expect_tool": "query_order_status"},
    {"query": "这个东西想退",         "expect_tool": "apply_refund"},
    {"query": "帮我找找红色的鞋",     "expect_tool": "search_products"},
    {"query": "改下收货地址",         "expect_tool": "update_address"},
    # ... 几十上百个覆盖各种问法的样例 ...
]
def evaluate():
    correct = 0
    for c in eval_cases:
        chosen = agent.decide_tool(c["query"])   # 看 Agent 实际选了哪个工具
        if chosen == c["expect_tool"]:
            correct += 1
        else:
            print(f"选错: '{c['query']}' 期望 {c['expect_tool']}, 实际 {chosen}")
    print(f"工具选择准确率: {correct}/{len(eval_cases)} = {correct/len(eval_cases):.0%}")
# 每次改动工具描述后跑一次, 量化提升, 并定位还在选错的那些 case

这套评估集的价值,和之前聊 RAG 时强调的"建评估集"一模一样:它把"工具选得准不准"从一个主观感觉,变成了一个可量化、可对比、可持续优化的客观指标。有了它,你优化工具描述时,就能清清楚楚地看到:这次改动,准确率从 70% 提到了 88%;还有哪几个 case 在选错,它们错在哪、是哪两个工具的边界还不够清晰——于是你能精准地去改那几个工具的描述,而不是凭感觉瞎调。"凡是想优化的东西,先想办法量化它"——这条朴素的工程原则,在 Agent 这种行为"看起来很玄"的系统上,价值尤其巨大。没有评估集,你对 Agent 的所有"优化",都只是盲人摸象。

把"一个好的工具描述该包含什么"提炼成一张要素清单表,你写描述时可以对照检查:

要素 作用 示例
功能说明 这工具是干什么的 "根据订单号查询订单状态和物流"
使用场景 何时该用(给典型问法) "当用户问'到哪了''发货没'时用"
边界说明 何时不该用(划清边界) "不用于搜索商品或退款"
参数说明 每个参数的含义、格式 "order_id: 订单号, 形如 ORD..."
返回说明 会返回什么 "返回状态枚举和物流节点列表"

第五件事:这些工具的"反模式",尽量避开

反过来,我把我们踩过的、以及常见的工具设计"反模式"也整理成一张表——看到自己的工具有这些特征,就该警惕了:

反模式 问题 改进
描述只有几个字 大模型没依据, 全靠猜 补全功能/场景/边界/参数
多个工具功能重叠 边界不清, 选哪个都像 合并, 或明确划清各自边界
万能工具(一个 action 参数) 职责混杂, 参数易传错 拆成多个单一职责的小工具
工具几十个全摊开 选择负担过重, 准确率低 精简 / 分层路由 / 动态裁剪
参数是自由文本 大模型乱填, 不可控 能枚举就用枚举约束
从没量化过准确率 优化全凭感觉 建评估集, 量化迭代

这张反模式表,几乎就是我们那个"频繁用错工具"的 Agent 的"病历"——它当初这六条几乎条条都中。而当我们对照着把这些反模式一条条改掉:补全每个工具的描述、合并重叠的工具、拆掉万能工具、精简并分层、参数尽量枚举化、建起评估集量化迭代——那个曾经"看不懂说明书、瞎选工具"的 Agent,工具选择准确率从一开始的六七成,一路提到了九成以上,终于变成了一个靠谱的客服。这个过程让我深信:Agent 用不好工具,十有八九不是模型的问题,而是我们给它的"工具"和"说明书"做得不够好。

一张"Agent 总用错工具怎么排查"的决策图

把这次踩坑沉淀成一张图。当你的 Agent 频繁选错、用错工具时,别急着怪模型,照着它走一遍:

这张图的第一步,也是最该记住的:Agent 用错工具,第一件事是"建评估集、量化它到底错多少、错在哪",而不是凭感觉去改、或一上来就怪模型。有了量化,你才能顺着"描述含糊?工具太多?设计有问题?"这条线去逐项排查、逐项改进,并用评估集验证每次改动的效果,形成"改→量化→再改"的优化闭环。这套数据驱动的迭代方法,远比对着 Agent 干瞪眼、瞎调提示词靠谱得多。

我立下的几条 Agent 工具设计规矩

这次"Agent 频繁用错工具"的事故后,团队做 Agent 的规范里加了这么几条:

  1. 工具描述当提示词写:每个工具的描述都要包含功能、使用场景(带例子)、边界(何时不用)、参数说明,像打磨核心提示词一样字斟句酌。
  2. 控制工具数量:工具尽量精简,合并功能重叠的;数量多时用分层路由或按场景动态裁剪,别一次把几十个全摊给模型。
  3. 工具单一职责:一个工具只干一件清晰的事,别用 action 参数堆出"万能工具"。
  4. 参数尽量枚举化:能用有限选项约束的参数就别用自由文本,降低大模型乱填的概率。
  5. 返回结构清晰:工具返回要易于大模型理解,必要时带上对下一步的提示。
  6. 建工具选择评估集:准备"问法→期望工具"样例集,量化工具选择准确率,每次改动后回归验证。
  7. 先查工具再怪模型:Agent 用错工具时,先排查工具描述和设计,这往往比模型本身更可能是症结。

这几条里,第一条和第七条最点题。我尤其想强调第七条背后的心态转变:当 Agent 表现不好时,我们的第一反应,太容易是"模型不行";但更多时候,真正的问题在我们自己给 Agent 提供的"环境"里——工具描述写得糊不糊涂、工具设计得合不合理、提示词写得清不清楚。这就像带一个能力很强但刚入职的新人:他没干好,你与其抱怨"这人不行",不如先反思"我交代清楚了吗?我给的工具和文档够好吗?"——大模型也是如此,它很聪明,但它只能在你给它的信息和工具的基础上工作。把 Agent 当成一个聪明的新员工,你的职责是为它创造一个"能把事情做对"的好环境——清晰的指令、好用的工具、明确的边界;环境好了,它的能力才能真正发挥出来。

写在最后:Agent 的能力,一半在模型,一半在你给它的"环境"

这次做 Agent 踩的坑,和我之前做 RAG 踩的坑,在我心里汇成了同一个深刻的认知:一个 AI 应用最终好不好用,大模型本身的能力固然是基础,但同样关键的,是你为这个大模型精心搭建的那个"工作环境"——在 RAG 里,这个环境是"检索到的高质量资料";在 Agent 里,这个环境是"清晰的工具、好的描述、合理的设计"。大模型再聪明,如果你给它的是一堆含糊不清的工具说明书、一份驴唇不对马嘴的检索资料,它也办不好事——不是它不行,是你没给它一个能把事办好的环境。

想通这一层,我对"AI 应用开发者"这个角色的理解,变得清晰而坚定:我们的核心工作,不是去"造"那个大模型(那是模型厂商的事),而是去为大模型,精心地"搭建一个能让它充分发挥能力的环境"。这个环境,包括了喂给它的高质量数据、为它设计的清晰工具、给它的精准指令、帮它兜底的护栏、以及评估和迭代它表现的体系。大模型提供的是"原始的智能",而我们工程师的价值,在于把这份原始的智能,通过精心的"环境工程",可靠地、高质量地转化为解决实际问题的能力。这,恰恰是我们最该花心思、也最能体现专业价值的地方。

所以,如果你也在做 AI Agent,我想把这次踩坑最想说的话送给你:当你的 Agent 表现不尽如人意时,先别急着怪模型、急着换更贵的模型;回过头,认真审视一下你给它搭建的那个"环境"——你的工具描述,清晰到能让一个聪明的新人一看就懂吗?你的工具设计,简单到不容易用错吗?你的工具数量,克制到不会让它挑花眼吗?你有没有一套评估体系,能告诉你它到底表现如何?把这些"环境"打磨好,你会惊讶地发现,同一个模型,能力仿佛瞬间提升了一大截——因为你终于给了它一个能大展身手的好环境。那个曾经"频繁用错工具"的 Agent,在我把工具这套"环境"认真做好之后,脱胎换骨;而它教给我的最宝贵的一课就是:在 AI 时代,我们或许造不出最强的模型,但我们完全可以,为模型造出最好的环境——而后者,往往才是决定一个 AI 产品成败的、真正属于工程师的战场。

—— 别看了 · 2026
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理 邮箱1846861578@qq.com。
技术教程

插个枚举值搞乱所有历史数据:TS 数字枚举避坑复盘

2026-6-1 13:22:17

技术教程

开了多线程反而更慢:Python GIL 避坑复盘

2026-6-1 13:32:20

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索