☰
Agent Skills实战:从模型能力到技能仓库的工程化设计
2026/10/8 11:17:53 网站建设 项目流程

业界这两年聊 Agent,聊到最后都会落到一个词上:agent-skills。模型本身越来越聪明,但真正把 Agent 从"demo 里很能打"推向"生产环境真能用"的,恰恰是这一层平时不太容易被注意到的技能体系。我也踩了不少坑,从最初的暴力 prompt 堆砌,到后来老老实实做技能仓库的设计,中间的过程值得拿出来聊聊。

如果你正准备搭一个 AI Agent,或者你已经在做了但总觉得效果不稳定、任务一复杂就翻车,这篇文章会适合你。我会从"为什么光有模型不够"讲起,拆解技能到底包含哪些层面,再给出一套可以直接落地的技能仓库设计思路,最后分享几个真实踩坑案例和排查方法。

1. "agent-skills"不是模型能力,是模型的手脚

先澄清一个容易混淆的概念:很多人觉得 Agent 的能力上限取决于背后的 LLM,模型强则 Agent 强。这话对了一半。模型负责的是"脑",但 Agent 要完成真实任务,还需要"手"和"脚"——而 agent-skills 就是这套手脚。

1.1 一个反直觉的实验结果

我做过一个对比实验:同一个模型(当时是 GPT-4 级别的 API),配了两套不同的技能方案去处理同一个任务——整理一份竞品分析报告。

第一套方案,我只在系统提示词里写"你是一个资深市场分析师",给了大量关于报告结构、分析框架、写作风格的指令。结果模型确实写出了一篇结构完整的报告,但里面的数据全部是编的,时效性为零,行业动态靠的是训练数据里的旧知识。

第二套方案,我给它注册了四个技能:web_search、web_fetch、extract_table、markdown_render。模型在生成报告之前,自动调用了搜索技能去拉最新资讯,再用抓取技能打开几个具体网页,提取表格数据,最后整理成报告输出。同一颗"大脑",产出质量天差地别。

这就是 agent-skills 的核心价值:它决定了模型能不能把"思考"变成"行动",把"知识"变成"结果"。

1.2 技能的三个层次:工具、流程、判断

在实际工程里,我习惯把 agent-skills 拆成三个层面来理解:

工具层(Tool Layer):这是最基础的一层。模型通过外部工具与真实世界交互,比如搜索引擎、数据库查询、API 调用、文件读写、代码执行。工具层解决的是"模型会想但不会做"的问题。

流程层(Workflow Layer):单个工具能做的事情有限,真实任务往往需要多个步骤。流程层把若干工具调用编排成一个完整流程,比如"搜索 → 抓取 → 提取 → 总结"就是一个最小的可复用流程。这一层解决的是"单步会做但多步不会串"的问题。

判断层(Judgment Layer):这一层最容易被忽略,却最影响体验。它负责决定"什么时候该调用工具、该调用哪个工具、怎么根据工具返回结果调整下一步计划"。我见过很多 Agent 死在判断层——明明有计算器这个技能,它偏要心算;明明有搜索技能,它偏要凭记忆瞎编。判断层的本质是决策逻辑,它决定了技能能不能被正确使用。

理解这三个层次,后面的技能仓库设计才有抓手。

2. 大规模使用前的关键一步:把技能当作产品来设计

单个技能能力有限,给 Agent 配几十个技能做真实业务的时候,技能本身就需要当作产品来设计。这不是简单地把函数注册进列表,而是要对技能做拆分、边界定义和体验打磨。我在这块走过弯路,最初只是把一堆函数一股脑堆给模型,结果效果一塌糊涂。

2.1 技能的单一职责与命名规范

给 Agent 设计技能,一个特别容易忽略的原则是:技能要小而专,命名要有语义。

举个例子,我曾经设计过一个大而全的process_data技能,把数据清洗、格式转换、统计分析全塞进一个函数,参数多达十几个。模型调用的时候经常搞错参数,而且因为一个函数干太多事,返回结果的格式也很难统一。

后来我把它拆成了clean_csv_data、convert_json_to_table、compute_statistics这三个独立技能,每个技能参数不超过四个,返回格式明确。模型的选择准确率立刻上来了。原因也简单:LLM 在工具选择时,需要根据技能的名字和描述做语义匹配。大而全的技能名含糊,描述含糊,模型就拿不准该不该用、怎么用。

命名规范这条,我现在执行得很严格:动词开头 + 明确对象 + 可选场景标签,例如search_wiki、send_slack_message、deploy_docker_service。描述统一用"当用户需要 XXX 时,使用该技能完成 YYY,返回 ZZZ"的句式。

