从Function Calling到Agent Skills:大模型工具调用的设计范式与工程实践
2026/9/16 22:11:25 网站建设 项目流程

1. 从Function Calling到Agent Skills:为什么我突然开始重新思考Agent的工具设计

1.1 大多数人切入Agent开发时的第一反应

做AI Agent开发的同行应该都有一个共同的经历:第一次把大模型接上外部工具时,第一反应就是“这不就是Function Calling吗”。定义一个JSON Schema,声明几个参数,模型就会在合适的时机把调用意图和参数返回给我,然后我执行函数、把结果塞回对话上下文,一个Agent工具链路就通了。早期我也是这么干的,也确实能跑通一些简单场景,比如查询天气、算个加减法、拉个订单状态。

但跑着跑着就发现不对劲。等到技能数量超过五六个、场景从演示变成生产,整个系统的脆弱程度简直让人头皮发麻。参数传错、模型拿不到关键信息、返回结构不匹配、上下文被日志撑爆、多轮对话里技能状态错乱……这些问题不是偶发,而是结构性必现。也就是从这个时候起,我开始认真研究“Agent Skills”这个概念——它不是Function Calling换个名字,而是一整套关于“如何让大模型可靠地使用能力”的设计范式。

1.2 我理解的Agent Skills到底是什么

如果非要用一句话定义,我会说:Agent Skills是一套“以模型认知习惯为中心”的能力封装方案,它把完成某类任务的完整知识、操作步骤、输入输出规范和边界条件打包成一个独立、可复用、可被模型自主调用的模块。

这个定义里最关键的是“以模型认知习惯为中心”这半句。传统软件开发是给人用的,接口设计只要人能看懂就行;但Agent Skills是给模型用的,接口设计必须符合大模型对任务的理解方式。你定义一个严格结构化的入参对象,模型反而容易搞错;你给它一段自然语言描述加上示例,它反而处理得非常好。这套方案的提出背景,本质上是把设计视角从“开发者好写”切换到“模型好用”。

这里我拿真实场景做个对比,你会发现差别非常明显:

维度Function Calling思路Agent Skills思路
接口形态JSON Schema强制结构自然语言描述为主,结构为辅
工具定位单点函数,越原子越好完整技能包,可以做多步推理
调用决策模型根据函数名和描述选择模型根据技能的目标、流程、样例综合判断
失败处理靠外部代码兜底技能内部自带各种边界条件说明
扩展方式加函数、改Schema加技能包、升级技能版本

1.3 为什么现在这个时间点特别适合重看Agent Skills

大模型本身的推理能力在过去一年提升很快,但工具调用的可靠性其实提升得没那么明显。这不是模型不行,而是端到端的Agent任务里,工具设计往往成为瓶颈。模型明明有能力做三步推理,但是你的工具只支持一步调用,那就只能靠外部代码来编排;外部编排越多,系统就越脆,一旦场景变化就要改代码。

Agent Skills刚好补上了这一环。它把“属于模型应该做的事情”交还给模型,同时用结构化的技能描述让模型在调用时更自信、更准确。加上像Anthropic发布Agent Skills规范这类行业动作,整个生态正在从“再造一个Function Calling”走向“形成一套可共享、可复用的技能资产体系”。这个趋势本质上和前端从“写页面”到“组件化”再到“组件市场”的发展路径非常像。


2. 我踩过的最深的坑:Function Calling的方式构建Agent,越做越脆

2.1 第一个坑:参数地狱与必填项的魔咒

Function Calling体系中最大的噩梦就是参数设计。你为了一个“查订单”的功能,可能会定义order_id、customer_name、date_range、status、page_size、sort_by……十几个字段,然后一大半都是可选的。可选的还好,最怕的是必填项太多。模型拿着用户一句模糊的“帮我看下上周的订单”,面对五个必填参数,它不是去追问,而是会根据自己的猜测给你填一堆五七八八的值进来。

我实际遇到过一次用户说“查一下老客户的复购情况”,模型给customer_name填了“老客户”,给date_range填了“2024-01-01到2024-12-31”。字段类型没错,语义完全跑偏,最后查出来的结果当然也是无意义的。这个问题本质上不是模型的错,而是我们把一个“开放式理解任务”强行塞进了“封闭式参数结构”里,系统自然要出问题。

