ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Agent技能库实战:让AI稳定复用经验的Skills体系

Agent技能库实战:让AI稳定复用经验的Skills体系 最近被问得最多的一个问题为什么别人做的 Agent 能稳定跑业务我自己搭的 Agent 总是玩两天就废了我给的答案通常很简单——你缺的不是更好的模型而是一套让 Agent 稳定复用经验的机制这也是 agent-skills 这个东西真正要解决的问题。这里说的 skills你可以直接理解成技能把某个任务从每次让模型临时想怎么做变成仓库里一份可复用、可验证、可迭代的执行单元。这篇内容就是我整理自身实践经验的一份总结适合正在做 Agent 应用、希望把演示 Demo 推到生产状态的开发者也适合那些被工具调用不准、输出不稳定、上下文越用越乱折磨的团队。看完之后你至少能学会怎么设计第一门技能、怎么搭技能仓库、以及哪些坑是必须绕开的。1. 为什么我给Agent搭了一套技能库大模型原生能力的边界1.1 模型临时思考很贵也很不稳定先说我踩过的真实场景。早期做 Agent 的时候我喜欢把任务直接写进 system prompt比如你是一个数据分析助手请根据用户上传的数据生成报告。听起来没毛病但跑起来就是灾难模型每次都在对话里重新推理整个流程结果经常漂移——同一个数据、同一个 prompt上午跑和下午跑能给出两个版本的结论。更麻烦的是只要对话一长模型就会忘掉前面的约束开始自由发挥。这背后其实是 LLM 本身的工作机制决定的。它没有真正的记忆每一步都是根据当前上下文里的 token 做概率预测。上下文窗口有限你在 prompt 里塞的规范越多有效信息占比越低推理过程又不可控同一个任务在不同的温度、不同版本模型下思维链走向可能完全不同。我后来算了笔账一个并不复杂的清洗客户表格任务靠模型在对话里自由发挥平均要消耗 2 到 3 万 token而且经常需要我人工盯结果。这不是模型变笨了而是我用错了方式。我等于让一个实习生每次上班都重新发明一遍做事流程而不是给他一本 SOP 手册。1.2 技能的本质把能力从prompt里的感觉变成仓库里的资产后来我在项目中引入了技能库这个结构思路就一句话凡是流程稳定、能被验证的任务就不该让模型每次从头想而应该把过程固化成一块可插拔的积木。我拿老带新来类比。老员工带新人不会指望新人凭空悟出怎么做而是会给一份标准作业流程上面写明什么情况启动这个流程、第一步做什么、依赖什么数据、产出长什么样、怎么自检。技能库干的就是这件事只是服务对象从人换成了模型。一个标准技能单元通常包含四块触发条件描述、输入参数契约、执行流程、输出格式与验证规则。模型遇到任务后不是自己去推理每一步而是先在大脑里搜索有没有匹配的技能匹配上了就把参数填进去技能执行完把结构化的结果返回给模型。这看起来只是架构变了实际上把模型自由发挥变成了模型做选择、技能做执行。我之前在另一个项目里把网页正文抽取做成了技能里面封装了正文识别、去噪、标题提取、段落切分全流程。挂上之后模型不再自己对着 HTML 一顿乱分析而是直接调用统一入口输出格式也是固定的 JSON。从那以后这个模块的成功率从大概 70% 直接拉到了 98%而且基本不挑站点。1.3 从Function Calling到Skills这条路为什么是必然很多人可能觉得Function Calling 不就能干这件事吗确实函数调用是基础但它在工程上有一个明显的短板它只解决让模型能用某个工具的问题不解决让模型按正确流程做完一件事的问题。举个例子。你给模型一个send_email()函数它可以调用但如果发一封每周团队同步邮件这件事需要先拉取成员列表、再统计本周 issue、再套用模板、最后发送——这三个步骤靠模型在对话里一个个调用函数中间任何一步输出格式乱了后面的步骤就全断了。而技能库把整条链路封装成一个单元模型只需要提供基础参数剩下的事情由技能内部的有序步骤完成。更底层一点的演进路线是这样的一开始大家靠 prompt 工程在 system prompt 里写满规则后来发现规则太多模型记不住于是出现了 Function Calling让模型知道有工具可以用再往后工具多了、描述复杂了社区又做了 MCP 这类标准化协议把工具装进统一入口。但工具标准化解决的还是连接问题技能库解决的是编排和执行问题——它包含了工具的调用逻辑也包含了模型在流程中需要做判断的节点。所以在我看来从 prompt 工程到技能库是一条必然路径每一步都是把更多知识从模型脑子里搬到仓库里让模型越来越专注在自己最擅长的事情上——理解意图、做选择、调节奏。2. 一个Skill的长相接口、描述与被正确调用的关键2.1 先把什么任务值得做成技能搞清楚做技能库之前先做减法。不是所有任务都值得被封装成技能我踩过一段时间的坑就是看什么都想封装最后技能列表长得像小说目录真正被调用的没几个。我自己总结了三个筛选条件全部满足才值得做第一任务频繁出现。一个只有月初用一次的任务不值得专门维护但从日志里提取报错并归类这种每周都来几次的性价比就很高。第二流程相对固定。如果任务本身有明确步骤比如先查数据库、再调接口、再组合数据、最后按模板输出那就完美命中技能的场景。反过来像帮我想一个品牌 slogan这种开放式的创意任务技能反而会限制模型发挥。第三输出可以被自动验证。这是很多人忽略的点。技能产出的结果最好能被程序检查——是不是合法 JSON、字段齐不齐、数据有没有越界。如果一项任务的产出无法自动校验那你很难保证技能改了之后没有被改坏也没法放心让 Agent 独立执行。2.2 技能三件套描述、输入契约、输出契约一个技能能不能被模型正确使用关键在于三样东西描述、输入参数、输出结构。描述是给模型看的说明书它决定了模型什么时候调用这个技能。输入契约是一个 JSON Schema它限定了模型能塞进来的参数长什么样。输出契约则是技能向模型返回数据的固定格式也是下游流程能继续解析的前提。我做技能的经验是这三样里输出契约往往比输入契约更关键。因为输入参数是模型生成的即使偶尔不符合预期技能内部还能做一层清洗兜底但输出是技能给模型的如果输出格式不固定模型拿到的就是一堆稀碎的数据后续步骤又要靠模型重新整理不稳定因素再次出现。我自己的目录结构里输出契约都会单独写清楚并且技能内部最后一层一定有一个格式强制器——把所有结果转成规定好的 JSON 或者 Markdown 块确保进入模型上下文的东西是干净的。2.3 描述写得好不好直接决定模型会不会乱调用这里要重点说描述因为它是整个技能系统里最容易被低估的一环。模型选择是否调用某个技能几乎只看描述文字和函数名关系不大。描述写得太泛模型就什么都往这个技能上靠写得太窄模型遇到该用的场景反而想不起来。我在技能库里有过一个典型的反面教材一个文本优化技能描述只写了优化文本内容结果模型把翻译、摘要、改写、纠错全都派给它一个技能背上八种职责没有一个任务做好。后来我把描述改成了三段式能力范围、触发场景、禁用条件。能力范围写清楚这个技能做什么和不做什么触发场景写当用户提到……、当数据包含……这类具体信号禁用条件直接写明只有当……才可调用其余情况不要使用。改完之后误调用率直接降了一大截。这个细节是我认为 agent-skills 实践中最容易立竿见影的一处。2.4 我的技能模板长这样下面是我在项目里实际在用的技能模板会简化一点但结构保留。一个技能在我的库里是这样一个目录skills/ └── weekly_report_generator/ ├── SKILL.md # 给模型看的描述和步骤 ├── main.py # 技能执行代码接收参数返回 JSON ├── requirements.txt # 依赖声明 └── tests/ └── cases.json # 黄金评测用例SKILL.md 我通常是这么写的--- name: weekly_report_generator description: 根据日期范围、关注点和汇报对象生成结构化周报。 trigger: 用户提到周报、周总结、weekly report 等关键词提供时间范围或可以从上下文推断时。 not_trigger: 用户提到月报或年报时请改用 monthly_report_generator。 input: start_date: string, 必填, YYYY-MM-DD end_date: string, 必填, YYYY-MM-DD focus: string, 可选 audience: string, 可选, engineer | manager | mixed output: 返回 JSON, 字段为 summary, highlights, risks, action_items --- 步骤 1. 从 git 仓库和 issue 系统拉取该时间范围内的数据。 2. 按 focus 字段对数据进行主题归类。 3. 使用 main.py 中提供的 generate() 方法生成报告内容。 4. 返回结构化 JSON不要添加额外说明。模型看到这份 SKILL.md 后会先判断是否匹配匹配了就把参数提取出来调用技能最后拿到 JSON 结果再组织语言回复用户。整个过程里真正需要模型动脑的部分被压缩到了最小稳定性自然就上来了。3. 技能库的治理版本、测试、依赖一个都不能少3.1 技能仓库的目录结构技能写到一定数量之后治理就成了头等大事。我一开始把几十个技能全放在一个包里面互相 importdev 环境和 prod 环境共用一套代码结果有一次改了一个公共工具函数炸掉了六个技能。从那以后我把技能全部改成自包含模式每个技能一个独立目录内部可以有 helper但禁止跨技能共享函数。目录结构上面那一节已经展示过核心原则是技能是一个独立可部署的单元它的代码、文档、依赖、测试全部收拢在一个目录里。这样无论是否用容器技能都可以被单独打包、单独回滚。后来我甚至把技能目录直接镜像成了 git 子仓库每次改动走 review 流程效果非常明显。3.2 给技能上版本号和评测集技能和普通代码最大的区别是技能的运行环境里有一个不确定的模型模型行为会随着模型版本变化而变化。所以你光管住代码不够还要管住行为。我的做法是对每个技能都做语义化版本管理并且每个技能配一份黄金评测集。评测集一般是一个 JSON 文件里面放 5 到 10 条该技能最典型的输入输出对。每次技能代码有改动我就拿评测集跑一遍看输出是否仍然符合预期。这相当于给技能加了一层行为回归测试——不只是代码不报错还要行为达标。这个习惯救过我好几次。有一次我更新了一个信息抽取技能的底层解析逻辑代码运行完全正常但评测跑完之后发现三条用例的输出结构变了。如果当时没有评测集直接上线那些依赖固定结构的技能连锁崩掉是大概率事件。3.3 防止依赖冲突技能必须自包含依赖问题是我另一个深刻教训。技能最好各自声明依赖哪怕重复装库也比共享全局依赖强。原因很简单不同技能的演进节奏不一样今天 A 技能升级了某个库明天 B 技能可能因为这个升级行为异常而你根本不会往那个方向排查。在运行层面我也会尽量给技能一个隔离的执行环境。最简单的做法是每个技能跑在一个 subprocess 或者独立容器里模型只能拿到标准输出。这样即使技能内部崩溃了也不会污染整个 Agent 的上下文。实测下来这种隔离设计带来的稳定性提升远大于它在性能上多出来的那一点点开销。3.4 实测数据40多个技能的调用分布打理了半年技能库规模在四十多个技能左右下面是某个月的真实调用统计节选了一部分。技能名称调用次数成功率备注网页正文抽取38698.2%主力技能日志错误归类27496.7%主力技能周报生成器16897.6%团队日常高频联系人信息提取9194.5%稳定但频率一般PPT大纲生成3489.2%低频情绪分析1287.5%低频考虑合并翻译880.0%被通用能力替代准备下线从这个表里能看出的规律是大概 20% 的技能承担了 80% 的调用量剩下很多技能其实处于半冷启动状态。我的处理原则是低频技能如果又没有不可替代的特殊逻辑就及时下线或合并不要让它留在技能列表里干扰模型的选择。技能库不是收藏柜不是越满越好模型面对的选项越精简每次调用的准确率越高。4. 完整实战把一个周报生成器沉淀成一门技能4.1 需求拆解哪些活交给代码哪些活交给模型上面说的都是方法和框架这里用一个完整的实例把链路串起来。假设你和我一样每周要给团队生成周报数据来源是 git 提交记录和 issue 系统输出格式要符合公司模板。做技能之前先做任务拆解。一个周报生成任务包含这些子步骤拉取提交记录和 issue、按主题归类、总结要点、识别风险、按照模板组织语言。放在纯 prompt 模式里模型要自己完成全部五步还要自己处理拉数据的问题——实际上模型根本不擅长稳定调用命令行工具也没有可靠的权限控制。做技能之后划分逻辑是这样的与数据获取和格式强相关的工作交给代码由main.py负责语义理解、归类总结、风险判断这些需要一点人的判断力的部分交给技能内部模型执行节点。这里有一个关键设计技能并不一定要完全排除模型参与它可以把模型当作内部子流程来用。技能定流程模型做判断代码做执行。4.2 技能代码与SKILL.md怎么配合我给周报生成器的main.py写了一个非常简化的版本用来展示技能内部的配合方式。# skills/weekly_report/main.py import json from datetime import date def fetch_git_data(start_date, end_date): # 实际项目里这里会调用 git log / gh 命令 return {commits: [], issues: []} def generate_weekly_report(start_date, end_date, focusNone, audienceengineer): data fetch_git_data(start_date, end_date) # 模型节点从 raw data 中提取主题和风险 model_summary extract_summary_with_llm(data, focusfocus) # 代码节点套用模板并强制输出结构 report { summary: model_summary[summary], highlights: model_summary[highlights], risks: model_summary[risks], action_items: model_summary[action_items], generated_at: date.today().isoformat(), } return json.dumps(report, ensure_asciiFalse)这个写法里extract_summary_with_llm是技能内部持有的小模型调用它只在技能流程中被执行输出会被外层强制套进模板。相比让 Agent 直接面对一堆数据技能让模型的判断集中在这个 commit 到底属于哪个主题这种局部问题上单个任务简单了稳定性自然高了。配合上前面那节给的 SKILL.md整个技能的工作流就是模型根据描述识别意图 → 提取日期参数 → 调用技能 → 技能内部走完执行链路 → 返回 JSON → 模型再基于 JSON 组织最终回复。4.3 挂载到Agent后的效果对比我把这套周报生成器接到 Agent 上之后做了前后效果对比数据如下。对比项使用技能前自由 prompt使用技能后输出格式达标率64%99%平均 token 消耗约 34000约 8700平均耗时约 3 分钟约 40 秒需要人工修正的比例每次都要偶尔一次最让我意外的是 token 消耗的下降幅度。原因也很简单以前模型要把拉数据、读记录、写总结全过程都放进上下文里反复思考现在数据获取完全在代码里完成模型只需要处理精炼后的结构化信息。上下文里不再堆满原始 commit message效率和稳定性一起上来了。4.4 从周报到月报复用比重构更便宜技能还有一个隐藏红利可复用性极强。我的周报生成器加了两个参数之后直接变成了月报生成器——只需要把start_date拉长到一个月、模板稍微调整一下、focus支持更粗的粒度即可。等于新增一个能力只花了一小部分成本而且底层逻辑经过周报场景反复打磨已经非常可靠。后来我又用它衍生了项目复盘技能、团队 OKR 进度汇总技能核心流程全是同一套。这就是我反复提到的资产概念技能一旦沉淀下来它就不再是一次性的代码而是可以被不同 Agent、不同场景反复调用的经验资产。5. 我在落地过程中踩过的坑粒度、权限和冷启动5.1 技能粒度粗了失控细了选择困难技能粒度是我权衡最多的地方。一开始我很激进尝试过把文本分析整个做成一个巨型技能里面塞了情感分析、关键词提取、摘要生成、命名实体识别。结果就是模型进入这个技能之后根本不知道该执行其中哪条逻辑技能内部自己先乱了输出质量反而不如不封装。后来我又走到另一个极端把提取邮箱地址和提取手机号拆成两个技能技能列表瞬间膨胀到 60 多个模型每次光匹配就消耗几百 token还经常匹配错。一个我后来觉得很实用的判断标准当一个技能能被一句话说清楚、并且内部流程能控制在三到五个步骤时粒度基本是合适的。如果一个技能的描述需要写超过三行才能说清那就该拆如果两个技能经常被同时调用那就该合并。粒度本来就是一个动态平衡的过程不用追求一次到位先拆粗跑一段时间再根据调用数据调优。5.2 权限边界技能不是给模型一把万能钥匙技能封装了执行逻辑同时也封装了权限这是好事但你必须在设计技能时就把权限边界想清楚。我的一个数据清洗技能曾经出过事故技能内部有一个删除临时文件的清理步骤代码写的时候没有限制路径结果模型在某个场景传入了一个意外的路径差点把缓存目录清掉。现在的原则是技能内部涉及文件系统、网络请求、shell 命令的部分全部做白名单限制。比如删除文件只允许在技能自己的 temp 目录下操作网络请求只允许访问预先配置好的内网地址任何外部命令都不允许拼接模型提供的原始字符串。技能给模型的是功能不是任意门。权限问题宁可设计得保守一点也不要为了省事放开所有限制。5.3 错误处理与冷启动两件容易被忽略的事技能运行不可能永远成功而模型面对失败时的行为很大程度上取决于你给它的反馈。如果技能内部只是抛出一个干巴巴的error字符串模型不知道是参数错了还是系统挂了往往会选择换个参数反复重试白烧 token。我的做法是让技能失败时返回结构化错误错误类型、可能原因、建议操作给模型一条明确的出路。这样模型要么修正参数再试一次要么直接告诉用户失败原因而不是在死循环里打转。冷启动则是另一个容易被忽略的问题。新技能刚挂上去的前几天调用率通常很低因为模型还不熟悉它。我测试过一个新技能的调用情况只写了标准描述没有任何示例的时候一周内调用次数只有个位数我加了两三个典型调用场景示例之后调用次数直接翻了几倍。原因也很好理解模型看到描述只能知道这个技能负责什么而看到示例才真正知道什么时候该喊它出来干活。所以新技能上线时别忘了在 SKILL.md 里给一到三个真实的触发场景示例。5.4 什么时候不该用技能最后一条经验是没有经验的人最容易忽略的不是所有东西都值得做成技能。简单到一句话就能完成的任务比如把这段文字翻译成英语直接让模型做就是了做成技能纯属制造管理负担。技能适合的是那些有一定复杂度、重复发生、并且你希望每次都用同一种方式来执行的任务。如果你的项目里目前只有七八个任务老老实实把 prompt 写好就够了等任务开始变得杂乱或者多个 Agent 都要用到同一套逻辑时再引入技能库。过早引入技能体系反而会让项目失去灵活性。用了大约两个多月的时间把这套体系整理出来之后我最大的体会是Agent 能不能稳定落地往往不取决于模型选得多好而取决于你愿不愿意把它的行为沉淀成一套可治理的资产。最开始整理第一个技能的时候也挺痛苦的但跑通一次之后后面所有 Agent 都在吃同一套经验的复利。如果让我给一个建议那就是别急着铺开做几百个技能先选一个你每天都用、又足够烦人的任务把它做成第一个技能然后认真写描述、配评测集、观察调用数据。等你从这一个技能里摸清门道其他技能基本都是顺势而为的事了。
返回列表