2.2 技能之间的边界与上下文传递

真实业务中技能之间经常需要协作。比如数据处理流程里,fetch_data的结果要传给clean_data,再传给analyze_data。这里的关键问题是:技能之间的数据通过什么来传递?

我用过两种方式,各有优劣:

管线式传递:每个技能的输出直接作为下一个技能的输入,参数在调用链中传递。这种方式效率高,但链路长了以后,中间某一步出错会导致整个链路断裂,且很难排查。

黑板式传递(Blackboard Pattern):每个技能把结果写入一个共享的上下文存储区,后续技能按需读取。这种方式灵活,但要求设计好存储区的数据格式和访问权限,而且模型对数据的理解成本更高。

我自己的经验是:在 Agent 场景里,混合方案最舒服。短链路的固定流程用管线式,涉及"多技能可选、多路径尝试"的复杂流程用黑板式。关键是把中间数据统一成结构化格式,比如标准 JSON,并明确标注数据来源技能与生产时间,方便后续步骤追溯。

2.3 技能的可观测性是保底项

技能调用不像代码函数调用,出了问题你很难一眼看出来。所以设计技能时,可观测性必须前置,而不是事后补。

我现在每个技能在被调用时,会自动记录三类信息:

  • 输入摘要:模型传入了什么参数,是否涉及敏感数据。
  • 执行状态:成功、失败、超时,失败的具体原因。
  • 输出摘要:返回结果的长度、类型、关键字段。

这些日志会汇总到统一的追踪面板。有一次线上 Agent 频繁报错,我看着追踪面板发现web_fetch技能经常超时,但 Agent 在超时后重新调用的不是同一个技能,而是换了一个不合适的替代技能,导致结果质量下降。没有日志面板,这种问题很难快速定位。

3. 一套可直接上手的技能仓库工程结构

技能多了之后,就不能再零散地在代码里堆函数了。我推荐用仓库化的方式管理技能,类似前端组件仓库的思路。下面这套结构我跑了大半年,比较稳定。

3.1 技能仓库根目录结构

我现在的技能仓库大概是这样的:

skills/ ├── registry/ # 技能注册中心 │ ├── index.json # 所有技能的注册索引 │ └── categories.yaml # 技能分类及权限标签 ├── core/ # 核心通用技能 │ ├── web_search/ # 一个技能一个目录 │ │ ├── skill.py │ │ ├── schema.json │ │ ├── description.md │ │ └── tests/ │ ├── web_fetch/ │ └── data_extract/ ├── domain/ # 业务领域技能 │ ├── competitive/ │ ├── finance_report/ │ └── customer_service/ └── shared/ # 共享工具、上下文存储、日志模块 ├── context_store.py └── observability.py

每个技能目录下必须有schema.json和description.md,前者给模型看(决定能否正确调用),后者给开发者看(方便维护与审计)。这种"双文档"分离其实挺重要——给模型看的说明要精简直接,给开发者看的说明要详细完整,两者不能混在一起。

3.2 schema.json 的写法要点

schema.json本质上是给 LLM 看的函数签名。这里我吃过不少亏,总结几个关键点。

第一,参数描述必须写"人话",不能只写类型。比如:

{ "name": "web_search", "description": "搜索互联网获取最新信息。当用户询问实时数据、最新动态或需要验证事实时使用。", "parameters": { "type": "object", "properties": { "query": { "type": "string", "description": "搜索关键词,建议使用具体名词和短语而非自然语言长句" }, "max_results": { "type": "integer", "description": "返回的搜索结果数量,默认5,最大10" } }, "required": ["query"] } }

注意description里的"当用户询问实时数据..."这句,这不是废话。它给模型提供了技能调用的决策依据,从语义上告诉模型"什么场景用我"。很多 Agent 该用工具而不用工具,就是因为技能描述里只写了功能,没写适用场景。

第二,参数的取值范围和默认值必须写清楚。模型是概率系统,你不限定范围,它就自由发挥。上面的max_results我明确写了"默认5,最大10",模型在不确定时就会倾向使用默认值,而不是传一个奇怪的数字。

第三,required 数组要精简。只有真正必须的参数才放进required,可选参数全部放到properties里并写明选填与默认行为。这能显著降低模型因参数缺失而报错的概率。

3.3 description.md 别写成论文给模型看

很多人在写技能描述的时候,恨不得把函数的内部实现都写进去。我建议千万别这样。模型消费的描述文本会占用上下文窗口,描述越冗长,模型做决策时的信噪比越低。

