从硬编码到动态决策:Agent工具选择策略的演进与落地

发布时间:2026/10/31 13:24:14

从硬编码到动态决策:Agent工具选择策略的演进与落地 上周有个朋友过来找我聊说他负责的 Agent 项目要从 20 多个工具里做选择代码里全是 if-else每次加新需求都得把整棵规则树翻一遍改完还要担心把旧分支打坏。他说想换成动态决策但又怕结果不可控。这个纠结我太熟悉了我自己做 Agent 的早期也是这么过来的从硬编码开始再一步一步过渡到动态选择。这里要说的工具选择策略是 Agent 开发里最基础、也最容易被低估的一个环节用户一句话进来Agent 到底该调哪个工具、传什么参数、按什么顺序执行。选错了后面所有动作全白费。市面上聊 Agent 框架、多 Agent 编排的文章已经很多了但专门把工具选择拎出来讲透的反而少见。这篇博文我就从硬编码讲起分析它为什么成了大多数人的默认选择再讲动态决策背后的原理、落地实现、性能优化和踩坑记录适合正在做 Agent 产品、想把手头工具编排方式优化的开发者参考。1. 先聊聊硬编码为什么大家一开始都这么干1.1 硬编码工具选择的四种常见形态在 Agent 项目里硬编码不是一上来就写得很丑它其实有几种递进的形态。第一种是最朴素的 if-else / switch 分支。根据用户输入里的关键词或者意图标记直接路由到固定工具。比如检测到查天气就去调天气 API检测到订闹钟就去调闹钟工具。逻辑直白新手上路基本都先这么写。第二种是正则 / 规则映射。比 if-else 更进一步先抽取出实体再把命中的规则映射到工具。例如用户说我要订明天早上 8 点去北京的机票先用正则抓日期、时间、目的地再按模板拼出订票工具的调用参数。第三种是状态机路由。把 Agent 会话切成待确认身份 → 查询订单 → 处理售后这样的状态每个状态下面只开放一个或几个工具。这种形态适合流程固定的场景本质上还是人为规定好了路该怎么走。第四种是干脆在 prompt 里写死调用剧本要求模型先调 A 工具如果结果为空再调 B 工具。看起来是模型在决策但调用顺序和条件都已经被写死了改起来照样要改 prompt还是硬编码的思路。这四种形态我早期都写过最伤的其实是第一类和第四类。第一类是纯维护灾难每加一个分支都要担心和其他分支打架第四类是假动态看起来模型在做决定实际上一点容错和泛化能力都没有。1.2 硬编码的开局优势与后期代价硬编码之所以能成为几乎所有 Agent 项目的默认起点是因为开局优势太明显了。开发快一个分支对应一个工具几小时就能跑通主流程。完全可解释出问题能立刻定位是哪个分支、哪个条件出了问题。没有额外推理延迟不需要等模型做二次决策。初始效果稳定工具集合小的时候规则很容易覆盖大多数用户说法。但工具数量一旦超过某个阈值代价就开始快速放大。先是最直观的维护成本每加一个新工具都得把旧分支全看一遍怕命中冲突加完还要补测试用例。其次是覆盖不全的痛点用户说法千变万化关键词规则永远追不齐同一个查订单能说出十几种变体规则漏一个就挂一个场景。再就是上下文浪费如果你把整套路由规则都写进 prompt每次请求都背着厚厚一叠指令token 费用上去了首字延迟也上去了。我当时项目里有 13 个工具时硬编码还能扛得住。等工具涨到 20 多个并且出现了同一个意图可能命中多个工具的情况规则树就彻底失控了漏匹配、误匹配轮番出现修完一个又冒出来两个。硬编码和动态决策之间不是谁绝对更好的关系。如果你手里只有四五个工具流程又高度确定硬编码就是最优解又快又稳。真正逼着你升级的是规模而不是某个单点问题。1.3 什么时候硬编码依然是正确答案虽然我把硬编码吐槽了一顿但如果你满足下面任一条件我建议你继续用硬编码别跟风上动态决策。工具数量少五六个以内规则覆盖得了。流程是确定性的每个分支都有明确触发条件比如表单校验、数据回填。对延迟和成本极度敏感希望尽量不走模型推理。场景完全封闭用户输入变化不大比如内部系统的固定指令。还有一个经常被人忽略的点硬编码最适合当骨架用。一个复杂的 Agent 主流程主干可以硬编码比如必须先登录、再填参数、最后提交但主干上的这一步该选哪个工具可以交给动态决策。硬编码负责确定性动态决策负责不确定性两者不是二选一而是可以混合的。这套规则骨架 动态决策的形态是我现在做 Agent 方案时的默认推荐后面第 3 节我还会结合实现展开讲。2. 从硬编码到动态决策核心痛点与设计思路2.1 动态决策的本质是什么工具选择本质上是路由问题动态决策说白了就是把路由权从程序员手里移交到大模型手里。模型读你的工具描述结合用户当前意图输出该用哪个工具、参数是什么。这个决策过程不再需要你维护规则树取而代之的是你维护工具描述的质量。我刚开始很不适应让权总觉得不可控模型选的工具凭什么信得过。后来想明白一件事动态决策不是放弃控制而是把控制的粒度上移。硬编码控制的是每一种输入具体怎么走动态决策控制的是工具怎么描述、候选集怎么给、结果怎么校验。控制点变了但控制一直都在。而且动态决策天然适配大模型的泛化能力同一套机制能覆盖你完全没预写过的用户说法。比如你先写了查订单状态的工具用户某天说我的快递怎么还没到模型依然有可能通过语义相关性把它路由到正确的工具上这在硬编码时代几乎不可能。2.2 动态决策的三个关键维度做动态决策的时候我一般会盯紧三个维度。相关性是第一位的。模型选工具靠的是工具描述和用户意图之间的语义重合度。描述写得烂选择必然烂这个没有任何捷径只能靠描述工程去补。复杂度排在第二。候选工具越多模型的选择准确率越低。这不是玄学而是有明确趋势的工具在 10 个以内时准确率比较高20 个以上明显下滑50 个以上就必须要做预筛。你可以理解成模型在长列表尾部容易注意力稀释目标工具被埋在了几十个工具描述里。可靠性排第三。同一个用户意图多轮对话、多人重复触发时要尽量保持选择结果一致减少随机抖动。平时 demo 看不出来一旦你接上自动化流水线抖动问题会非常折磨人。这三个维度是我判断一套动态决策方案是否合格的硬指标后续所有调优动作基本都是围绕它们展开的。2.3 动态决策快照让每次选择都可复现先介绍一个我在项目里非常受益的概念动态决策快照。听起来复杂其实就是把选择过程做成一条条结构化记录包含当前意图、候选工具、评分依据、参数草案和最终选择结果。这样每次工具调用都能追溯到一个决策现场调试和审计都有据可查。实操上我会把一次选择写成类似下面这样的快照{ intent: query_order_status, candidates: [search_orders, query_logistics, refund_process], scores: [0.82, 0.51, 0.12], selected: search_orders, params: {order_no: 20240101}, model: gpt-4o, latency_ms: 320 }快照最大的价值不在当天复盘而是能回流成测试集。把误选的样本沉淀下来下次迭代工具描述的时候拿来当回归用例改完就知道有没有修好有没有打坏别人。我现在项目里任何工具选择的 bug都不是靠口头争论修的而是先补一条快照用例再改描述、跑回归、看结果。3. 动态工具选择的落地实现从注册到执行的完整链路3.1 工具注册表与 Schema 设计动态决策的第一个基础设施是工具注册表。你不该把工具列表散落在代码各处而应该在一个地方集中注册并且给每个工具提供结构化元数据。这里我按生产环境的常见实践给你一个可复用模板tools [ { name: search_orders, description: 按订单号或客户手机号查询订单状态适用于用户询问订单进展、预计送达时间的场景。不要用于退款和投诉退款请使用 refund_process。, parameters: { type: object, properties: { order_no: { type: string, description: 订单号一般以字母开头如 A20240101 }, phone: { type: string, description: 客户手机号非必填用于辅助定位订单 } }, required: [order_no] } }, { name: refund_process, description: 发起退款申请并跟踪退款进度适用于用户明确提出退款、退货、不想买了等诉求。订单状态查询请改用 search_orders。, parameters: { type: object, properties: { order_no: {type: string, description: 订单号}, reason: {type: string, description: 退款原因} }, required: [order_no, reason] } } ]别小看这个 schema很多人在 description 上偷懒写一两句查询订单就完事。我的经验是工具描述必须回答三个问题这个工具负责什么什么场景下使用什么场景下不要用。尤其不要用这一点很关键能显著减少相似工具之间的误选相当于你自己给模型画好了决策边界。参数部分也要认真写类型和说明否则模型只能靠猜。required 一定要严格能必填就必填否则模型经常漏参数后面执行环节就开始报错。3.2 选择的实现三种主流策略动态选择不是只有一种实现完全取决于你的规模和成本。我按复杂度从低到高排个序你对照自己的情况选。策略一单轮 LLM 函数调用。直接用 function calling 或 tool calling 接口把工具列表塞给模型让模型输出结构化的工具调用。适合工具在 10 到 20 个以内、对成本不敏感的场景。优点是实现最快缺点是每次选择都要消耗不少 token而且候选一多模型容易犯迷糊。策略二分类器预筛 LLM 精排。先用轻量分类器从几十个工具里筛出 Top 5 到 8 个候选再让模型在这些候选里做最终选择。分类器可以是规则、Embedding 相似度也可以是小型微调模型。LLM 的决策负担小很多准确率也更稳这是我现在最常推荐的方案。策略三决策缓存加快照。命中高频意图时直接复用上次的选择快照完全不走模型。缓存可以维护一份意图到工具选择的映射对于高频场景这一层能挡掉大半的模型调用。把策略二和策略三结合起来的伪代码大概是这样的def select_tool(user_input, tools, cache): # 1. 查缓存高频意图直接命中快照不走模型 hit cache.lookup(user_input) if hit: return hit # 2. 预筛用 embedding 相似度取 Top N 候选 candidates embedding_search(user_input, tools, top_n6) # 3. LLM 精排在候选集里生成最终选择与参数 chosen llm_tool_choose(user_input, candidates) # 4. 写入快照置信度够高才缓存避免污染 if chosen and chosen.confidence 0.8: cache.store(user_input, chosen) return chosen这套流程我实测下来模型调用成本能降一半以上而且选择稳定性明显提升。核心思路就是能不麻烦模型就不麻烦模型把模型的价值集中在真正需要语义理解的决策环节。3.3 从选择到执行参数填充、校验与回退选择只是起点真正跑通业务需要把选了哪个工具变成工具被正确调用。这一段是工程化最容易翻车的地方但很少被聊到。首先是参数填充环节。模型给出的参数草案不能直接透传必须先做一轮校验必填项是否齐全、格式是否符合 schema、枚举值是否合法。校验失败的可以让模型针对缺失字段补充也可以直接返回提示让用户重新描述。我项目里有个搜索工具模型经常漏传日期范围加了参数校验之后这类问题基本绝迹。然后是执行环节的兜底。工具本身可能超时、报错、返回空结果这些不能直接抛给用户。通常做法是工具失败后先回退到同义工具比如主搜索失败就试备份搜索服务或者把失败原因整理成反馈带回给模型让模型换工具或换参数重试一次。最后记得加一条保险丝。如果连续两次失败就停止自动重试转人工或给出兜底话术。否则模型容易陷入循环调用疯狂消耗资源却没有业务产出。这是我见过的最常见的生产事故来源之一。4. 动态选择策略的进阶调优描述、评分与缓存4.1 工具描述直接决定命中率工具描述是最容易被低估的杠杆。同样一套工具描述从按订单号查订单状态改成用于处理用户查询订单进展、物流、签收状态的场景也可按手机号辅助定位退款请走 refund_process命中率能肉眼可见地提升。我在调描述时有一个固定套路先收集误选样本看模型为什么选错。比如发现它把订单查询和退款混淆就在退款工具的描述里明确加一句订单状态查询请改用 search_orders。这种边界化描述比单纯罗列功能点有效得多因为它直接消解了相似工具之间的语义重叠。顺便说一句现在很多 Agent 框架强调 harness 和 agent 的分离工具描述这种核心资产其实是放在 harness 层的。选型的时候别只看框架功能花哨不花哨要看它对工具注册、描述版本管理、测试回流的支持好不好这些才是长期维护的关键。4.2 参数约束与防抖让决策结果可复现在自动化链路里选择抖动是最折磨人的问题之一。同一句话可能上午选 A 工具下午选 B 工具结果还不一样。抖动的来源主要是三个模型采样温度、候选工具顺序、描述模糊。解决采样抖动最简单的是调低 temperature 到 0 或 0.1如果接口支持 seed 参数就固定 seed。候选顺序影响则可以这样处理在提交给模型前对候选排序做稳定化比如按工具名或者历史成功率排序而不是直接用 embedding 打分的原始顺序避免因为微小的相似度波动导致顺序变化。描述模糊引起的抖动没有捷径只能靠边界化描述去消除。我特别建议给动态选择建一套回归测试集。挑 200 条真实用户输入每条标注好期望工具每次改完描述就全量跑一遍看准确率是涨还是跌。没有这套回归你改描述就是凭感觉很容易修好一个工具又打坏另外两个。4.3 并发与性能动态选择怎么扛住流量动态选择的性能瓶颈很明显在 LLM 调用而不是工具本身。要扛并发不能指望每个请求都跑一轮模型推理。第一层优化是缓存高频意图直接命中快照挡住大部分请求。第二层是预筛前置Embedding 检索本身可以做成异步、并发友好让请求先在轻量层被分流。第三层是对 LLM 调用做池化和限流限制并发数、设置合理超时避免被单次慢响应拖垮整条链路。我实测过一个客服场景全量走模型时平均选择延迟约 600ms加上缓存和预筛后平均降到 150ms 以内并且约 70% 的请求完全不再消耗模型 token。动态选择的性能优化本质是想办法减少对模型推理的依赖而不是盲目堆高并发上限。5. 常见问题与排查实录5.1 工具一多就选不准怎么办先把工具数量降下来核心思路是漏斗Embedding 预筛 LLM 精排而不是让模型在 50 个工具里大海捞针。同时检查工具命名是否有冲突名字和描述里不要出现 get_data、do_something 这类毫无业务含义的通用词尽量改成带场景语义的名字比如 search_orders_by_customer。5.2 相似工具之间误选怎么隔离把相似工具的边界写死在描述里。比如查询订单和查询物流这两个工具在各自的 description 里互相声明边界明确写物流查询请使用 query_logistics本工具不处理物流信息。模型在候选阶段看到这样的边界声明误选率会显著下降。这个方法成本极低效果却是立竿见影的。5.3 把所有工具描述塞进 prompt上下文爆炸怎么办把工具全集变成候选集先检索再拼接。工具注册表里可以存完整描述但每个请求真正进入 prompt 的只保留 Top 5 到 8 个候选工具的描述。如果模型上下文本来就紧张还可以进一步压缩描述只保留名称、用途和必要参数把详细说明留在注册表里。5.4 动态选择会不会带来安全与权限问题会而且必须严肃对待。模型选出来的工具和参数不等于业务允许的操作。实践中我会做三层防线工具注册表里标注每个工具的最小权限执行前校验参数的取值白名单对高危工具比如发消息、删数据、转账强制人工确认或二次校验。动态决策是让模型更聪明不是让模型拥有权限。还有一点凡涉及用户敏感数据工具选择快照的日志要做脱敏手机号、订单号这些字段不能在日志里明文存储否则排查问题的时候容易惹出合规麻烦。6. 一点真实的项目体会与迁移建议说实话工具选择从硬编码到动态决策不是一次英雄主义式的彻底重写而是一个渐进迁移的过程。我现在的默认建议是小工具集直接硬编码中等工具集用规则骨架 动态决策的混合架构大工具集再上完整的检索、评分、缓存体系。如果你要动手改造我建议先从最容易变化的那批工具开始接上动态选择配上快照、缓存和回归测试集跑稳两个星期再扩大范围。别一上来就把所有工具切换成全动态出了错都找不到是从哪一步开始崩的。先把动态选择的路跑通再逐步收编硬编码只管得住的那部分分支。最后说一个我反复踩过的坑优先把工具描述写好比什么都强。模型选不准九成情况下不是模型太笨而是你的工具描述给它留了太多模糊地带。描述边界清晰候选集给得合理动态选择的效果就会远超你最初的预期。
延伸阅读