2.2 第二个坑:链式调用时,中间状态的丢失

做稍微复杂一点的Agent任务,往往需要多个工具按顺序配合。比如“给客户写一封促销邮件,然后发给近30天有购买记录的用户”,这需要先调用户筛选工具、再调邮件模板工具、再调发送工具。如果用Function Calling方式实现,每一步的结果都得想办法传给下一步,模型的上下文窗口里堆满了中间数据。

藏得最深的坑在这里:一旦某一步返回的数据结构比较大,比如几千个用户的列表,模型在下一步决策时根本读不完这些数据,注意力会被无关字段稀释掉。经常出现的情况是,模型明明拿了用户列表,写邮件时却忘了用户群体是谁,逻辑完全断掉。而Agent Skills的方式把整套流程封装成一个技能,模型的注意力只需要放在“最终目标”上,中间的数据流转由技能内部自己消化,问题就从根源上消失了。

2.3 第三个坑:技能越多,选择越混乱

函数数量在30个以内时,模型的选择准确率还算能接受。但一旦超过50个,情况就急剧恶化。模型开始混淆相似功能之间的边界,比如“发送通知”和“发送营销邮件”在描述中长得差不多,它就经常选错。你在提示词里怎么强调都不管用,因为这不是提示词质量问题,而是信息架构问题。

我后来反思,Function Calling的设计思路是“把尽可能多的能力暴露给模型”,这条路对模型的工作记忆是极不友好的。Agent Skills的思路则是“把相关能力聚合成块”,模型面对的不是50个函数,而是七八个技能,每个技能内部再去决定具体怎么执行。选择维度从50个掉到8个,模型的准确率自然就上来了。


3. 重新设计一个Agent Skill,从目标拆解到完整落地

3.1 核心原则:先定义边界,再写实现

一个合格的技能,不是写完功能就算完。它需要包含六个组成部分,缺一个到生产环境都会出问题。我把这六部分列成一个检查清单,每次新写技能都会逐项过一遍:

组成部分关键内容缺了会怎样
技能目标这个技能要达成的最终效果模型不知道什么时候该用它
运行条件什么情况下允许执行、什么情况下应该拒绝模型在不符合条件时也乱调
输入输出规范需要哪些信息,返回什么格式链式调用时数据对接不上
操作步骤内部执行流程,支持多步推理只能做一把梭式的单步操作
知识库领域专业知识、规则、话术输出结果停留在表面
边界与异常失败场景、超时处理、兜底策略出问题时整个会话直接卡死

边界这一项尤其重要。很多开发者觉得“先跑通核心流程就行”,边界条件后面再补。但模型的调用决策高度依赖边界描述,如果没有明确写“哪些情况下不能用”,模型就会把它用在所有看起来沾边的地方,出了错还不自知。

3.2 自然语言优先的输入输出设计

设计技能时要尽量让输入输出贴近自然语言,减少结构化参数的依赖。一个反直觉但非常有效的方法是:让模型用自己的话描述目标,而不是填充一个对象。

举个例子,假设我们要做一个“销售日报生成”技能。Function Calling思路下可能会定义:

{ "type": "object", "properties": { "report_date": { "type": "string", "description": "报表日期" }, "metrics": { "type": "array", "items": { "type": "string" } }, "include_charts": { "type": "boolean" } } }

Agent Skills思路下会改成:技能接收一段自然语言任务描述,比如“生成昨天的销售日报,包括收入、订单量和退款率,最好附带趋势对比”,然后技能内部用另一个模型调用或规则引擎去解析这个描述,拆出关键要执行的动作。

这样做的好处非常明显:用户和模型都只需要表达意图,而不需要学习接口。很多非技术用户说出来的话根本不可能贴合JSON字段,与其让模型做一次“人话翻译成严格结构”的任务,不如让整个调用过程都保持自然语言的一致性。

3.3 Skill内部的状态管理与自包含设计

优秀的技能必须做到自包含。所谓自包含,就是技能的整个生命周期——从输入到执行到返回——都由技能自身管理,不依赖外部系统的临时状态。这意味着技能内部要有自己的状态表达方式、任务队列和存储路径。