我的一贯做法是,description.md控制在两百字以内,包含四块内容:

  • 技能一句话定位(它能干什么)。
  • 典型使用场景(什么时候该用它)。
  • 边界声明(什么时候不该用它)。
  • 与相似技能的区别(避免模型选错)。

举个例子:

# web_search 技能描述 定位:通过搜索引擎获取互联网最新信息,覆盖新闻、文档、数据页面。 典型场景:用户询问最新新闻、行业动态、数据验证、时效性信息。 边界:无法访问需要登录的页面,无法解析纯 JavaScript 渲染的内容。 区别:与 web_fetch 配合使用——search 负责找线索,fetch 负责抓内容。

这段描述既能让模型快速理解技能定位,也能避免它把web_search和web_fetch搞混。

3.4 版本的隐性坑

技能本身就是程序代码,必然面临迭代。但技能版本管理有个独特问题:Agent 在运行时是动态选技能的,你更新了某个技能,正在执行的会话任务可能依然在使用旧版本逻辑。

我的解决办法是给技能加版本号,并且在调用时显式记录版本。在 index.json 中:

{ "skills": [ { "name": "web_search", "version": "2.3.0", "entry": "core/web_search/", "enabled": true, "tags": ["search", "web", "core"], "permission": "standard" } ] }

当模型调用技能,日志会留下版本信息。一旦新版技能引入问题,我可以快速回退到上一个稳定版本,同时批量回放受影响的会话,看哪些任务被污染了。不夸张地说,这个设计帮我避免过好几次线上故障。

4. 踩坑实录:Agent 明明"会"技能,为何就是"不用"?

给 Agent 配了一套技能之后,你会发现一个让人抓狂的现象:模型在有的场景下宁可自己瞎编,也不调用你精心准备的工具。我在这个坑里蹲了很长时间,最终定位出四个高频根因,而且这四个原因每个都有对应的排查手法。

4.1 根因一:技能名和自然语言习惯不符

第一个项目里,我管"发送邮件"的技能叫email_sender_v2_fast。模型在需要发邮件时,经常绕开这个技能,直接写"我已经通过邮件发送了"——它根本没找到这个技能。

问题出在技能名需要承载语义索引的功能。太长的名字、含版本号的名字、非动宾结构的名字,在模型做 tool selection 时都容易失焦。尤其当技能列表里有几十个选项时,命名糟糕的技能基本等于不存在。

我自己后来的排查手法是:把所有的技能从 prompt 里摘出来,随机让模型看一段用户对话,让它几秒内判断该调用哪个技能。如果模型犹豫了或用了几秒才反应,说明这个技能的名字或描述与自然语言习惯不匹配。这个测试方法简单有效,强烈建议你在新技能上线时跑一遍。

4.2 根因二:描述里只有"是什么",没有"什么时候用"

另一个高频问题是,技能的 description 写成了函数注释风格,比如"Send an email"。模型看到之后,只知道这个工具存在,但不知道什么时候应该激活它——尤其在用户表达比较口语化、迂回的时候,比如"帮我催一下张工的进度"。

这句口语里没有出现"邮件"两个字,但如果技能描述里写清楚了:"当用户需要与同事沟通、催办、同步信息时,可以使用 email_sender 技能",模型就能完成从意图到工具的映射。描述里只有"是什么"而没有"什么时候用",等于只给了一半信息。

写技能描述的时候,我现在的习惯是用场景化语言,明确写"当用户需要XXX时使用"。仅仅是前面那个例子,就让我项目的技能调用率提升了三成以上。

4.3 根因三:参数 schema 过严导致的报错连锁

第三个坑,schema 太严格。我曾在某个技能里把date字段设计成严格的YYYY-MM-DD HH:mm:ss格式,结果模型在不确定具体时间时,要么不敢调用技能,要么反复报参数校验错误。

在 Agent 系统中,一次工具调用失败带来的连锁反应远大于普通程序中一次函数报错。因为模型会把失败的日志读回去重新决策,失败越多,上下文越混乱,后续步骤越容易崩。

后来我做了两个重要调整。一是参数校验调整成"宽容输入 + 内部转换",模型传什么格式先接收,再在函数内部统一解析。比如日期字符串,进来先用一个解析器尝试多种常见格式,不行再报错。二是给关键参数提供枚举值和建议值,模型不确定时靠这些兜底。

4.4 根因四:模型上下文里的技能选择压力

还有一个隐蔽的原因——技能数量过多时,模型的选择准确率会断崖式下降。我把技能仓库扩充到五十多个技能后,调用准确率不升反降。

这可不是玄学。给模型塞了几十个工具后,工具选择就变成了一道高难度分类题,模型在大量相似选项中犹豫,出错率必然上升。解决思路是分层路由——先用一个轻量级路由模型判断"当前任务属于哪个领域",再把该领域的十几个技能传递给主模型。这个思路跟检索增强生成里用检索缩小信息候选集是一个道理。