更多相关文章

2026/10/31 13:24:14

企业级软件二次开发全流程实战指南

1. 二次开发内容流程全解析 在软件开发领域,二次开发(简称"二开")就像给一套精装房做个性化装修——我们基于已有的成熟系统框架,根据业务需求进行定制化改造。最近五年,随着企业数字化转型加速,…

2026/10/31 13:24:14

AI Agent必备:Skills技能包设计指南,让大模型稳定执行任务

最近在技术社区里泡着,大家张口闭口都是 Agent、智能体、工作流自动化,但我自己最大的体感是:真正让 Agent 从“玩具”变成能干活“工具”的关键,往往不在模型选得有多强,而在你有没有给它配好一套“Skills”。这个词直…

2026/10/31 13:24:14

EULA资源包工程化:条款抽取、指纹校验与同意留痕实践

简介:围绕《电子用户许可协议(EULA)详解》整理的Java版Minecraft服务端开服配置参考包,面向需要搭建、调试服务端并理解EULA约束的初学者与服主。包内共9个文件,以4个yml服务端配置文件、server.properties属性文件、e…

2026/10/31 14:29:22

Claude-Relay-Service:构建多AI模型统一接入架构的技术实现方案

Claude-Relay-Service:构建多AI模型统一接入架构的技术实现方案 Claude-Relay-Service(CRS)是一个开源的多AI模型代理服务架构,通过统一API网关实现了Claude、OpenAI、Gemini、Droid等多种AI服务的标准化接入。该方案解决了企业级…

