新闻详情

新闻详情

首页 / 资讯中心 / 详情

Agent技能封装全指南:从工具调用到可复用能力设计

发布时间:2026/9/26 19:02:13来源:尧图网络
Agent技能封装全指南:从工具调用到可复用能力设计
在 LLM 应用落地过程中我一直有个很深的感受做一个能跑通的 Agent 不难难的是让 Agent 的每一项能力都能被稳定复用、被团队协作维护、被业务场景自由组合。如果你也在折腾 agent-skills大概率已经经历过这种场景——某个功能明明写好了换一个 Agent 框架、换一个业务场景就得重来一遍。这篇内容我会把围绕 agent-skills 的整套玩法拆开揉碎从概念定义到落地方案再到我实际踩过的坑一次性讲清楚。这套思路适合正在做 AI 应用、智能体开发的工程师也适合想把自己领域里的经验沉淀成“可被 LLM 调用能力”的产品经理和技术负责人。它不是某个框架的官方文档而是从实践里长出来的经验总结。1. agent-skills 到底是什么先搞清楚定义我第一次听到“agent-skills”这个概念时第一反应是“这不就是 functions calling 换个皮吗”。但真正用起来才发现如果只是把它当函数封装后面的维护成本会非常高。所以先把这个概念对齐了后面所有操作才有意义。1.1 技能与工具、插件的边界现在市面上的术语很乱工具tools、插件plugins、技能skills很多人混着用。我自己的理解是这样的工具是最底层的形式通常就是一个函数接收参数、返回结果Agent 通过 function calling 机制来调用它。工具的粒度通常比较小比如“获取天气”“计算两数之和”“查数据库”。插件是工具的集合围绕某一个平台或产品形态做了适配比如 ChatGPT Plugin 这种本质上是把一组工具包成一个可以在特定运行时里加载的单元。技能skill则更偏“能力封装”。它不一定只是一个函数而是一整套“什么时候用、怎么用、输入什么、输出什么、内部怎么处理”的完整定义。一个技能可以包含多个工具、可以有自己的提示词模板、可以有内部的决策逻辑甚至可以对 LLM 进行约束和引导。我用一个生活化类比帮助理解工具是一颗螺丝钉插件是一盒带说明书的标准螺丝套装而技能是一个“会拧螺丝的人”——它不仅知道螺丝怎么拧还知道什么场景该用多大的力、拧到什么程度、拧完怎么检查。1.2 为什么技能是代理能力复用的最小单元早期我直接把所有业务能力都注册成几十个 function 塞给 Agent结果很快发现几个痛点一是上下文爆炸。function 的 description 和 schema 都要占 token几十个 function 塞进去光定义就有几万个 token很多还是用不上的。二是选择和调度困难。LLM 面对几十个平铺的函数经常出现选错函数、参数乱传的问题。函数越多准确率越低这是实测的结论。三是复用性极差。同一个业务能力在这个 Agent 里这么写换个 Agent 又要重新定义一遍团队协作时更是灾难。技能的概念就是为了解决这些问题。它强调的是“把一个领域的完整能力打包”对外只暴露一个经过设计的、语义清晰的入口内部怎么组织不关你的事。而且技能本身可以分层——底层技能可以被上层技能调用形成一个能力的嵌套结构这比平铺一堆工具要优雅得多。2. 设计一个技能之前先把这几个问题想明白技能设计是最容易忽视、也最影响长期效果的一环。很多人上来就写代码写到一半发现技能跟实际需求对不上或者 Agent 老是不按预期调用问题根源基本都在设计阶段。2.1 技能的职责边界如何划分划分职责边界是个典型的“看着简单做起来难”的活。我现在的判断标准就三条第一条一个技能只解决一个问题。比如“处理订单”就不是一个好技能因为订单处理涉及创建、查询、退款、修改等多个动作这不是一个技能是一组技能。好的划分是“创建订单”“查询订单状态”“处理退款”每个技能职责单一。第二条技能的边界跟着业务概念走而不是跟着代码实现走。我之前把一个“发送通知”的技能拆成了“发邮件”“发短信”“发站内信”三个技能因为底层调用不同服务结果 Agent 经常要连续调三个技能才能完成一次通知任务。后来合并成一个“发送通知”技能内部根据参数判断走哪个渠道效果立刻好很多。因为对 LLM 来说“通知用户”是一个业务概念拆分反而制造了理解障碍。第三条技能之间不要互相依赖对方内部细节。技能 A 需要技能 B 的输出时应该通过标准化的返回结构来衔接而不是 A 里去读 B 的状态。一个技能的修改不应该导致另一个技能不可用这是我们团队的一条硬规矩。2.2 命名与描述的隐藏价值如果你以为技能名和描述只是方便人看的那就大错特错了。Agent 选择技能的唯一依据就是“技能名 描述 参数 schema”这三件事它们本质上决定了 LLM 能不能在正确的场景选中正确的技能。技能名要短、准、动词开头。比如“获取天气信息”“提交请假申请”“计算运费价格”这种名字 LLM 一看就懂。千万不要用“工具A”“func_001”这种名字也不要在一个名字里塞两个以上动作。描述是所有字段里最关键的。我总结了一个模板此技能用于【在什么场景下/当用户想要做什么事】时使用。 当【具体哪种情况】时不要使用本技能请优先考虑【另一个技能】。 输入参数说明【参数1】是xxx可选值为【枚举】默认值【xx】【参数2】必须符合【格式要求】。 输出说明返回【什么格式】包含【哪些关键字段】。这个模板看起来啰嗦但实测能明显提高技能选中的准确率。LLM 天然对语义敏感你给它越多关于“什么时候该用”的信息它就越不容易选错。有个细节值得单独拿出来强调描述里一定要写负面场景也就是“什么时候不要调用我”。我见过太多失败的案例就是因为 Agent 在模棱两可的情况下选择了一个看似相关、实际错位的技能。你告诉 LLM 这个技能不适合哪些情况比只告诉它适合哪些情况更重要。2.3 参数设计的三种模式参数是技能与 LLM 交互的接口设计不好就会出现“LLM 传了参数但你接不住”的尴尬局面。我总结了三种常见模式模式一扁平参数。适合简单场景几个业务字段直接平铺例如查询天气需要 city、date 两个参数。这种模式解析简单、错误率低但字段一多就失控。模式二嵌套结构。适合复杂业务对象用一个 JSON 对象承载多个子字段如创建订单时传入 items 数组每个元素包含商品 ID、数量、单价。这种模式对 LLM 的理解能力要求更高但表达能力更强。模式三原材料模式。不直接结构化参数而是让 LLM 传入原始文本或文件技能内部自己解析。比如“解析简历”技能入参就直接传简历文件路径或文本内容内部调用解析逻辑。这种模式降低了对 LLM 参数规整能力的要求把复杂度收口到技能内部。三种模式没有绝对优劣核心原则是能用扁平参数解决的就不要用嵌套能用结构化解决的就不要用原材料。参数结构越复杂LLM 出错概率越高这直接跟 token 消耗和使用体验挂钩。3. 从零实现一个技能完整实操光讲概念没用我直接带你跑一遍完整实现。这里我用一个“请假申请审批”的技能作为例子它既有表单结构、又有内部状态流转非常适合演示技能设计的完整思路。3.1 技能骨架与项目结构我现在倾向于用一个标准目录结构来组织技能做到“一个技能一个目录”方便版本管理和复用leave_request_skill/ ├── skill.yaml # 技能元数据名称、描述、参数schema ├── prompts/ │ ├── system.md # 技能内部的系统提示词 │ └── fewshots.md # 示例帮助LLM理解输入输出 ├── actions/ │ ├── submit.py # 提交请假申请 │ ├── approve.py # 审批通过/拒绝 │ └── query.py # 查询请假状态 ├── utils/ │ ├── validation.py # 参数校验逻辑 │ └── storage.py # 数据存取封装 └── main.py # 技能入口统一调度这个结构的核心思路是把“对外接口”skill.yaml和“内部实现”actions、utils完全分离。外部 Agent 只看到 skill.yaml 里的描述和参数 schema内部怎么实现都可以替换不影响调用方。skill.yaml 是一个技能的身份文件长这样name: submit_leave_request description: | 当用户想要提交请假申请、填写请假单、申请休假时使用此技能。 当用户只是想查询请假规则或审批进度时不要使用本技能请使用query_leave_request。 参数start_date和end_date必须为YYYY-MM-DD格式请假天数不得超过30天。 version: 1.0.0 parameters: type: object properties: applicant_name: type: string description: 申请人姓名 start_date: type: string description: 请假开始日期 end_date: type: string description: 请假结束日期 leave_type: type: string enum: [annual, sick, personal, marriage] description: 请假类型 reason: type: string description: 请假原因必须填写 required: [applicant_name, start_date, end_date, leave_type, reason]看起来简单但这里面的细节都是踩过坑才补上的。比如“请假天数不得超过30天”这条就是因为我遇到过 LLM 一次给用户批了半年的假期。参数设计上所有用户可见字段都做了必要的约束说明LLM 在提取参数时就会更谨慎。3.2 核心逻辑实现与细节技能入口是整个技能的调度中心所有请求先进 main.py再做参数校验、业务分发、结果返回。我把 main.py 做成了一个“薄入口 强校验”的模式import json from typing import Any, Dict from utils.validation import validate_params from actions import submit, approve, query def handle(action: str, params: Dict[str, Any], context: Dict[str, Any] None): 技能统一入口根据action分发到具体处理逻辑 # 1. 统一校验参数拿不到合法参数直接拒绝 errors validate_params(action, params) if errors: return { status: error, errors: errors, hint: 请提供完整的申请信息包括姓名、请假起止日期、请假类型和原因。 } # 2. 根据动作分发 if action submit: result submit.run(params, context) elif action approve: result approve.run(params, context) elif action query: result query.run(params) else: return {status: error, errors: fUnknown action: {action}} # 3. 统一包装返回结果保证结构一致 return { status: success if result.get(success) else error, data: result.get(data), message: result.get(message, ) }这套实现里有几个细节值得说道说道。第一入口函数接收一个action参数用来区分同技能下的不同操作。这是技能内部做子功能拆分的关键手法——对外是一个“提交请假申请”技能对内可以细分为 submit、approve、query 三个动作供内部调度或上层技能调用。第二params和context分开了。params是用户侧的意图参数context是系统侧的运行上下文如用户身份、租户信息、权限等级。这个区分特别重要否则技能很容易被“越权调用”——比如一个普通员工传一个 managertrue 就把自己审批通过了。第三所有返回信息都要带上hint字段。这个字段是给 LLM 看的当参数校验失败时Agent 可以根据 hint 提示用户重新提供正确信息而不是对着一个“参数错误”的报错无所适从。我再展开说一个容易被忽视的细节返回结构的稳定性。技能返回给 Agent 的数据结构必须是一套固定模板不能今天返{status:ok, data: {...}}明天又改成{code:0, result:{...}}。Agent 的逻辑很多时候是在“猜”你的返回格式格式越稳定它越能正确理解你的输出。我甚至遇到过 Agent 因为上次返回结构带了一个多余字段下次就误以为那个字段是必填的情况。格式统一这个事值不值得都不过分。3.3 挂载到代理的两种方式技能实现好之后怎么让代理真正用上它我实战中主要用过两种方式各有适用场景。方式一直接作为函数调用注册。如果你用的是支持 OpenAI function calling 风格的框架LangChain、AutoGen、各种开源 Agent 框架基本都支持可以把这个技能的入口函数直接注册成一个 tool。这种方式的好处是快速、直观适合技能数量不多的场景。缺点是技能一旦增多description 和 schema 全量塞进上下文token 开销和选择准确率都会受影响。注册时有一个小技巧把 yaml 里的 description 和 parameters 直接作为 tool 的 description 和 parameters不要自己再重新写一遍。这样保证 Agent 看到的信息和技能作者设计的信息完全一致避免信息损耗。方式二通过技能路由器Skill Router挂载。当技能数量超过十几二十个之后我强烈建议引入一个路由器层。思路是先注册一个“技能路由”函数它的描述是“当用户有某类需求时从技能列表中选择一个最合适的技能返回技能名称”然后路由器内部维护一个技能清单用更轻量的方式比如先做一次关键词/向量检索缩小候选集再把缩小后的候选技能定义给 LLM让它在其中精确选择。我用一个生活化类比说明这个做法的好处如果一间办公室有 100 个人你要找一个能修打印机的人你不会把 100 个人都叫进来问一遍而是先问“谁懂设备维护”筛选出 5 个人再从中精细匹配。路由器就是做这个初筛的人。关于路由器用一个简单的关键词匹配还是用向量检索我的经验是先用关键词和规则能覆盖的场景不超过七成才上向量检索否则就是过度设计。毕竟每增加一个被调用的模型或向量服务就多一个延迟和失败的可能。4. 测试技能上线前必须过的三道关好多团队做 Agent最头疼的其实不是开发而是测试。技能这东西不像普通函数同样的输入可能因为 LLM 的随机性得到不同的行为路径所以测试策略必须分层设计。4.1 单元级验证单元级验证的核心是“不经过 LLM直接调用技能”。也就是把技能的入参写死成不同的 case验证返回结果是否符合预期。这一步能筛掉大部分参数校验、逻辑分支、异常处理方面的问题。我一般会为每个技能准备三类用例正常路径用例各种合法输入组合验证业务逻辑正确性。对于请假申请要覆盖年假、病假、事假、婚假等不同类型验证计算逻辑是否正确。边界值用例比如请假天数恰好 30 天边界允许、31 天边界拒绝、跨年日期、闰年日期。这些边界最容易出 bug也最容易在 Agent 真实使用时暴露。异常输入用例缺失必填参数、日期格式错误、类型不在枚举值中、超长文本等。这些 case 不是为了等 Agent 去兜底而是直接通过校验逻辑拦截返回带 hint 的报错。单元级验证还有一个隐藏收益它能反推你技能内部的分支逻辑是不是“可解释”的。如果你的技能逻辑复杂到连测试用例都写不清楚那说明设计阶段就该优化。4.2 代理级联调单元测试通过后必须把技能挂到真实的代理环境里做联调。这个阶段的目标是让 Agent 通过自然语言指令触发技能看它最终走的路是否正确。联调时我有两个常用手段一是指令集覆盖。提前准备一批参考指令覆盖各个调用场景。比如“请帮我请明天到后天的事假”“我下周一到下周三休年假帮我提交申请”“帮我看看刘XX的请假审批到哪一步了”。每个指令都要记录三件事Agent 是否选中了正确的技能、参数提取的准确率、返回结果是否符合预期。二是链路日志追踪。一定要在 Agent 运行链路里加上完整的日志包括 LLM 每次的选路、工具调用的入参和出参、每步耗时。联调时出问题九成都要靠日志来排查没有日志等于盲人摸象。联调时最常见的失败模式是“Agent 选了技能但没有正确传参”。比如用户说“帮我请个假”Agent 选了请假技能但是 start_date 和 end_date 都没填就去调用了然后技能返回报错。这种情况要在技能的 hint 里引导 LLM 追问用户让它通过“多轮对话”补齐信息而不是强行调用。4.3 长尾场景回归这一个阶段是最容易偷懒、也最能体现经验的地方。如果只是用固定指令测一遍就上线后面大概率会被各种长尾输入打脸。我做长尾回归的方式是把历史真实对话中出现过的、以及业务同事提出的“奇怪问题”全部收集起来组成回归测试集。每次技能或系统更新后跑一遍确保之前能通过的 case 没有回归顺便观察新增了哪些覆盖。比如请假技能上线一段时间后我回收了这些长尾 case“我今天心情不好不想上班”没有明确请假类型和日期“请帮我请一个明天的病假”类型具体但缺原因“你好在吗能帮我看看吗”完全模糊根本不涉及请假“帮我把上周提交的请假申请撤销”不在当前技能的职责范围这些 case 的预期不是“调用成功”而是**“正确处理”——有的预期是技能被选择后追问信息有的预期是技能不被选择并转给其他技能或兜底回复。所以回归不是看技能能不能成功执行而是看 Agent 的整体决策是否合理**。我强烈建议每个团队把回归测试集沉淀成一个独立的数据文件定期执行。这比任何单元测试都更接近线上真实情况也是提升 Agent 稳定性的最大杠杆。回归测试这个事没有“做完”的时候它是一个持续维护的资产。5. 常见问题与排查技巧实录开发 agent-skills 的过程里我累积了一批高频问题。这里列出来每个问题都附带我的排查思路和最终解法希望能帮你少走点弯路。5.1 描述写得太泛导致代理总是选错现象监控日志里发现用户问天气Agent 却调用了“获取日期和时间”的技能用户想查物流Agent 却调了“查询订单”。技能本身没毛病就是 Description 写得太宽泛。排查思路打开 skill.yaml看描述的精确度。之前一个技能描述只写了“查询订单相关信息使用”实在是太泛了。我后来改成了“当用户询问订单状态、物流进度、预计送达时间时使用此技能。当用户想对订单进行修改或退款时请勿使用此技能——那应使用 modify_order 或 refund_order 技能。”结果改完之后技能选准确率明显上升。我复盘了几次出错案例发现 LLM 在多个 Description 都比较泛时会倾向于选择字面更接近用户问题的那个这套逻辑不准确但却是 LLM 的真实“思考路径”。所以描述越精确它越不容易想歪。5.2 参数歧义导致调用失败现象用户说“帮我请三天假”Agent 把 start_date 提取了但 end_date 怎么都提不出来技能一直报参数缺失。排查思路这是典型的参数设计对 LLM 不友好。用户说“三天假”LLM 需要自己计算 end_date这步对很多小模型来说很容易出错。我后来把参数 design 做了调整把 end_date 的必填逻辑放开改为“end_date 与 start_date 至少提供一个另一个可由技能内部计算”并且在技能描述里增加一句“当用户只提供请假天数时请先确认 start_date再根据天数计算 end_date”。结果参数提取成功率大幅提高。这个案例给我一个启发不要指望 LLM 去替你完成逻辑推导把推导放到技能内部。LLM 最适合做的是意图理解和参数提取纯计算和逻辑推导尽量交给代码。5.3 技能内部出现不确定性现象技能内部依赖了 LLM 来解析非结构化输入结果有时解析对有时解析错导致最终结果不稳定。比如“解析请假原因”时让 LLM 判断用户说的是病假还是事假同一个输入多次运行结果不一致。排查思路我遇到这个问题的第一反应是优化 prompt但连续调了几版都不稳定。后来我意识到技能内部的确定性必须靠规则和代码保证而不是靠 LLM 的自觉。于是我把内部解析逻辑改成了“关键词规则优先 LLM 兜底”规则能命中就直接返回只有规则无法覆盖时才调用 LLM。结果稳定性立刻上一个台阶。这件事让我养成了一个习惯凡是技能内部的决策能写规则就不上 LLM必须上 LLM 的地方要把输出约束成极简枚举值并且做好失败回退。为了方便参照我把这些问题整理成了速查表问题典型现象排查方向推荐解法描述泛化选错技能看 Description 是否覆盖正负面场景用“何时用/何时不用”模板重写描述参数歧义必填参数缺失分析 LLM 提取参数难易度放开必填约束内部补齐缺失字段内部不稳定同样输入不同输出检查内部是否依赖 LLM 决策规则优先LLM 兜底上下文膨胀响应变慢、选路变差技能注册量过大引入技能路由器做两级筛选返回格式漂移Agent 理解错误检查返回结构是否稳定统一返回模板禁止随意增删字段5.4 额外分享一个容易被忽略的坑并发与超时Agent 调用技能时通常都有超时限制如果技能内部处理时间过长Agent 那边就会“断掉”。我遇到过一个问题某个技能内部需要调一个外部 API那个 API 偶尔响应特别慢结果 Agent 一直拿到超时错误用户以为系统卡死了。解决方式有二一是把技能内部的耗时操作改成异步化先返回一个“处理中”的状态再通过单独的状态查询接口拿最终结果二是调大 Agent 侧的超时阈值并给技能内部的服务增加显式超时和重试机制。很多 Agent 框架里 tool 的超时是可以配置的别用默认值硬扛。6. 从经验角度说几点我的真实体会写到这里我不打算给你一个“万能方法论”式的总结因为 agent-skills 这个领域演进太快方法论过几天就可能过时。我分享几个从实操中沉淀下来的判断供你参考。一个是我现在宁可技能少而精也不多而滥。技能数量每增加五到十个选择器的准确率就要掉一个台阶这几乎是个铁律。与其把什么小操作都封装成技能不如把高频、高价值的场景做深低频小操作直接让 Agent 用通用能力处理。第二个感受是技能的描述比实现更重要。不管内部逻辑写得多好如果描述写得不够精确这个技能在 Agent 眼里就等于没有。我会花至少一半的时间在设计描述和参数 schema 上代码反而是其次。团队里新人加入时我也会要求他们先写技能描述评审过关了再动手写实现效果出奇地好。第三个体会是评估指标要跟着业务目标走不要只看调用成功率。调用成功不等于任务完成更不等于用户满意。我做技能效果评估时会统计三个维度任务完成率用户在合理轮数内得到有效结果、参数提取正确率Agent 是否从用户话语中准确提取必要信息、无效调用率Agent 选择了技能但其实不该调用或调用无意义。这三个指标同时达标才敢说技能是真正可用的。最后一个建议多去观察真实对话。别只看测试集。真实用户产生的输入是最有价值的数据也是改进技能设计和描述的直接素材。每过一段时间把线上对话日志拿出来遛一遛你会惊讶地发现有那么多设计时没想到的边角场景。agent-skills 是一条值得长期投入的方向因为它直接决定了 Agent 能力的天花板和扩展效率。希望这篇内容能帮你少踩几个坑更早地把你的 Agent 从“能聊”推向“能干活”的阶段。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