5. 技能编排的进阶玩法:从"会调用"到"会编排"

技能本身设计好了,Agent 的能力上限又从"单次调用的准确性"转移到"多次调用的编排能力"上。这一层玩好了,Agent 才真正具备解决复杂任务的价值。

5.1 流水线编排:把固定流程固化为模板

很多真实业务任务本质上是有固定流程的。拿竞品分析为例:搜索素材 → 抓取详情页 → 抽取关键数据 → 汇总对比 → 生成报告初稿。这段流程每次执行都让模型临场发挥,效果不稳定且耗时,更好的做法是固化为一个编排模板。

我在技能层之上加了一个pipeline概念,每个 pipeline 是一组技能的有序调用,且中间数据格式已经预先定义好。模型只需要负责各个步骤里的局部决策,比如"搜索关键词应该用什么",而不必操心跳过哪一步、怎么传数据。

固化流程之后,整个任务的执行时间平均缩短了约百分之四十,稳定性提升也很明显。这里也要注意:pipeline 的每个步骤之间要保留合规的用户确认节点。尤其涉及发送消息、提交表单、发起支付这类有实际影响的动作,必须留出人工确认的窗口,不能全自动跑到底。

5.2 动态编排:给模型一张技能的"地图"

不是所有任务都适合固定流程。复杂、开放的任务还需要模型动态规划。我管这个叫「技能地图」:在上下文里给模型的不只是技能列表,还包括技能的分类、先后次序建议、组合禁忌。

一段精简的技能地图提示:

可用技能按功能分四类: 1. 信息获取类:web_search, web_fetch, db_query 2. 数据处理类:clean_data, convert_format, compute_stats 3. 内容生成类:draft_report, summarize, translate_text 4. 行动执行类:send_email, create_ticket, deploy_service 使用优先级:遇到问题先走信息获取,再处理数据,最后生成内容。 行动执行类技能必须经过用户确认后才能调用。 组合禁忌:db_query 不能在未认证的环境使用;send_email 和 create_ticket 不要同时调用。

这张地图的作用是主动引导模型的编排方向,又不至于把每一步都锁死。从效果上看,模型的规划路径比纯自由发挥时要稳健不少。

5.3 技能冲突处理:多个技能都能解决同一任务时

进阶场景里还会遇到技能冲突——比如web_search和db_query都能回答"去年销售额是多少",但检索结果可能不一致,甚至结论相反。

我采取的策略是给技能加上"可信度提示":

{ "name": "db_query", "description": "查询内部数据库获取结构化业务数据,权威性高,优先于互联网搜索。当用户询问内部经营数据时,必须使用本技能而非 web_search。" }

同样的场景,web_search的描述中明确写上"互联网公开信息,权威性低于内部数据库"。通过描述里的优先级提示,让模型在冲突场景下有决策依据。

不过话说回来,描述里的优先级提示并不能百分之百保证模型选对,所以在日志追踪面板里我会把"同一问题、不同技能回答不同结果"的情况专门标记成异常样例,攒多了以后分析到底是哪个环节出了偏差。

6. 技能的下一个版本:自我进化的空间

聊到最后,如果你已经有了一套稳定跑通的技能库,自然会想一个问题:技能能不能像代码一样被持续优化,甚至让 Agent 根据运行数据改进自身。

我目前在实验的方向有三个:

一是基于运行日志的自动技能优化。每次技能调用都被记录。如果某些技能长期未被调用,它要么是垃圾技能,要么是描述有问题导致模型没识别出来。定期分析日志里的调用频次、失败率、纠偏率,据此调整技能的描述和参数。

二是把沉淀下来的成功调用路径固化为新技能。比如我发现某类任务模型每次都要走 5 步才能完成,那就把 5 步固化为一个一步完成的新技能,既省 token,又减少出错面。这块在电商客服场景里很实用——商品推荐、退换货引导这些高频固定路径,完全可以沉淀成复合技能。

三是基于合成数据做技能调优的可行性验证。比如用大模型生成"问题-期望技能-期望参数"的合成样本,再拿这些样本去微调轻量路由模型,让路由本身更聪明。这个方向我还在验证阶段,但初步感觉潜力不小,因为它能把对主模型能力的依赖逐步转移到可控的小模型上。

每次想到这些,我都觉得 agent-skills 工程化的空间其实比模型本身要大。毕竟模型能力是公共资源,而技能体系才是你能长期积累、持续沉淀的核心资产。

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

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

立即咨询