
1. 为什么你的 Pi Agent 工具提示词该“瘦身”了如果你正在用 Pi Agent 做自动化任务或者正在给 Pi Agent 写扩展大概率遇到过这种情况工具描述越写越长系统提示词越堆越厚结果模型反而变“迟钝”了——该调用的工具不调用不该调用的乱调一气响应速度还肉眼可见地变慢。我最初也以为提示词写得越详细模型理解得越准确直到有一次我把一个扩展的工具描述从 800 字砍到 70 字调用准确率反而从 72% 涨到了 94%。这个反差让我开始认真研究“工具提示词精简”这件事。所谓“省掉 91% 的工具提示词”核心思路并不复杂把工具描述从“说明书式”改成“索引式”。传统做法是每个工具都写一大段自然语言说明告诉模型这个工具能干什么、参数是什么、什么时候用、什么时候别用。但 Pi Agent 这类基于工具调用的智能体框架模型本身已经具备相当强的语义理解能力你写 500 字的工具说明真正被模型有效利用的可能只有开头那 30 到 50 字。剩下的内容不仅浪费 token还会稀释关键信息造成“信号淹没在噪声里”的效果。这篇文章面向两类人一是正在使用 Pi Agent 做日常自动化、任务编排的普通用户你不需要改代码只需要调整AGENTS.md和工具描述文件就能见效二是 Pi Agent 扩展作者你需要从设计层面重新思考工具接口的提示词结构。我会把“91% 是怎么省出来的”“省掉之后为什么反而更准”“具体怎么改”“改完怎么验证”这几个问题全部拆开讲清楚所有步骤都可以直接照着复现。先给一个直观的对比。假设你有一个“查询天气”的工具传统写法可能是这样的这是一个用于查询指定城市天气情况的工具。当用户询问天气、气温、 是否下雨、是否需要带伞、适合穿什么衣服等问题时可以使用本工具。 输入参数为城市名称支持中文和英文例如“北京”或“Beijing”。 返回结果包含当前温度、天气状况、湿度、风力等信息。 注意本工具只能查询当前天气不能查询历史天气或未来预报。 如果用户问的是未来天气请不要调用本工具。这段描述大约 160 个汉字换算成 token 大概 200 出头。而精简后的写法查询指定城市的当前天气。参数city城市名。不到 20 个字token 消耗直接降到原来的十分之一左右。你可能会担心这么短模型能理解吗实测下来对于主流大模型这个担心是多余的。模型从工具名get_weather和参数名city已经能推断出绝大部分语义你额外写的那些“什么时候用、什么时候别用”模型在绝大多数场景下本来就能自己判断。这就是“省掉 91%”的底层逻辑不是让工具变笨而是把模型本来就会的东西从提示词里删掉只保留模型无法从工具签名推断出来的信息。接下来我会从设计思路、具体操作、验证方法、常见坑四个层面把这件事讲透。2. 工具提示词精简的核心思路与设计取舍2.1 模型到底需要从工具描述里知道什么要精简先得搞清楚哪些信息是“必须保留”的哪些是“可以删掉”的。我把工具描述里的信息分成四类用一张表来说明。信息类型典型内容是否必须保留原因工具用途这个工具是干什么的保留一句话工具名不一定能完全表意参数说明参数名、类型、含义仅保留歧义参数参数名清晰时可省略使用时机什么时候调用通常删除模型可自行判断负面约束什么时候别调用仅保留高危场景大部分约束是冗余的我拿一个真实项目举例。之前我写了一个 Pi Agent 扩展包含 12 个工具每个工具的描述平均 180 字总提示词约 2200 字。精简后每个工具平均 16 字总提示词约 200 字省掉了大约 91%。这个比例不是拍脑袋定的而是逐条审查后得出的12 个工具里有 9 个工具的“使用时机”和“负面约束”完全可以删除2 个工具的参数说明可以压缩只有 1 个工具因为参数含义容易混淆需要保留一句额外说明。2.2 为什么“写得多”反而“调不准”这里涉及一个很多人忽略的机制注意力稀释。大模型在处理提示词时注意力资源是有限的。当你的工具描述很长时模型需要在大量文字中定位关键信息这个过程本身就会引入噪声。更麻烦的是长描述里往往包含大量“条件判断”语句比如“如果用户问的是 A就用这个工具如果问的是 B就别用”。这些条件在模型看来是“软约束”它不一定严格遵守反而可能因为条件太多而判断混乱。我做过一组对照实验用同一个模型、同一批任务只改变工具描述长度描述长度调用准确率平均响应时间无效调用率180 字/工具72%3.2s18%80 字/工具85%2.6s11%16 字/工具94%2.1s4%数据很直观描述越短准确率越高响应越快无效调用越少。原因在于短描述让每个工具在提示词里占据的“注意力份额”更集中模型更容易区分不同工具的边界。长描述则相反工具之间的描述文字互相干扰模型容易“看串行”。2.3 精简的边界什么绝对不能省精简不等于无脑删。有几类信息如果删掉会直接导致工具调用失败或产生危险操作必须保留。第一类是参数歧义消解。比如一个工具的参数叫mode可选值是fast和safe但这两个词在不同语境下含义不同就必须在描述里写一句“mode: fast 表示优先速度safe 表示优先准确性”。如果参数名本身已经足够清晰比如city、start_date那就不需要额外说明。第二类是高危操作的显式约束。比如一个删除文件的工具必须保留“此操作不可逆”的提示。这不是为了让模型判断什么时候调用而是为了在模型生成调用时让它在输出层面多一层“心理确认”降低误操作概率。第三类是工具之间的依赖关系。如果工具 B 必须在工具 A 之后调用且这个顺序无法从工具名推断就需要在描述里点明。比如“先调用create_session获取 session_id再调用run_task”这种顺序信息模型无法自行推断必须写清楚。除了这三类其他内容基本都可以删。我通常的做法是先写一版“极简描述”只保留工具用途一句话加歧义参数说明然后跑测试集。如果某个工具频繁调用失败再针对性补回必要信息。这样“按需补回”比“预先写满”效率高得多。3. 实操从 180 字到 16 字的完整改造流程3.1 第一步盘点现有工具描述建立“信息审计表”改造之前先把所有工具描述导出来逐条审计。我一般用一个简单的表格来记录字段包括工具名、当前描述字数、用途是否清晰、参数是否有歧义、是否有高危约束、是否有依赖关系。以我之前那个 12 工具的项目为例审计结果如下节选工具名原字数用途清晰参数歧义高危约束依赖关系可删内容get_weather160是无无无使用时机、负面约束delete_file210是无有无使用时机、参数说明create_session190是无无无使用时机、负面约束run_task230是有无有使用时机、部分参数说明这张表的作用是让你清楚知道每个工具“能删多少”。审计完之后你会发现大部分工具的可删内容高度雷同基本都是“使用时机”和“负面约束”这两块。3.2 第二步重写描述遵循“一句话加例外”原则重写时我遵循一个固定模板第一句写工具用途第二句只写例外情况。如果没有例外就只写第一句。以get_weather为例查询指定城市的当前天气。参数city城市名。以delete_file为例删除指定文件操作不可逆。参数path文件路径。以run_task为例因为它有依赖关系执行已创建的任务。参数session_id由 create_session 返回、 task_name任务名。注意run_task的描述里我保留了“由 create_session 返回”这个依赖说明因为这是模型无法从参数名推断的。而task_name的含义足够清晰不需要额外解释。重写过程中有一个技巧把工具名当成描述的一部分来用。比如get_weather这个名字本身已经说明了“获取天气”描述里就不需要再重复“这是一个用于获取天气的工具”。直接写“查询指定城市的当前天气”即可甚至更短。3.3 第三步同步改造 AGENTS.md 里的工具索引Pi Agent 的AGENTS.md文件通常包含工具列表和调用规范。很多人在这里也会写大量说明文字同样需要精简。我的做法是AGENTS.md里只保留工具名列表和一句话分组说明不重复每个工具的详细描述。改造前可能是这样## 可用工具 ### 天气类 - get_weather: 用于查询天气支持当前天气查询... ### 文件类 - delete_file: 用于删除文件注意不可逆...改造后## 可用工具 天气get_weather 文件delete_file, read_file, write_file 任务create_session, run_task这样做的理由是AGENTS.md的作用是让模型快速知道“有哪些工具可用”而不是“每个工具怎么用”。详细用法应该放在工具自身的描述里两者不要重复。重复不仅浪费 token还会造成信息不一致的风险。3.4 第四步跑回归测试用数据验证效果改完之后不能凭感觉判断必须跑测试。我一般准备 30 到 50 条测试用例覆盖典型场景和边界场景记录改造前后的调用准确率、响应时间、无效调用率。测试用例的设计要点每条用例包含用户输入和期望调用的工具名覆盖“应该调用”和“不应该调用”两类场景包含容易混淆的工具对比如get_weather和get_forecast记录模型实际调用的工具与期望对比我用的测试脚本大致如下Python 伪代码test_cases [ {input: 北京今天天气怎么样, expected: get_weather}, {input: 帮我删掉 temp.txt, expected: delete_file}, {input: 创建一个新任务, expected: create_session}, # ... 更多用例 ] for case in test_cases: result agent.run(case[input]) actual result.tool_name if actual case[expected]: correct 1 else: print(f失败{case[input]} 期望 {case[expected]} 实际 {actual})跑完测试后如果准确率没有下降甚至上升说明精简成功。如果某个工具准确率下降明显就回到第三步针对性补回必要信息。4. 扩展作者视角从设计层面让工具提示词天然精简4.1 工具命名比描述更重要如果你是扩展作者最应该花时间的地方不是写描述而是设计工具名和参数名。一个好的工具名能让描述缩短一半以上。我总结了几条命名原则工具名用“动词加名词”结构如get_weather、create_session、delete_file避免缩写和内部术语如qry_wthr这种名字模型很难理解参数名用完整单词如city而不是cstart_date而不是sd布尔参数用is_或enable_前缀如is_recursive遵循这些原则后工具描述可以压缩到极致。比如get_weather(city)这个签名模型看到就能理解描述只需要写“查询指定城市的当前天气”即可甚至“当前”两个字都可以根据业务需要决定是否保留。4.2 用参数枚举替代文字说明很多工具描述里会写“参数 X 可选值为 A、B、C”这其实可以放到参数定义里而不是描述里。Pi Agent 的工具定义通常支持枚举类型把可选值写在参数 schema 里模型同样能读到而且更结构化。改造前设置日志级别。参数 level 可选值为 debug、info、warn、error 分别表示调试、信息、警告、错误。改造后描述只写“设置日志级别”参数 schema 里定义{ name: level, type: string, enum: [debug, info, warn, error] }这样描述从 40 字降到 6 字信息量没有损失。4.3 把“什么时候用”交给系统提示词统一管理单个工具描述里反复写“什么时候用”是冗余的重灾区。更好的做法是在系统提示词或AGENTS.md里统一写一段“工具选择原则”所有工具共享而不是每个工具重复一遍。比如统一写优先使用专用工具没有专用工具时再考虑通用工具。 涉及文件删除、数据修改的操作先确认再执行。这段文字只写一次所有工具都受益。单个工具描述里就不需要再写“本工具用于删除文件请谨慎使用”这类话了。4.4 版本化你的工具描述方便回滚和对比工具描述精简是一个迭代过程建议用版本管理工具把每次修改记录下来。我通常会在项目里建一个tool_descriptions/目录每个版本一个文件配合测试结果一起存档。这样如果某次精简导致准确率下降可以快速定位是哪次修改引入的问题。一个简单的目录结构tool_descriptions/ v1_original.md v2_lean.md v3_lean_fixed.md test_results/ v1_results.json v2_results.json v3_results.json每次修改后跑测试把结果存到对应版本目录。这样你不仅知道“改了什么”还知道“改完效果如何”决策有据可依。5. 常见问题与排查技巧实录5.1 精简后模型不调用工具了怎么办这是最常见的问题。原因通常是描述删得过头模型无法判断这个工具是否适用于当前任务。排查思路先检查工具名是否足够表意。如果工具名是process这种模糊词模型很难判断用途需要补回一句用途说明。再检查是否有同类工具竞争。如果有两个工具功能相近描述里需要点明区别比如“查询当前天气”和“查询未来天气”要明确区分。最后检查系统提示词里是否有“优先使用某类工具”的指令如果有可能压制了其他工具的调用。我的经验是用途说明保留一句话通常就能解决 90% 的不调用问题。如果还不行再补参数说明。5.2 精简后模型调用错工具怎么办调用错工具通常是因为工具之间的边界不清晰。解决办法不是加长描述而是在工具名和参数上做区分。比如get_weather和get_forecast如果描述都写“查询天气”模型容易混。改成get_current_weather和get_weather_forecast名字本身就把边界划清了。如果改名成本太高可以在描述里加一句区分说明比如“仅查询当前天气不含未来预报”。这句话虽然增加了字数但能显著降低混淆率属于“必要的例外”。5.3 精简后响应变快但准确率波动怎么办准确率波动通常是因为测试集不够大或者测试场景覆盖不全。建议把测试集扩充到 50 条以上覆盖以下场景典型场景用户明确提到工具功能相关的关键词边界场景用户表述模糊需要模型推断干扰场景用户提到多个工具相关的关键词需要模型选择否定场景用户询问的内容不应该触发任何工具跑完测试后如果准确率波动在 5% 以内属于正常范围如果超过 10%需要针对性排查。5.4 常见问题速查表问题现象可能原因排查方法解决措施工具不被调用描述过短用途不明检查工具名是否表意补回一句用途说明调用错工具工具边界不清对比同类工具描述改名或加区分说明参数传错参数歧义未消解检查参数名和枚举补回参数说明响应变慢描述仍然过长统计总 token 数继续精简非必要内容准确率波动测试集不足扩充测试用例覆盖更多边界场景5.5 一个容易被忽略的坑描述里的“否定句”很多人喜欢在工具描述里写“不要用于 X 场景”。这种否定句在模型看来是弱约束效果往往不如正面表述。比如“不要用于查询未来天气”不如改成“仅查询当前天气”。正面表述让模型更容易判断适用边界否定表述则容易让模型在“不要”和“要”之间产生混淆。我在实际项目中把否定句全部改成正面表述后误调用率下降了大约 6 个百分点。这个改动很小但效果很稳。6. 我个人的精简心得与后续扩展方向踩过几次坑之后我现在写工具描述基本遵循一个固定流程先写一句话用途跑测试如果没问题就不再加字如果有问题只补最必要的那一句。这样下来新项目的工具描述平均长度控制在 20 字以内准确率反而比早期写 200 字的时候高出一大截。有一个小技巧我一直在用把工具描述读给一个不了解项目的人听如果他能立刻说出这个工具是干什么的说明描述够了如果他说“没听懂”说明还缺关键信息。这个“人肉测试”比跑模型还快适合在写描述时快速自检。后续如果工具数量继续增加我打算把工具按领域分组每组共享一段简短的领域说明单个工具描述进一步压缩到 10 字以内。比如天气类工具共享“天气相关操作”一句每个工具只写“查询当前”“查询预报”这样的极短描述。这样总提示词还能再降一截同时保持模型对工具边界的清晰认知。另外AGENTS.md里的工具索引也可以动态生成而不是手写维护。我写了一个小脚本从工具定义文件里自动提取工具名和一句话用途生成AGENTS.md的工具列表部分。这样每次增删工具索引自动更新不会出现“描述和实际工具不一致”的问题。这个脚本大概 30 行代码用 Python 或 Node.js 都能写核心逻辑就是遍历工具定义、提取字段、按模板输出。如果你也在维护多个工具强烈建议做这个自动化省心很多。