COS域名防红防封实战:多域名轮换调度与健康度评分 2026/9/26 22:26:59

COS域名防红防封实战:多域名轮换调度与健康度评分

简介:这份COS域名防红防封强开源码面向需要处理域名拦截问题的站长、运营人员及前端开发者,核心解决微信等平台内链接被拦截、域名被标记的困扰。资源包共2个文件,均为html格式,压缩包体积约5KB,轻量到几乎不占空间&am…

阅读更多 →
2026年DBA的6项核心能力:从被动救火到价值驱动 2026/9/26 22:26:58

2026年DBA的6项核心能力:从被动救火到价值驱动

2026年,DBA这个岗位早就不是“会装库、会备份、会看告警”就能安稳混日子的时代了。我见过太多同行,干了五年八年,还在被同一个问题困住:数据库一出事就被叫起来背锅,平时却没人觉得你有价值。说句不好听的&#xff0c…

阅读更多 →
C#反编译工具实操指南:DLL还原成可编译工程的全流程 2026/9/26 22:26:52

C#反编译工具实操指南:DLL还原成可编译工程的全流程

简介:ILSpy是一款完全免费且开源的.NET反编译器,基于MIT许可证发布,主要面向需要逆向分析.NET程序集的开发者与安全研究人员。它由iCSharpCode团队打造,旨在替代收费的Reflector,可直接将dll、exe等程序集拖入界面或通…

