Agent Skills实战:从技能设计到编排避坑,让大模型稳定干活

发布时间:2026/10/21 4:09:27
Agent Skills实战:从技能设计到编排避坑,让大模型稳定干活 1. 从会聊天到会干活Agent Skills 到底解决什么问题近半年我一直在折腾各类智能体项目最深的感受是模型本身的能力已经够强了真正拉开体验差距的反而是那些看起来不起眼的技能定义。同样是调用一个天气接口有人写的技能让模型一次就精准命中参数有人写的技能能让模型连续犯错、胡编乱造。这个现象让我意识到一件事——Agent Skills 才是智能体落地时最值得花心思打磨的部分。打个比方大模型本身就像一个刚入职的高学历新人知识储备充足、理解能力很强但它不知道你们公司的报销流程是什么、不知道内部系统的字段含义、不知道哪些操作有风险需要人工确认。Skills 就是那份新人入职手册把每个任务拆解成可执行的动作、说清楚触发条件和注意事项。没有这份手册新人只能靠猜有了它才能稳定地干出及格线以上的活。这篇文章写给正在做 Agent 应用、尤其是被模型调用不听话工具参数老填错多步骤任务总断链这些问题折磨过的开发者。我会从技能设计的基本原则、参数约束的关键技巧、多技能编排的取舍再到排查思路和评估方法把我在真实项目里踩过的坑和验证过的做法完整梳理一遍。内容偏工程实践不涉及复杂的数学推导只要写过几段调用大模型接口的代码就能看懂并直接用起来。2. 技能设计整体思路拆解先想清楚边界再动手写2.1 技能、工具、函数调用三个名词的边界在哪很多人把 Agent Skill、Tool、Function Calling 混着用但在实际工程里它们是有明显分工的。我的理解是这样的Function Calling / Tool Calling模型输出结构化的调用意图告诉系统我想调用某个函数参数是这样的。这是通信协议层的东西解决的是模型怎么表达意图的问题。Tool一个可以被调用的具体能力单元比如查询天气发送邮件计算运费。它通常是独立的接口封装对应一个或一组函数。Skill技能更高一层的抽象它把完成某个用户目标所需的若干步骤、知识、约束条件打包在一起。一个 Skill 内部可以包含多个 Tool 的调用、固定的处理流程、甚至一段领域知识文本。举个例子帮用户完成订单退款是一个 Skill。它内部可能包含校验订单状态Tool A、计算可退金额Tool B 一段规则知识、发起退款Tool C、通知用户Tool D。如果只给模型四个孤立 Tool它可能顺序搞错、漏掉校验、退款金额算错但如果把这些编排和约束放进 Skill 的描述里模型就能按剧本执行。理解了这层差异你就明白为什么说 Agent Skills 是让模型从会聊天到会干活的关键 了。工具是零件技能是装配说明书模型则是那个拿着说明书干活的工人。2.2 设计技能时的五大边界问题在动笔定义任何技能之前我会强制自己回答五个问题回答不清楚就不写第一这个技能的触发条件是什么用户说什么样的话、处于什么样的上下文时才应该调用这个技能不写清楚模型就会滥用。比如发送邮件技能如果没有明确仅当用户明确要求发送时才调用模型可能在用户只是询问邮件功能怎么用时就去调用发送接口。第二这个技能能做什么、不能做什么边界不清晰是技能设计最常见的失误。我见过一个文本润色技能描述里写着负责优化用户输入的文本结果用户问数学题时模型也去调用它润色答案。正确做法是明确写本技能仅用于优化已有文本的表达质量不用于生成新内容、不用于回答事实性问题。第三这个技能需要哪些输入每个输入的约束是什么这一步直接决定了调用成功率。参数缺失、格式错误、枚举值超范围是最常见的三类调用失败原因。设计阶段就要对每个参数定义清楚类型、取值范围、默认行为、以及缺失时的兜底策略。第四这个技能的输出格式是什么模型拿到结果后还要继续推理输出格式混乱会连锁导致后续步骤出错。我会坚持给每个技能定义结构化的输出最好是 JSON Schema 级别的严格程度。第五这个技能的失败模式有哪些失败后怎么办真实的接口调用总会出错超时、限流、返回空数据、业务异常。技能描述里必须写清楚如果收到 XXX 错误码应该重试一次如果查询结果为空要告知用户未找到而不是编造数据。把五个问题写进技能定义相当于给模型划了一条清晰的跑道它不会乱跑你也更容易定位问题。2.3 为什么不要一上来就追求全能型技能很多开发者倾向于把技能设计得又大又全希望一个超级技能解决所有问题。我的经验恰恰相反技能的粒度越细越容易被模型正确理解和调用。细粒度技能的优势体现在几个方面。第一描述可以写得极其精确不会因为功能太多而含糊第二模型选择技能时更容易匹配用户意图减少误调用第三单个技能出问题时的影響面可控排查成本低第四可以针对高频技能做专门的测试和优化。当然粒度太细也会带来副作用——技能数量爆炸模型在第一步选择哪个技能就犯难。我目前的经验阈值是单领域内的技能数量控制在 10~15 个以内超过这个数量就要考虑分层或合并。技能越多对描述质量的要求越高这个下文会详细展开。3. 核心参数与描述规范模型听话的底层逻辑3.1 技能描述的结构化模板模型不像人它不会理解言外之意只会严格按照字面信息做匹配。因此技能描述必须结构化、无歧义。我在项目中总结了一套模板每个技能都按这个结构填写技能名称短名词短语一眼能看出功能。如查快递物流计算房贷月供。 触发条件什么情况下必须使用什么情况下禁止使用。 功能概述2~3句话说清楚这个技能做什么、达到什么效果。 输入参数每个参数的名称、类型、必填性、取值范围、约束条件、示例值。 执行流程核心处理步骤按序排列说明特殊情况如何处理。 输出格式结构化输出字段及其含义。 错误处理常见异常场景的处置方式。 安全与限制涉及权限、敏感操作时的确认要求。示例一个查快递物流技能的描述【技能名称】查快递物流 【触发条件】 - 当用户提供快递单号并要求查询物流轨迹时使用。 - 当用户询问包裹到哪了物流状态等意图时使用。 - 禁止在用户未提供或未授权提供快递单号时自行推测查询。 【功能概述】 根据用户提供的快递单号和快递公司代码查询该包裹的最新物流轨迹及当前状态返回带时间线的物流摘要。 【输入参数】 - tracking_number必填string快递单号支持数字和字母组合长度6~32位。示例SF1234567890。 - carrier_code必填string快递公司代码枚举值SF顺丰、ZT中通、YT圆通、YD韵达、JD京东。若用户只说了快递公司中文名需映射到对应枚举值。 - phone_last4可选string收件人手机号后4位部分快递公司查询需要校验如无需要可不传。 【执行流程】 1. 调用物流查询接口传入 tracking_number 和 carrier_code。 2. 若接口返回需要手机号校验的错误码提示用户提供收件人手机号后4位。 3. 若查询成功提取物流轨迹节点时间、地点、状态描述按时间倒序排列。 4. 若轨迹为空检查单号是否符合当前快递公司的格式格式错误则提示用户核对。 【输出格式】 JSON对象包含 - status: in_transit | delivered | exception | not_found - latest_time: 最新轨迹时间 - latest_location: 最新轨迹地点 - summary: 一句话物流摘要 - milestones: 轨迹节点数组每项包含time、location、description 【错误处理】 - 接口超时重试一次仍失败则告知用户物流系统繁忙请稍后再试。 - 单号不存在返回 not_found并提示用户核对单号。 - 严禁在查询失败时编造物流节点信息。 【安全与限制】 - 仅允许查询用户主动提供的单号。 - 物流轨迹数据仅用于回答用户本次查询不用于任何其他用途。写这么长的描述看似繁琐但它就是技能的说明书。实测下来描述越细致模型调用的准确率和成功率就越高反而节省了后续排查的时间成本。3.2 参数定义决定调用成败很多时候模型不是不聪明而是你给的参数要求让它无从下手。我整理了参数设计的三条铁律铁律一能枚举就不开放。凡是取值范围有限的字段一律给出枚举值。比如快递公司代码就不要让模型自由填字符串它可能会填顺丰速运SF-Express等各种变体。给出枚举表模型照抄就行。铁律二能给默认值就给默认值。比如查询天气技能的 units 参数默认 celsius发送邮件技能的 priority 参数默认 normal。减少模型需要决定的事情就是减少出错的概率。铁律三明确缺失参数时的处理策略。是让模型主动追问用户还是用默认值替代还是宁可失败也不猜测这个策略不同体验差异很大。对于安全敏感操作我倾向于缺失关键参数就向用户确认对于非关键参数直接用默认值更流畅。3.3 一个技能一个文件工程化组织方式当技能数量多起来之后组织方式会影响维护效率。我采用一个技能一个文件、外加一个索引清单的方式skills/ ├── index.yaml # 技能清单含每个技能的简介和入口 ├── shipping/ │ ├── track_express.yaml # 技能定义文件 │ └── README.md # 设计备注和变更记录 ├── payment/ │ ├── refund_order.yaml │ ├── query_balance.yaml │ └── README.md └── common/ ├── parse_address.yaml └── format_datetime.yaml每个技能定义文件用 YAML 或 JSON 编写因为这类格式对机器和人都是可读的。index.yaml 里同时维护每个技能的版本号技能逻辑变更时版本号递增方便回溯。这种组织方式的直接好处是可以针对单个技能做代码评审、走查和回归测试。我在项目里还加了自动化检查确保每个技能文件都包含必填字段、描述长度达标、参数约束合法。4. 多技能编排的实操要点从点状能力到流程闭环4.1 拆解一个完整任务的多技能协作流程用户的一个请求往往需要多个技能协作完成。以用户想申请退换货为例可能涉及查询订单状态、生成退货单、预约快递上门取件、通知用户。如果没有编排逻辑模型会手忙脚乱。我在实践中把多技能协作的编排策略固定为两种顺序流水线和条件分支。顺序流水线适合固定步骤的操作步骤1调用 order_query 获取订单详情 步骤2根据订单详情中的商品状态调用 return_create 创建退货单 步骤3调用 courier_book 预约上门取件 步骤4调用 message_send 给用户发送进度通知条件分支适合需要判断的场景判断订单状态 - 若 status 已发货先调用 return_apply 走售后审核流程 - 若 status 未发货直接调用 order_cancel 取消订单并退款 - 若 status 已完成提示用户该订单已超出退货时效关键在于编排逻辑不能只靠模型自由发挥必须在技能描述或者系统 Prompt 中给出明确的路径依赖。我的做法是在系统 Prompt 里固定写一段流程规则模型只能遵循不能自由创造流程。4.2 依赖关系与状态管理多步骤任务的翻车点多技能协作的另一个大坑是状态管理。步骤2依赖步骤1的输出但模型在步骤3的时候可能已经忘记了步骤1的某些细节。解决方案不是指望模型记住而是显式地把上下文传递给下一步技能。我采用技能间通过结构化中间结果传递数据的模式。步骤1的输出不只是一段自然语言而是一个 JSON 对象下游技能直接读取其中的字段。系统 Prompt 中规定所有技能的执行结果必须先整理为结构化的 JSON 数据再进入下游技能。任意两个技能之间禁止用自然语言段落传递关键数据。这一步彻底解决了模型把城市名写在句子里导致下一步提取失败的问题。4.3 什么时候该用子任务拆解什么时候该一步到位有些任务看似复杂其实单技能就能搞定有些任务看似简单却藏着隐性条件依赖。我的判断标准就一条如果这个任务的中间结果需要被多个下游逻辑复用就必须拆如果从头到尾只有一个出口那就合并。举个例子查询天气并推荐穿衣可以是一个技能也可以拆成查天气根据温度给出穿衣建议两个技能。如果后续还要做根据天气推荐出行方式那拆开明显更划算——查询天气的结果可以被多个下游技能复用。反之如果只做一次性回答合并反而更简洁、调用链路更短、响应更快。技能拆分不是越细越好复用性和链路长度之间的平衡才是决定因素。我通常会在初版设计时偏向于拆细等跑通之后再根据实际调用频率合成高频组合这属于动态演进的过程。5. 实操过程全记录从定义到评测一次完整的技能开发闭环5.1 环境准备与最小实现清单做技能开发不需要重型基础设施但下面几样东西是必须的大模型 API 一套支持 Function Calling 或 JSON 输出模式技能定义文件存放目录建议用 Git 管理一个简易的运行时用于接收模型调用请求、执行技能、返回结果测试脚本我习惯用 Python 写一个 pytest 文件对每个技能做冒烟测试最小实现的调用流程是这样的用户消息 → 系统 Prompt 技能定义 → 大模型 → 输出技能调用意图 → 运行时执行对应技能函数 → 返回结构化结果 → 大模型生成最终回答关键点是技能定义文件要随着每次请求动态拼进 Prompt。不要一股脑把所有技能定义都塞进去除非你的技能数量很少否则上下文会被撑爆模型的注意力也会分散。5.2 为模型正确解析技能定义保驾护航这里分享几个我在工程中积累的保命细节。细节一技能描述放在系统 Prompt 中的位置越靠前遵循度越高。我做过对比测试同样的技能定义放在 Prompt 开头部分的调用成功率比放在末尾高约15%。原因可能是模型对前文的注意力权重更高。所以把最重要的技能放在最前面不重要的甚至可以精简。细节二使用分隔符把不同技能的定义隔开。技能定义之间不加分隔符时模型的解析偶尔会混。我用固定格式的分隔符--- 技能模块开始技能名 --- 技能描述内容 --- 技能模块结束 ---这个简单的格式化管理让模型的调用意图识别稳定了很多。细节三裁剪技能数量以降低误召回概率。技能定义总长度有限时模型被干扰的概率更低。我做过一组实验当技能数从20个减少到8个时准确调用率提升了近20个百分点。代价是部分低频技能失去了自动调用的机会解决办法是把低频技能做成按需加载——先让模型决定是否需要该领域技能再把该领域的技能定义追加进去。这种两级召回机制是我的标配操作。代码示例Pythondef build_skill_system_prompt(user_message, all_skills): # 第一步先让模型判断意图匹配哪些技能域 domain_prompt f 用户消息{user_message} 以下是技能域清单{list(all_skills.keys())} 请返回匹配的技能域ID列表JSON数组格式不要调用任何技能。 domains call_llm(domain_prompt, response_formatjson_array) # 第二步只加载匹配域内的具体技能定义 active_skills [] for d in domains: active_skills.extend(all_skills[d]) system_prompt build_system_prompt(active_skills) return system_prompt这个方案既控制住了上下文长度又保证了关键技能的准确命中。实测下来效果很稳。5.3 Prompt 调优实践让模型对系统规则言听计从我对系统 Prompt 的写法要求非常高因为一个模糊的表述就可能让模型跑偏。几个高频踩坑点和优化技巧负面清单必须明确列举。只说不要乱编不够要写严禁编造订单号、物流轨迹、退款金额等任何数据数据必须来自接口返回。每一步决策都需要输出依据。要求模型在输出中附带一句依据字段说明为什么选了某个技能便于排查。对无法处理的情况给出明文处理方式。而不是让模型自作聪明地兜底。所有技能调用尝试都必须在日志中留下痕迹。我会在运行时层记录每次调用请求、响应、耗时、错误方便回溯和调优。下面是一段我在项目里用过的系统 Prompt 片段定义了模型执行技能时的行为准则【技能调用行为准则】 1. 必须在每次技能调用前输出一段调用理由说明当前用户意图与技能触发条件的匹配关系。 2. 所有参数必须严格匹配技能定义中列出的枚举值和格式有歧义时向用户确认或选择最安全的默认值。 3. 技能返回结果必须被结构化暂存作为后续步骤的唯一数据来源。 4. 禁止在技能执行失败时返回虚构数据失败时向用户如实说明错误信息并给出可行的下一步动作。 5. 在一次任务中每个技能至多执行3次执行3次仍失败则终止任务并上报。这些行为准则加上结构化的技能描述组合起来形成了一套模型不容易犯错的约束体系。5.4 评测机制不给技能做体检上线就是灾难我学到的最大教训是任何技能在发布前必须经过评测而不是看起来能用就上。我的评测方案分三层第一层单技能冒烟测试。对每个技能写5~10个测试用例覆盖标准输入、边界输入空字段、超长字符串、非法枚举值、模拟接口异常。目标是验证技能在模型环节是否被正确选召、参数是否合规、输出格式是否稳定。第二层端到端流程测试。模拟真实用户的一整段对话验证多技能协作链路是否顺畅。我特别关注中间步骤的上下文传递是否完整、是否出现重复操作或步骤跳跃。第三层线上灰度评测。把新技能放在一小部分流量中用技能调用成功率、参数合法率、任务完成率、用户重问率四个指标来量化表现。和旧版本做对比不达标就回滚。个人经验评测阶段发现的问题类型和实际线上问题高度一致。每次上线前认真跑一轮三层评测可以过滤掉超过70%的线上事故。6. 常见问题与排查实录我把踩过的坑都列给你6.1 模型不调用该调用的技能现象用户问了一个明显需要技能才能回答的问题模型却直接用自身知识编了个答案。排查步骤确认技能是否已经载入当前会话的 Prompt。动态加载时最容易遗忘。检查技能描述里的触发条件是否写得太隐晦。我建议直接用当用户提到XXX词时这种强绑定的表述。看是不是 Prompt 里存在抑制调用的冲突指令。比如系统 Prompt 说尽量用已有知识回答模型就会倾向于不用技能。尝试把技能描述写得更有行动号召力——描述末尾加上看到这里你应该调用本技能来完成任务。6.2 参数总填错特别是枚举值现象模型填了一个不在枚举列表里的值或者把字符串格式写错。排查步骤检查枚举值是否有歧义或同义词。如果枚举值本身就容易混淆模型选错的概率就会高。在技能描述中增加常见混淆提醒。例如快递公司代码是 SF 而不是 shunfeng 或 SF-Express。提供参数示例模型对示例的模仿能力很强。在运行时层做参数合法性校验非法参数自动回传错误信息让模型自行纠正。这个兜底能救回不少调用。6.3 多步骤任务中断或跳步现象任务进行到一半模型跳过某个必要步骤直接输出结论。排查步骤检查系统 Prompt 中是否定义了必须按顺序执行的流程规则。没有明确顺序约束时模型容易自行简化流程。确认中间步骤的输出没有被下一步技能正确传递。我建议中间步骤必须输出结构化 JSON而不是自然语言。检查模型是否因为某个步骤看起来不重要而省略了它。这时需要在技能描述中强调步骤的必要性比如该步骤用于确认用户身份不可跳过否则后续操作会失败。极端情况下可以考虑用确定性代码限定主流程只把非关键分支交给模型判断。流程主干锁定模型只做分支决策。6.4 常用问题速查表问题现象最可能原因快速解决办法技能未被调用触发条件含糊 / 技能未加载强化触发词检查动态加载逻辑参数填错枚举值有歧义 / 缺少示例增加示例值运行时做参数校验并回传调用报错接口变化或技能定义过期检查技能文件版本和接口适配情况输出格式混乱技能描述未明确输出JSON结构在描述中写死输出 Schema 并配示例多技能跳步流程规则未强调不可省略在系统 Prompt 中加硬性顺序约束模型幻觉数据错误处理策略缺失明确失败时禁止编造数据、必须如实上报上下文过大一次性加载全部技能采用两级动态加载机制6.5 独家避坑技巧最后分享几个不一定写进文档、但实战价值很高的技巧技巧一给技能描述加入反例说明。只写正面描述远远不够模型还是可能误用。我会在描述里追加一小段不要这样做的说明比如不要将退货地址解析为订单地址。加了反例之后误用率能再降一个台阶。技巧二运行时记录调用理由字段。就是之前在行为准则里提到的让模型每次调用前输出理由。这样出了问题你能立刻看到模型的思考链路排查效率翻倍。技巧三多版本 A/B 对比。修改技能描述后不要只做改前改后对比要把改动前后的版本同时挂在灰度流量里对比。因为模型输出有随机性单次对比很容易误判。技巧四把高频组合技能固化为一个新技能。当发现查询天气穿衣建议经常成对出现时就把它封装成一个weather_outfit组合技能。这样既省了一次模型决策环节又减少了中间步骤的失败概率。7. 从技能库到技能资产的进阶路径体系建设与迭代节奏做了一段时间技能开发之后我发现真正的分水岭不是会不会写技能而是能不能把技能管理成一个持续进化、可复用的资产库。具体来说有三个演进方向值得投入。第一个是技能指标的线上化。我会给每个技能挂了三个核心指标调用成功率、参数合法率、平均响应耗时。每周固定跑一次数据看板任何一个指标出现异常就立刻定位。这个习惯帮我提前发现了两个因为第三方接口升级引发的隐性故障。第二个方向是技能编排的可视化。当技能数量超过二十个之后纯靠梳理文字已经很难看清全貌了。我引入了简单的编排图描述文件用代码定义每个技能之间的依赖关系和调用方向再自动生成一张依赖图。这样每次新增或修改技能都能快速看出影响范围不会出现改了一个下游技能导致上游全线崩溃的连锁问题。第三个方向是技能评测用例的持续积累。每遇到一次线上事故我都会把触发事故的输入原样加入评测集。这样一个季度下来评测集的覆盖度就有了显著提升再改技能描述时就能及时发现自己引入了回归。技能不是一次写完就完事的它和业务代码一样需要持续维护、改进、验证。我个人实际操作的体会是把 Agent Skills 当成第一公民来对待而不是顺手写给模型看的一段描述整个项目的稳定性会有一个质的提升。很多团队用最强的模型做 Agent 却依然频繁翻车问题往往就出在技能定义粗糙、编排逻辑松散、评测机制缺失这些看起来不炫酷但决定成败的地方。技能是智能体的肌肉记忆做扎实了模型才能把聪明用对地方。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询