比如做“周期性数据分析”技能,它不是简单调一个查询接口,而是自己在内部维护“本次分析的输入快照”“执行过程中的中间结果”“最终产出的汇总报告”三个阶段。这样即使主对话经历了多轮交互,技能的状态也是完整的。我在工程实践中发现,把技能状态从对话上下文中剥离出去,是整个Agent系统从“demo”走向“可用”的关键一步,这也是Agent Skills框架和Function Calling最底层的区别之一。


4. 一个真实可跑的技能实现:自定义一个“订单归因分析”Skill

4.1 技能的目标与输入输出定义

光讲理论太空,我直接拿一个线上在跑的例子拆给大家看。我做过一个“订单归因分析”技能,它的核心任务是:根据用户的一个粗略诉求,自动圈定订单范围、分析数据、找出规律并生成结论。假定场景是运营人员在后台对话里问“端午节促销期的订单哪类商品贡献最大”,传统方式需要他手写SQL、联表、算占比、再写PPT,现在他只需要把这个需求作为一条消息发给Agent就行。

技能的输入只有一条自然语言诉求,输出也不是一个JSON对象,而是一段结构化分析报告,包含数据范围、分析方法、核心结论和原始数据明细四个部分。这里的设计思路是:输出要既适合人看,也适合后续链路继续消费。模型拿这段报告再做下一步决策,就不会缺上下文。

4.2 技能内的核心执行逻辑

这个技能内部其实跑了一条4步流水线,但对外就像黑盒一样干净透明:

  • 第一步,意图解析:模型基于用户的自然语言诉求,提取时间范围、维度字段、指标字段。比如“端午节促销期”会被解析成一个具体日期区间,“哪类商品”会被映射到商品类目维度。
  • 第二步,数据探查:技能自动调用数据仓库的元数据接口,看看目标表和字段是否存在、是否有数据、是否有重名歧义。这一步是防止后端出错的第一道防线。
  • 第三步,查询生成与执行:根据前两步信息生成查询语句,执行后拿到结果集,同时记录执行日志和质量指标,比如数据量大小、查询耗时。
  • 第四步,结果归纳:把数据结果交给大模型进行归因分析,生成一段人话结论,然后再拼装成最终报告返回。

这四步全部封装在一个技能里,不依赖外部编排脚本。模型端调用和代码端调用这个技能时面对的是同一个接口,只是入口有所不同。

4.3 技能描述文件:让模型知道“什么时候用我”

如果说技能实现是引擎,那技能描述文件就是方向盘。模型判断“要不要用这个技能”“怎么用”,全部依赖描述文件的内容质量。我用的技能描述模板一般包含这几个字段:

  • name,技能的唯一标识
  • description,讲清楚这个技能用来解决什么问题,不要含糊
  • instructions,被模型作为系统提示词注入的具体说明,写清楚什么时候允许调用、什么时候应该拒绝
  • input_schema,尽量宽松的自然语言字段描述
  • examples,2到3个典型调用示例,包含用户提问和技能正常执行后的效果

描述文件里最容易翻车的是一句话概括。比如“用于订单分析”这种写法,模型会把所有和订单沾边的需求都路由过来,最后技能被高频错误使用。好的描述应该是:

这个技能用于“回答任何与订单数据归因、趋势、构成相关的问题”。当用户想了解某个时间段的销售表现、哪个商品卖得好、哪些用户贡献大,或者需要解释数据变化的原因时,应该使用本技能。但如果是同步订单状态这种单行查询,应该调用订单详情技能,而不是本技能。

这种写法直接把技能的适用范围、典型时机和排除场景都说清楚了,模型做路由决策时就有据可依,而不是瞎猜。


5. 技能跑通之后的事:关于可靠性、并发与迭代,我不太想回避的一些现实问题

5.1 模型的指令遵循比你想的更“看心情”

即便你把技能描述写得很完善,模型依然有概率不按你规定的路径走。我统计过线上数据,单次技能调用时模型“跑偏”的概率大约在3%到8%之间,具体高低取决于任务复杂度。在To B场景下,这个概率是不能接受的。

我目前的应对策略不是去微调模型,而是做一层“技能执行护栏”,就是在技能内部对模型生成的每一步做一次规则校验。比如归因分析技能里有一个子步骤是“判断查询条件有没有包含时间范围”,如果模型漏掉了,规则层会拦截并自动补上。形象地说,就是把模型的每一次执行当成“一个聪明的实习生”,而规则层是“审核文档的老员工”,模型可以提方案,但最终执行必须过一遍审核。

