Agent-Skills实战:从工具函数到技能封装,打造真正会干活的智能体

发布时间:2026/10/13 23:24:24
Agent-Skills实战:从工具函数到技能封装,打造真正会干活的智能体 去年底我在做一个内部的智能体项目当时团队对“agent-skills”这个词的理解还非常混乱。有人说是给模型挂一堆工具函数有人说是一套提示词模板还有人直接把它等同于工作流。折腾了两个月踩了不少坑才慢慢摸清楚agent-skills 到底是什么它和工具、提示词、工作流之间的边界在哪里以及真正可落地的一套技能体系应该怎么设计。这篇文章就顺着这条线把我自己的理解、实操过程和踩过的坑一次性说清楚。先说结论agent-skills 是一套让智能体真正“会干活”的能力封装它不是单个工具函数也不是一段固定的 prompt而是把意图理解、参数解析、工具调用、内部逻辑、异常兜底和结果反馈打包在一起的完整闭环。这篇文章适合两类人一类是正在搭建智能体应用但发现自己做的智能体总是“聊得很好、干不了活”的开发者另一类是已经开始用 skill 但感觉效果不稳定的朋友。下面所有内容都以我实际做过的项目为背景方案也是验证过的可以直接照着抄。1. agent-skills 到底在解决什么问题1.1 从“能聊天”到“能干活”差距到底在哪里如果你只让模型回答“今天是几号”“帮我写一段文案”那确实不需要 skills一个对话接口就够了。但一旦涉及“帮我把这批数据清洗后导入系统”“根据昨天的报表生成一份邮件摘要并自动发送”这类多步骤任务问题就来了。最直接的体验是模型经常在关键环节掉链子。它可能知道要调用某个函数但参数传不对可能第一步做对了第二步就开始胡编更常见的是遇到异常情况完全不知道该怎么处理要么卡住要么给用户编一个假的结果。我最初以为这是模型能力不行后来发现根子在于我们只给了模型一堆零散的能力却没有给这些能力一个“技能”层面的组织方式。就像你给一个人工具箱里塞满了扳手、螺丝刀但没告诉他哪把工具对应哪个活儿、干活的顺序是什么、干砸了该怎么办。这人当然干不好活。1.2 skill 的本质把“能力逻辑兜底”打包在我现在的理解里一个 skill 应该具备三样东西能力本身能够执行的操作或计算、使用方式模型或用户需要提供的输入、以及行为边界什么条件下可以用、失败时该怎么反馈。举个例子一个“发送邮件”的 skill最朴素的写法是一个叫send_email的函数接收收件人、主题、正文三个参数。但真正生产级的写法需要更多收件人格式校验、正文敏感词过滤、调用外部邮件接口失败时的重试策略、返回值里带上发送结果和失败原因。这个例子很直观模型拿到的是函数是单一动作智能体需要的是 skill是能承担一个完整任务的最小闭环。1.3 为什么直接写工具函数还不够市面上很多智能体框架都支持自定义工具tool至少形式上支持。但工具给我的感觉是“接口导向”的它告诉模型“这里有个函数可以调用”但对模型来说这个函数只是在某个正确的时机、填对参数才叫“有用”。为了让模型正确调用一个工具你往往需要在系统提示词里写大量解释、给示例、约束边界。而 skill 是在工具之上再做一层组织。它可以包含多个工具的调用顺序、内部状态处理、中间结果的判断甚至可以嵌入一部分业务规则。相当于把“怎么做”的细节藏起来只把“做什么、需要什么、什么时候做”暴露给模型。打个比方工具是字典里的一个词条skill 是一个完整的短语甚至句子。模型不需要知道这个句子里的语法结构它只需要知道在什么场景下用这个句子以及句子里需要填哪些空。2. 构建技能体系前的必备设计粒度、接口与注册机制2.1 skill 的粒度问题一个 skill 该管多大事这是我见过最多的翻车点。很多人建 skill 立两极分化要么建得特别大把整个业务流程塞进一个 skill 里要么建得特别碎一个“读取文件”就建一个 skill最后注册了几百个模型选择起来反而更懵。我自己的经验是skill 的粒度应该等同于“模型的一次有效决策”。也就是说当模型看了用户的需求之后它应该能判断“这个需求可以完全交给某一个 skill 完成”而不是需要组合好几个 skill 才能完成。如果一个任务需要拆成好几个步骤但步骤之间的决策依赖很强、需要临时判断下一步做什么那把它拆成多个 skill 反而更好。因为模型可以在步骤之间进行判断这比在 skill 内部硬编码流程要灵活得多。反之如果步骤完全固定比如“先查天气再根据天气推荐穿衣”那就应该打包成一个“穿衣推荐” skill而不是拆成“查天气”和“推荐穿衣”两个。拆开之后模型可能调用第二个时忘了第一个的结果或者天气查到了却不知道怎么传给推荐函数。2.2 skill 的入口与出口输入输出 schema 是关键我给 skill 设计接口时最核心的原则是参数数量要少参数概念要直白参数约束要清晰。参数数量上能少则少。能用一个复合参数就不要拆成两个平铺参数。以“发送邮件”为例与其拆成to、cc、subject、body、scheduled_time五个参数不如设计成email_message一个对象里面包含主题、正文、收件人、抄送人。模型生成一个嵌套结构远比生成五个平铺字段更不容易出错。参数概念上要避免让模型去“猜业务含义”。比如一个“生成周报”的 skill如果你给模型的参数是aggregated_data模型根本不知道传什么如果你写成work_summary_notes本周工作要点笔记模型即使没有真实数据也可以把会话中提到的内容放进去。输出方面不要只返回一个成功标志。要给模型一个结构化的结果至少包含任务是否完成、执行结果摘要、需要继续处理的信息比如出错原因、缺失参数。这很重要因为模型下一步往往要根据这个结果来决定再调用哪个 skill。2.3 skill 和 tool 的关系组合与分工基于我的实践tool 更贴近“原子操作”比如读文件、调 API、查数据库skill 则是一种“脚本化能力”它既可以直接实现逻辑也可以编排多个 tool。一个反直觉的经验是不在乎用的是框架内置的 tool 还是自定义写死逻辑关键是让 skill 的对外表现稳定。稳定性指的是在同样的输入条件下skill 的输出格式和返回结构要保持一致哪怕是失败失败信息的结构也得统一。这样模型才能学习到规律否则它会因为找不到规律开始随缘调用。2.4 技能注册中心让智能体知道自己有什么在动手写代码之前一定要先设计一个“技能注册中心”。它的作用是统一管理每个 skill 的名称、描述、参数定义和环境要求让智能体运行时能拿到一份“技能列表”来决策。注册中心里我特别重视两个字段description和when_to_use。前者告诉模型这个技能能做什么后者告诉模型什么场景下该用它。很多人写技能描述时喜欢堆关键词比如“邮件、发送、通知、群发”其实模型更需要的是一句场景化描述“当用户需要发送邮件包括单发和批量发送时使用。用户在对话中提到收件人、主题等邮件要素可以使用此技能”。我后来把技能注册中心设计成一个纯 JSON 的清单提交新的 skill 时就加一条记录。好处是技能列表不混在代码里方便排查看也方便给智能体做“能力路由”。3. 实操从零实现一个靠谱的 skill3.1 从目录结构开始每个 skill 都是独立小项目我建议每个 skill 在代码上都是一个独立目录而不是把全部逻辑堆在一个文件里。一个标准的 skill 目录长这样skills/ ├── send_report_email/ │ ├── __init__.py │ ├── skill_meta.json # 注册信息 │ ├── main.py # 技能执行入口 │ ├── validator.py # 参数校验逻辑 │ └── tests/ │ ├── test_happy_path.py │ └── test_failures.py这么做的好处非常直接首先技能的边界清晰不会互相乱引用其次测试可以独立运行而不需要起整个智能体环境最后当某个 skill 出问题时可以快速定位是它自身的 bug 还是外部依赖的问题。3.2 接口定义与参数收敛的示例下面这个例子是模拟项目中的一个 skill“查询订单物流状态”。它的参数被收敛成两个order_ids用户下单选中的订单号列表和user_context当前对话上下文中的用户身份信息。from dataclasses import dataclass, field from typing import List dataclass class LogisticsSkillInput: order_ids: List[str] field(default_factorylist) user_context: dict field(default_factorydict) dataclass class LogisticsSkillResult: success: bool summary: str detail: List[dict] field(default_factorylist) error_type: str error_message: str 我把输入和输出都定义为 dataclass。输入定义参数的结构输出统一为结果对象。这样开发时 IDE 能自动补全测试时也能很方便地构造样例。3.3 内部的防御机制校验、重试、失败反馈skill 的代码虽然不会很长但内部的防御一点不能少。我最常见的问题是模型传参不规范比如order_ids传成了一个字符串而不是列表。这种事在测试时很少遇到一旦到了真实把模型接到运行时天天遇到。所以在入口处我会做一层强制的参数归一化def run_skill(inputs): # 参数归一化 order_ids inputs.get(order_ids) if isinstance(order_ids, str): order_ids [order_ids] if not isinstance(order_ids, list) or len(order_ids) 0: return LogisticsSkillResult( successFalse, summary订单号缺失或格式不正确, error_typePARAM_ERROR, error_messageorder_ids must be a non-empty list, ) # 业务逻辑...重试逻辑也比较讲究。有一次调用物流查询接口时第三方接口偶发 5xx最开始没加重试结果模型看到失败反馈后自己编了一个“订单已签收”的回复这非常危险。后来我在所有可能临时出错的环节都加了一轮重试最多两次间隔 500 毫秒。重试仍失败就返回明确的错误码让模型如实告诉用户接口暂不可用。3.4 把 skill 暴露给模型描述怎么写注册信息里的描述直接决定模型在什么时机调用这个 skill。写描述有两条硬要求第一不能夸大能力不能把只能查物流说成“还能预测送达时间”第二要把输入要求写清楚比如“用户需要提供完整的订单号列表”。我的经验是写描述时多写“不适用”的场景比多写“适用”场景更管用。比如这么写“当用户询问多个订单的物流轨迹时使用。仅支持查询已下单的订单状态不支持下单、修改地址、申请退款等操作。若用户没有提供订单号请先向用户索要订单号。”这里面的关键是最后一句“若用户没有提供订单号请先向用户索要订单号”。有了这句模型在参数不全时就不会硬填一个假订单号而是会主动追问用户。我之前在这个细节上栽过几次跟头后来把参数缺失时的引导话术写进描述里问题直接少了一大半。3.5 联调与自测别只测 happy path这部分我会启动一个模拟对话环境用户发一段请求观察模型是否选对了 skill、参数是否正确、结果是否传达清楚。除了开心路径我专门准备了一批刁钻输入用户口述的订单号是中文数字“一二三号订单”用户同时问了订单状态和售后入口涉及两个 skill 的决策用户要求查询一个根本不存在的订单号技能接口超时并返回 5xx观察模型是否如实说明。这些用例能暴露很多提示词和注册信息的问题。我甚至有一个暴力的测试方式故意写错 skill 描述里的一个关键词跑一遍看模型的行为会发生什么变化。这个方法很费时间但对理解模型与 skill 的交互非常有帮助。4. 常见问题与排查技巧实录4.1 模型总是不调用该调用的 skill 怎么办现象用户需求明确描述也写得清清楚楚但模型就是不走 skill而是自己凭常识回答。这种情况我排查三步走。第一步检查是不是别的高优先级指令干扰了。有些项目的系统提示词里写了“你是一位无所不能的助手”模型觉得自己什么都会自然不会看技能描述。把系统提示词往收敛方向改会好很多。第二步检查 skill 描述是否“任务导向”。描述里写“这是物流查询模块”效果很差改成“当用户需要查询订单的物流轨迹时必须使用该模块”效果立竿见影。第三步检查注册列表里是否有相似技能。如果一个“订单详情查询”和一个“物流轨迹查询”同时存在模型很容易混淆。这属于技能矩阵设计问题建议合并或者写清楚二者的差异边界。4.2 参数传得乱七八糟模型不按 schema 来我在某个项目里遇到了一个特别离谱的现象模型把整个用户输入原封不动地塞给了唯一的参数。比如我把参数定义成order_ids模型直接传“请查询订单号 123 和 456 的物流信息”这一整句。后来发现问题出在我给的参数描述不够“原子化”。我在参数描述里只写了“订单号列表”没有说明“这是一个纯数据字段不要包含任何自然语言”。后来我把参数描述全都改成“该字段只接受订单号数据禁止混入描述性文本、标点符号或疑问句”情况立刻好转。另外尽量用明确的枚举类型或对象结构而不要用自由字符串。比如状态字段给模型选项而不是让它自己发挥{ name: query_status, type: string, enum: [pending, shipped, delivered, failed], description: 用户想要查询的物流状态节点 }模型在枚举约束下出错率明显低于自由文本。4.3 skill 内部出错模型开始胡编结果这是最可怕的一种情况。某个 skill 返回了{success: false, error_message: 服务超时}但模型给用户的回复是“您的订单已派送预计明天到达”。原因我后来想明白了技能返回的错误信息不够“解释性”。模型看到success是 false但知道下一步该怎么办。这时候必须返回一个可供模型直接转述给用户的消息。就刚刚那个场景我改成在summary字段里直接返回“物流接口暂时不可用建议用户稍后再试或拨打人工客服电话咨询。”模型看到这句就不会自己编了。原则是skill 的失败信息要写成可以直接给用户看的句子而不是给程序看的错误码。错误码可以附在另一个字段里但summary必须是可转述的自然语言。4.4 提示词里技能文档太长上下文放不下技能多了之后全部描述塞进提示词里占的上下文会非常可观。我遇到过智能体上下文明显变笨经常忘事排查后才发现是技能描述占了将近一半的上下文窗口。解决思路有两个一是浓缩描述二是动态加载描述。浓缩描述就是在注册中心里只保留最核心的一句话更多细节放到一个“技能详情文档”里只有当模型选择调用该技能时才把详情文档塞进上下文。动态加载类似于路由实际上是先用一句话粗筛再展开详细说明。这个策略在我自己的项目里省出了大约 40% 的上下文空间。4.5 安全问题skill 越权访问数据之前我忽略了一个问题skill 一旦能被模型自由调用它的入口就相当于暴露给了模型。如果输入里带了一些不该给它的敏感信息比如用户身份凭据模型可能会把这些内容作为普通参数传给 skill。后来我给 skill 加了一层访问策略只有特定场景才允许访问用户敏感数据并且敏感字段不会直接出现在技能上下文中。同时skill 的日志里会对敏感信息做脱敏处理。提示一个更隐蔽的坑skill 的输出会被模型看到后再生成回复所以如果 skill 从外部接口拉到的数据包含用户隐私这些数据也会进入模型上下文。在设计时要确认哪些信息逐字透出、哪些信息只给一个结果摘要。5. 技能库的演进与维护做一次能长期用的设计5.1 技能复用先沉淀“通用能力”再长“业务技能”我曾经为了赶进度把业务逻辑写死在技能里比如直接在“查询物流”技能里连了某个商家后台的数据库。后来另一个项目也要查物流但因为业务数据源不同只能复制一份逻辑改改配置再上。这既浪费了代码也增加了后期的维护成本。更合理的方式是把“连接物流系统并查询轨迹”沉淀为一个底层工具把“将用户需求转化为查询参数”做成 skill。这样不同业务的技能可以复用同一个底层工具。技能负责理解用户工具负责对接系统各管一头。5.2 技能版本迭代改一个描述也可能影响全局技能的描述不是改完就完。我遇到过这样一个事更新了一个技能描述说要加上“支持批量查询”的说明结果原本正常走单查询请求的用户也开始被模型引导去做批量查询而批量查询的性能根本扛不住。一个小改动就能改变模型的调用习惯所以凡是涉及描述、参数、触发场景的改动我都建议在独立环境上跑一遍回归测试再上线。5.3 建立一套轻量的评估集说到评估不要一开始就追求复杂指标。我建了一个非常简单的 JSON 文件作为评估集里面塞了三十条用户请求每一条都已经标注了“期望调用的技能名称”和“期望参数值”。每次改完代码跑一遍这个评估集看看有几条正确命中。这样技能库改成什么样心里有数。后来我把它接入了开发流程只要 skill 代码有变更就自动跑一遍避免上一次改动把以前的逻辑搞坏了。这个评估集维护起来也不算很费劲看到新出现的错误样例就补充进去就好。半年下来已经有几百条覆盖率比人工反复点测试高出不少。6. 我对 agent-skills 的几点个人体会这套体系做完之后最大的感受是agent-skills 不是模型能力而是架构能力。模型本身就那一个技能库设计得好不好、描述写得清不清楚、边界划得明不明朗基本决定了一个智能体是“好用”还是“鸡肋”。在实际操作中我发现建模 skill 的时候多花时间在参数设计和描述上是最值的。那些细节不看几个真实项目很容易被忽略。比如一个“查询物流”的技能八十行逻辑没什么难点但“参数里不要混自然语言”这七个字比一整段业务代码更关键。还有一点切身的体会别太迷信“智能体自己会编排”。至少在我做过的实际项目里让模型在多个 skill 之间做自由组合很考验框架设计和提示词设计。对大部分生产需求开发一个覆盖面合适的 skill 目录让模型只做“选哪个技能”的决策而不是“怎么组合技能”的设计可靠性要高很多。最后分享一个小技巧每做完一个 skill花十五分钟写一段“我上回在这个技能上翻过什么车”的备注放在目录的 README 里。技能多了之后人一定会忘但这个备注会成为排查问题时最快的线索来源。这也是我目前所有技能目录里最被团队其他人看重的文档。

关于本文作者

来自尧图内容编辑团队

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

尧图内容编辑团队

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

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

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

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

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

网站改版的5个关键决策

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

获取专属建站方案

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

立即免费咨询