阅读更多 →
微信小程序投票评选系统源码实战:毕设部署与避坑指南 2026/9/26 22:26:52

微信小程序投票评选系统源码实战:毕设部署与避坑指南

简介:这套微信小程序投票评选系统源码,是面向毕业设计场景的完整Java项目,包含小程序端与后台管理端,适合计算机相关专业学生参考学习,也可作为课程设计或毕业设计的基础框架。项目实现投票活动配置、选手管理、用户投…

阅读更多 →
wordpress主题升级失败实战案例:3步避坑指南 2026/9/26 22:26:52

wordpress主题升级失败实战案例:3步避坑指南

wordpress主题升级失败实战案例:3步避坑指南 找建站公司怕被坑高价,这是很多中小企业主心里的刺。我见过太多老板花大几千甚至上万做站,结果主题一升级就崩盘,售后还推诿扯皮。今天不聊虚的,直接拆解一个真实的…

阅读更多 →
GaussDB 5.0轻量级安装包:Linux下三步搞定单机部署 2026/9/26 22:26:52

GaussDB 5.0轻量级安装包:Linux下三步搞定单机部署

简介:GaussDB 5.0轻量级安装包(Linux版,即高斯DB)是针对CentOS x86_64平台的数据库部署资源,定位为openGauss开源项目的Lite形态,特别适合硬件资源有限但希望体验华为自研分布式数据库能力的开发者、运维人…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