5.2 技能并发与资源隔离,容易被忽视但会炸

技能和函数不同,它不是一毫秒就能返回的。一个数据分析技能通常要跑几百毫秒到几秒,期间如果请求量上来,资源会发生明显竞争。多个技能同时跑的时候,如果都去查同一个数据源,数据库连接池直接被打满,接口报错率直线上升。

做技能化改造之后,我引入了一个比较简单的并发控制方案:每个技能在注册时可以声明自己的资源等级和预期的最大并发数,系统根据这些数据做排队。比如简单技能最多同时运行20个,重技能最多同时运行3个,超过的请求先进入队列。实测下来系统的稳定性改善非常明显,可用性从最开始99.3%提升到99.8%,别小看这0.5%,对To B业务的体验影响非常大。

5.3 技能版本迭代时,如何不打断线上业务流程

技能只要是代码,就会面临迭代。Agent Skills的独特之处在于,它不像普通API那样有明确的版本管理方案。你更新了一个技能描述,模型在上下文里看到的还是旧描述,因为你没有做好版本对齐。

我的做法是给每个技能加metadata,记录版本号、发布时间和变更说明,并在每次新会话初始化的时候让Agent主动拉取全量技能的最新描述。长期存活的会话则要做“技能热更新”的兜底,即判断当前会话中的技能版本与新版本是否兼容,不兼容的会话要做标记并提示用户开启新会话,避免旧会话一直拿旧技能干活。


6. 从单个技能到技能系统:后续演进时最值得投入的方向

6.1 先建立企业级技能库,而不是继续堆技能

技能数量上来之后,你一定会遇到复用、检索和治理的问题。不能靠每个团队各自维护自己的技能逻辑,那样同一种能力会被重复开发,实现还不一样,模型无法做统一决策。

我觉得比较值得投入的方向是建一套中心化技能仓库,内部包含三样东西:标准技能声明、示例库、质量评估记录。任何一个技能上线前都要过一遍“三个人”的评审——负责实现的工程师、负责模型效果的算法同学、负责业务效果的产品经理。签名通过之后编入仓库,可被全公司的Agent统一检索和引用。

6.2 从“单技能调用”迈向“技能编排”

当前大多数Agent系统还是单技能调用为主,也就是一次对话,模型决定调用哪一个技能。但当业务复杂到一定程度,你会发现很多真实任务天然是多个技能协作的,比如“看完这份报表,然后把异常项提供给风险组跟进”,这就同时涉及数据分析、文本理解和消息触达三类技能。

下一阶段的Agent Skills重点一定是在技能编排上。好比是给技能之间加了一种“会话式接口”,不仅输出结果给用户看,还要输出它的结论和下一步建议,让下一个技能可以根据建议决定自己要不要参与、怎么参与。这个思路目前还在演进中,但我认为它代表了Agent从“工具人”走向“协作者”的核心跳板。

6.3 把评估体系前置,别等上线了再补

技能越做越多之后,回退成了最难受的事:你优化了A技能的描述,结果B技能在路由选择上变差了。没有评估体系,你根本不知道是哪次调整引入了问题。

我现在的做法是搭一个“回归集”,每个技能底下挂了30到50条典型历史请求和对应期望结果,每修改一次技能就跑一遍全量回归。跑过之后看三个指标:技能路由准确率、执行成功率、结果可用率。这三个指标稳定或提升,改动才允许合入。这一点经验是从后端测试工程里借来的,但实际效果非常好,大大减少了我半夜被线上用户@的尴尬时刻。


最后再分享一个我个人感触最深的体会:Agent Skills的真正价值,不是让你把现有工具的调用变简单,而是逼着你重新思考“模型适合做什么、系统该扛什么”。Function Calling时代,我们习惯了把所有逻辑往外部代码堆,结果系统越做越重、越做越脆;Agent Skills的思路则是让模型在前面冲锋,系统在后面兜底。

我手上这套以技能为中心的Agent架构已经跑了近半年,线上承担了订单归因、客户分级、营销复盘等十多个真实业务场景,整体稳定性和可维护性比原先Function Calling方案提升了一个量级。后续我还会继续往技能编排和质量评估两个方向深挖,尤其是多个技能协作时的上下文传递,等有了更成熟的实践,再回来和大家分享。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询