2026/10/30 20:55:10

全国计算机二级C语言真题PDF高效刷题指南

简介:这份PDF是全国计算机二级C语言考试的试题与答案解析,专为备考二级C语言的考生准备。内容涵盖C语言特点与设计理念、程序基本组成单位、main函数执行流程、函数嵌套调用规则、标识符命名规范、整型实型字符型数据类型、八进制十六进制数合法形式、运…

2026/10/30 20:55:10

requests+BeautifulSoup:爬虫抓取h1标题的入门实战指南

简介:一份以实战为导向的Python爬虫入门资源,面向具备基本编程基础、希望快速掌握网络数据抓取的初学者,可解决从零编写简单爬虫的常见困惑。实例以requests库发送HTTP请求、BeautifulSoup解析HTML文档,完整演示从网页中提取 标题…

2026/10/30 20:55:09

递推最小二乘参数辨识MATLAB编程:二阶系统与渐消记忆实现

简介:这是一篇面向控制系统、信号处理与机器学习等领域学习者的最小二乘参数辨识程序说明文档。资源共包含一个docx格式文档,压缩包大小七十八KB,内容围绕递推最小二乘算法和渐消记忆最小二乘算法展开:先构造一个极点位于单位圆内…

2026/10/31 0:02:41

猫狗目标检测数据集:VOC/COCO/YOLO三格式一体化实战包

简介:本资源是一套面向计算机视觉初学者与YOLO目标检测实践者的猫狗图像数据集及配套开发工具包,专为快速上手目标检测模型训练而设计。资源包含1000张真实场景高清猫狗图片,标注质量高,同时提供VOC(XML)、…

2026/10/31 0:02:41

HDU2017多校标程复现:算法竞赛工程化真题沙盒

简介:本资源为2017年HDU多校联合训练第一场官方配套资料,面向ACM程序设计竞赛备赛学生、算法爱好者及高校编程集训队成员,旨在提供权威解题参考与完整测试验证环境。压缩包共40个文件,含15份C标程(覆盖全部赛题&#x…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