Agent技能库实战:用可复用脚本提升大模型执行稳定性

发布时间:2026/10/14 9:52:30

Agent技能库实战:用可复用脚本提升大模型执行稳定性 做 Agent 开发的人大概率都被同一个问题纠缠过模型的上限很高可真到具体任务上结果却忽上忽下。同一个需求换一种说法可能就完全跑偏换一个环境可能直接歇菜。我最近把散落在各个 Prompt 和脚本里的能力统一整理成了一个叫 agent-skills 的技能库才真正把“Agent 会做什么”变成了可以复用、可以测试、可以迭代的工程资产。这篇文章不是纸上谈兵是我搭建、验证这套技能库过程的实盘记录希望能给正在设计 Agent 功能边界的朋友一些参考。1. 先把“技能”这件事想清楚agent-skills 到底解决什么问题1.1 为什么写“技能”比写“万能 Prompt”更靠谱早期我做 Agent 的方式和很多人一样把任务背景、业务规则、输出格式全部塞进 Prompt指望模型“一顿操作猛如虎”。实际跑起来会发现两个问题。第一Prompt 越长模型对关键规则的注意力越分散经常出现“规则写了但没执行”的情况。第二每次接入新任务都要重新写一大段背景不同 Agent 之间的能力完全没法复用等于每个任务都在从零开始。后来我换了个思路把“任务”拆成“更小的能力单元”每个单元由一个技能文件加一段可执行脚本组成这就是 agent-skills 的基本形态。技能目录里不只有“说明书”还有真正能跑出结果的脚本。模型负责判断什么时候调用、参数怎么传而脚本负责把结果确定性地算出来。这里有个容易被忽略的关键点技能不能只是文字建议。如果技能文件里写着一堆“请仔细检查代码风格”这样的描述最终执行效果还是依赖模型当时的发挥稳定性不会有本质提升。我要求每个技能至少包含一个可独立运行的脚本入口脚本负责消化输入参数、执行核心逻辑、返回结构化结果。Agent 只调度不做重活。用生活化的类比来说长 Prompt 等于你给实习生发了一本厚厚的手册让他自己悟技能库等于你给他一个装好工具和操作卡片的工位他照着卡片操作结果是稳定可预期的。我们要的是后者。1.2 一次技能调用的完整链路agent-skills 的技能包形态其实很简单核心链路如下Agent 收到用户任务。编排层扫描技能库把每个技能的 description 和当前任务做匹配。命中技能后加载该技能文件夹里的 SKILL.md 说明文件。模型根据说明文件判断当前场景是否适用并准备参数。调用技能目录中的脚本传入参数。脚本执行完毕后返回结构化结果通常是 JSON。模型把结果加工成最终答复或基于结果决定下一步动作。这条链路里真正决定成败的是第 4 步和第 6 步。第 4 步要求技能描述写得足够精确否则模型不知道该不该调用第 6 步要求脚本的输出格式必须严格稳定否则模型拿到乱七八糟的结果后续推理就容易失控。我在设计中就刻意做了一个约束每个脚本的输出必须是可以被程序校验的 JSON包含 status、data、error 三个字段。status 标识执行成功或失败data 放核心结果error 放异常信息。这样 Agent 只要读到 status 就能判断下一步该做什么不用自己去猜脚本到底跑没跑成功。2. 从零开始搭建技能库目录、命名与可复用设计2.1 技能目录与命名规范我采用的目录结构非常直观每个技能一个独立子目录顶层统一挂在 skills 文件夹下skills/ code_style_check/ SKILL.md check_style.py doc_extractor/ SKILL.md extract.py schema.json data_transform/ SKILL.md transform.py web_checker/ SKILL.md checker.py目录命名的规则我建议是“动词_对象”。先说动作再说对象比如 code_style_check、doc_extractor、data_transform。这样做的原因很简单Agent 做意图匹配时动词信息的权重比名词更高。code_style_check一眼就能看出这是“检查代码风格”的能力而check_code_style虽然意思一样但在一些长文本匹配场景里“code_style”作为完整短语更容易被模型识别。2.2 SKILL.md 的头部信息与参数声明每个 SKILL.md 文件的开头我建议用 YAML 写元信息包括名称、描述、适用场景、参数列表。下面是我常用的模板--- name: doc_extractor description: 从 docx、pdf 或 txt 文件中抽取指定字段适合报告、合同、简历等文档的结构化信息提取。 when_to_use: 用户给出一个文档路径并希望得到字段化的 JSON 结果。 parameters: - name: file_path description: 输入文档的本地路径必须存在。 required: true type: string - name: fields description: 需要抽取的字段名列表例如 [title, author, date]。 required: false type: list ---description 字段要写清楚“什么时候该用”而不只是“这个技能是什么”。我在早期的技能描述里写的是“文档信息抽取”结果模型经常在有更合适技能的情况下仍然误选它。“when_to_use”这一项后来帮我解决了大量误触发问题模型能根据场景描述直接判断是否匹配比单纯看名称靠谱得多。参数列表也很有讲究。参数名、类型、是否必填必须和脚本里的函数签名严格对应。既然技能本质上是可调用的函数就遵循函数的接口规范。如果参数名在 SKILL.md 里叫file_path脚本里却用path模型就会自己瞎猜轻则报错重则读错文件。这里没有任何取巧空间。2.3 依赖、执行环境与权限设置技能要跑起来必然涉及脚本依赖。doc_extractor可能需要 python-docxdata_transform需要 pandasweb_checker需要 selenium。我建议在每个技能目录下放一个requirements.txt同时统一用一个全局的 Python 虚拟环境运行所有技能脚本。这样做的好处是维护成本低不用为每个技能单独建一套环境。但代价是依赖冲突要靠人工控制。实用做法是能不加新依赖就不加必须加的依赖在 requirements.txt 里写好版本号比如pandas2.2.2避免哪天升级把整个技能库搞挂。权限设置是很多人忽略的部分。技能脚本默认工作目录限定在项目指定工作区不允许访问用户主目录之外的文件不执行删除类高危命令。每个脚本入口统一加一层路径白名单校验凡是文件路径不在允许列表内的直接返回status: forbidden。这样做既保护了环境也让 Agent 的行为边界更清晰不会因为一次错误调用把系统搞乱。3. 核心技能实现代码检查、文档抽取、数据处理与页面检查3.1 代码检查技能把“写一遍”变成“改一遍”我给 Agent 做的最常用的技能之一就是代码风格检查。过去让模型直接审查代码风格是很主观的每次给出的意见都不一样。我把这部分逻辑抽到脚本里用 Python 的 AST 模块做静态分析检查导入顺序、未使用变量、函数定义位置等问题每次输出完全一致的 JSON 结果。核心逻辑大致是import ast def check_style(file_path): with open(file_path, r, encodingutf-8) as f: content f.read() tree ast.parse(content) issues [] # 检查未使用的导入 for node in ast.walk(tree): if isinstance(node, ast.Import): for alias in node.names: if alias.asname is None and not used_in_source(tree, alias.name): issues.append({line: node.lineno, issue: unused_import, detail: alias.name}) return {status: ok, data: issues, error: None}AST 解析天然保证结果可复现不依赖模型的主观审美。Agent 拿到 issues 后再逐条决定改还是不改。这样执行确定的归脚本需要判断和解释的归模型职责分得很清楚。实际使用中我最满意的一点是这类技能可以把模型从“想象力发挥”中解放出来。以前让 Agent 改代码它喜欢大段重构动不动就改出风格不一致的东西。现在它只负责定位问题和执行修改改动量反而小了代码风格也更统一。3.2 文档抽取技能输出格式的统一是关键文档抽取是 Agent 非常高频的任务但也是最容易产出脏数据的地方。PDF 的排版、表格、页眉页脚都会干扰解析结果。我实现的doc_extractor技能采用“读取文本 模型抽取 规则校验”的组合策略。脚本先用文档解析库把文本抽出来然后交给模型按预定义的 schema 进行抽取。关键在于 schema 要提前定义好。我放了一个schema.json在技能目录里脚本启动时先加载 schema再让模型严格按照 schema 填充结果{ title: {type: string, required: true}, author: {type: string, required: false}, date: {type: string, required: false}, keywords: {type: list, required: false} }脚本返回结果前还要做一轮规则校验必填字段如果为空status 直接标成partial_success并给出缺失字段清单。这样 Agent 在接手结果时就不用猜测“抽出来的数据到底全不全”。这里有个实操心得不要让技能脚本对抽取结果做过多“修正”比如自动补全日期格式、自动拼接姓名。这些修正动作会让数据源头变得不可追踪。宁可让数据保持原样再由 Agent 根据业务规则统一清洗这样排查问题时你能清楚地知道每一步发生了什么。3.3 数据处理技能CSV 到 JSON 再到摘要Agent 处理 CSV、Excel 这类表格数据最常见的问题是统计口径不一致。同一份数据今天算出来的平均值和明天算的可能不一样因为模型每次处理时对空值、异常值的处理方式都不同。data_transform技能就是为了统一这个口径。脚本接收文件路径和目标字段先做列类型识别再按照固定规则处理空值和异常值最后输出规范化的 JSON 数据import pandas as pd def transform(file_path, target_column): df pd.read_csv(file_path) if target_column not in df.columns: return {status: error, data: None, error: column_not_found} cleaned df[target_column].replace(, pd.NA).dropna() summary { count: int(cleaned.count()), mean: float(cleaned.mean()) if cleaned.dtype.kind in fiu else None, min: float(cleaned.min()) if cleaned.dtype.kind in fiu else None, max: float(cleaned.max()) if cleaned.dtype.kind in fiu else None, } return {status: ok, data: summary, error: None}统计逻辑一旦固化在脚本里无论模型怎么调用输出的统计结果都是一致的。模型只需要负责把 summary 拼成自然语言报告。这样既保证了数据准确又不会让模型去猜统计口径。3.4 页面检查技能等待、重试与截图浏览器自动化的技能要处理的不只是“打开页面”还有加载延迟、元素未出现、验证码等一堆情况。web_checker技能的做法是固定等待策略 明确重试次数 结果附带截图路径。脚本的核心模式是三重结构定位元素、等待出现、执行断言。每次操作最多重试三次每次间隔 3 秒。如果三次都失败返回超时错误而不是让 Agent 在页面上乱点。对于页面检查这种高风险操作宁可给 Agent 一个明确的错误信号也不能让它陷入无限循环。有一点经验很重要浏览器操作脚本一定不要直接向上下文塞回整张截图或整页 HTML。截图文件单独保存到工作区脚本返回的是截图路径和页面状态摘要。Agent 需要看截图时按路径去读文件而不是把截图二进制内容直接带回对话里否则上下文消耗会非常夸张。4. 实测与效果一组可复用的技能调用结果4.1 我用来验证技能库的真实场景为了验证 agent-skills 不是“自我感觉良好”我选了一个真实场景做测试每周整理某内部项目的进度周报。以前的做法是人工从几个本地文档里复制关键信息再结合数据表写一段总结整个过程大概要一个多小时。现在我把流程拆成了三步分别复用三个既有技能用doc_extractor从周报底稿文档里抽取完成事项、风险、下期计划。用data_transform读取项目数据表统计本周新增任务数和完成率。由 Agent 根据两部分结果生成最终的周报正文。整个流程跑下来纯人工耗时从 60 分钟左右压缩到了 10 分钟而且周报的数据字段相对固定前后格式高度一致。4.2 效果对比从“结果飘忽”到“稳定可交付”我对四类技能分别做了样本测试统计稳定率和平均耗时技能名称测试场景样本数成功次数稳定率平均耗时code_style_check代码风格审查12011898.3%2.4sdoc_extractor文档字段抽取403792.5%8.6sdata_transform表格数据统计605998.3%1.1sweb_checker页面状态检查807695.0%6.2s稳定率最低的是文档抽取92.5%。失败样本基本都集中在扫描版 PDF 或排版极其混乱的文件上这类输入纯靠文本抽取做不好需要后续加 OCR 才能补上。但从整体使用体验来看四个技能全部成功时Agent 的输出几乎不需要返工即使某个技能失败它返回的 error 信息也能让 Agent 明确知道是哪一步出了问题而不是像以前一样自己编一个结果。4.3 一些真实的参数记录和调优过程测试阶段我记录过几个细节值得回头看。第一doc_extractor初版不稳定问题不在抽取效果而在“模型一次性抽太多字段”时经常漏抽小字段。我把一次抽取拆成“逐字段抽取最后合并”漏抽率立刻明显下降。第二web_checker的等待时间一开始设成 1 秒测试中频繁误报失败。调整成“每轮等待 3 秒、最多重试三次”之后稳定率从 82% 提到了 95% 以上。不要把超时设得太短尤其是在内网页面本身响应就慢的情况下。第三任务链路如果较长建议在开头先把所有技能描述和参数预加载一遍而不是等到步骤执行到一半再去翻技能库。实测下来预先加载可以让多技能串联时的决策时间减少大约 30%。5. 常见问题与排查技巧实录5.1 Agent 不触发技能或触发了却用不好最典型的现象是任务很明确但模型完全没提技能自己硬着头皮做。排查下来问题几乎都出在 SKILL.md 的描述写得不够精确。description 里全是“文档抽取”这类宽泛词模型不知道什么场景才应该触发。解决办法是在描述里增加触发场景词比如“给一份 PDF 报告想提取标题和日期”。另外在 when_to_use 里明确写“不适用的情况”能显著减少误触发。还有一种情况是技能触发了但模型不知道参数怎么给。多半是参数描述不完整。比如file_path只写了“文件路径”模型不知道要不要绝对路径。补充为“输入文档的绝对路径例如 /data/reports/xxx.pdf”后错误率立刻下降。5.2 输出解析失败、字段缺失先救数据再报错技能脚本返回的结果被 Agent 继续加工时偶尔会出现字段缺失问题。这个问题的根源往往在 schema 定义。如果 schema 里某个字段是required: true脚本却在缺失时直接抛异常Agent 就拿不到任何可用的部分结果。我的做法是必填字段缺失时返回partial_success并把缺失字段列清楚如果只是部分字段有值先返回已有数据。这样 Agent 可以对现有数据继续处理而不是因为一个字段缺失就把整个任务卡死。从排查角度看partial_success也比error更容易定位问题至少你能确定哪一步执行成功、哪一步数据不完整。5.3 上下文污染中间结果别全量塞回对话技能脚本返回结果后Agent 把整段 JSON 原封不动地粘贴进上下文继续推理这是最常见的效率杀手。一个包含几百行数据的统计结果塞回对话会让模型在后续推理时被无关数据干扰还白白占用 token 额度。处理方式是在技能脚本内部就做“结果压缩”。返回的数据只保留关键统计量和摘要原始明细单独写到工作区文件需要时再按路径读取。模型在上下文中看到的永远是精炼过的结果而不是一大堆原始数据。这一点实战中收益非常明显多技能串联时尤其重要。5.4 资源失控和超时技能如果涉及浏览器、大数据集处理偶尔会在执行阶段卡死。我给脚本统一加了 timeout 机制Python 脚本外层用signal或者线程方式限制超时最长执行时间控制在 30 秒以内。超时时同样返回结构化错误而不是让调用方无限等下去。另外如果多个 Agent 任务并发执行要注意技能脚本是否有写同一个工作区文件的冲突。我加了一个简单的文件锁同一个技能同时只允许一个实例写文件避免脏写导致的结果错乱。这个坑比较隐蔽等出现复现问题时再排查会非常痛苦。5.5 我给技能库定的安全红线技能能做的事越强越要控制它的边界。我给整个 agent-skills 技能库定了四条红线全部固化在入口脚本里不靠模型自觉默认禁止删除文件、禁止格式化磁盘、禁止修改系统配置。文件路径必须在设定的工作区内否则直接返回 forbidden。外部命令执行采用白名单只放行ls、cat、git status等非破坏性命令。涉及环境变量、账号密码等信息一律从配置文件读取不允许写入技能脚本。这四条红线不是摆样子。任何超出边界的调用都会带上明确的拒绝原因Agent 看到原因后也只能按规则办事。把安全规则做成代码的一部分才算是真把边界立住了。6. 持续迭代agent-skills 的下一步和一点经验总结6.1 技能库如何随业务生长技能库不是一锤子买卖。每接一个新任务我做的第一件事是看它能不能拆成已有技能的组合。如果能就写一个“流程编排”层的备注告诉 Agent 先调用哪个再调用哪个。如果拆不开再看这个任务的高频部分是否值得做成新技能。新增一个技能有固定流程先写 SKILL.md再写脚本和 schema然后在本地用 5 到 10 个样例验证稳定率最后才放进正式技能库。我吃过一次亏一个技能只测了两个样例就上线结果第三个场景直接翻车。后来加了一条硬规则一个技能至少跑过 20 个样例才允许进正式目录。6.2 如果从头再来我会注意的三件事第一技能命名要早一点统一成“动词_对象”后期改命名牵一发而动全身所有 SKILL.md 里的 description 都要跟着调。第二参数定义要更细尤其是 type 字段宁可多写不能少写模型对弱类型参数的容忍度比想象中低。第三技能数量一定要克制五个好用技能胜过二十个摆设技能技能库过大会增加匹配成本反而让模型更犹豫该选哪个。说句实在话agent-skills 并不能解决 Agent 的所有问题它解决的是执行稳定性问题。模型仍然需要理解业务、需要判断边界、需要处理没见过的场景。但有了技能库底层能力是确定的、可测试的模型只需要在有限的选择里做决策容错空间自然大得多。如果你也在做 Agent 类项目建议从最常用的三五个动作开始把它们固化成技能哪怕一开始做得粗糙也比没有强得多。跑上一段时间你会明显感觉到“结果变稳了”这件事带来的连锁好处。
延伸阅读

更多相关文章

2026/10/14 9:52:30

HCIE云计算私有云备考:从虚拟化原理到面试实战全攻略

考完笔试那一刻,我一度觉得HCIE云计算已经拿下一大半。直到第一次模拟实验,虚拟机迁移连续三次在“迁移完成”前两秒报错,我才意识到这个认证真正难的地方不是操作,而是你能否在考官的连环追问下,把私有云这套技术栈讲…

2026/10/14 9:52:30

病理AI场景专用模型:从通用大模型到临床工作流嵌入

1. 项目概述:当病理诊断遇上AI基础模型,一场静默却深刻的范式迁移正在发生“AI病理文摘”这个标题乍看像一份行业简报,实则藏着过去两年里数字病理领域最硬核的突破信号。我从2018年开始跟进AI辅助病理诊断项目,参与过三家三甲医院…

2026/10/14 9:52:30

从Tool Calling到技能系统:生产级Agent能力治理实战

做Agent接入真实业务时,卡住我的从来不是大模型本身,而是那些“会做事的手”——一次查询、一次写库、一次调用第三方接口。大多数入门教程都在讲tool calling怎么把函数列表喂给模型,但真到了几十个工具、多轮调用、多角色权限的规模&#x…

2026/10/14 11:33:23

Agent运行时:从大模型推理到生产级任务执行的工程实践

一个开源仓库的星标数在 24 小时内涨了 1379 个,放在几年前几乎不可想象;可现在只要是和 Agent 沾边的项目,爆火已经成为常态。ax 这个仓库我扒过一遍,它本质上是一套 Agent 运行时,说白了就是专门把大模型推理能力、外…

2026/10/14 11:33:23

数据分析师工作真实要求与CDA二级备考经验全解析

我从统计专业毕业后,在一家做零售供应链的公司干了三年数据分析。这三年里换过两个业务方向,带过两个新人,也亲眼见过不少“看起来什么都会”的候选人入职以后水土不服。三年下来我最大的感受是:数据分析师这个岗位的要求&#xf…

2026/10/14 11:33:23

Android登录页工程实践:从Studio新建项目到真机上线

1. 这不是“画个按钮就完事”的登录页:为什么Android Studio里一个登录页面能卡住80%的新手在某高校移动开发实训课上,我带过一批刚接触Android开发的A同学。他们用Android Studio新建项目后,第一件事就是打开activity_main.xml,拖…

2026/10/14 11:33:23

NLP微博情感分类实战源码解析:数据清洗、中文分词与模型选型之路

简介:一份面向自然语言处理情感分析新人的微博内容情感分类实战源码包,完整覆盖数据分析、文本预处理、模型训练与评测流程,适合正在入门深度学习与自然语言处理的学生或开发者对照学习。包内共有二十五个文件,含九个脚本、七张训…

2026/10/14 11:28:22

背单词进度管理:告别无效努力,轻松扩充词汇量

引言 你是否有过这样的经历:为了扩充词汇量,每天埋头苦背单词,却发现效果不佳,甚至遗忘率极高?今天,就让我们一起探讨如何通过科学的背单词进度管理方法,告别无效努力,轻松扩充词汇量…

2026/10/14 11:31:03

Python调用Gemini Structured Outputs实现工单路由门禁

客服工单最怕的不是模型“答错一句话”,而是它给出一段看起来合理的说明,程序却从中猜错优先级。通俗做法是:要求模型只交 JSON(JavaScript Object Notation,轻量数据格式),再让代码验证它。Gem…

2026/10/13 17:09:18

Spring Boot超市进销存系统毕设实战:从需求拆解到答辩通关

最近带的一个学生项目组里,有A同学跑来问我:选什么毕设题目最稳妥,既能让评审老师觉得工作量够,又不会在答辩时被问到语无伦次。我第一反应就是推荐基于Spring Boot的超市仓库管理系统——也就是超市进销存系统。这个题目乍一看平…

2026/10/14 2:32:55

Flutter StatefulWidget 生命周期核心解析

很多刚开始接触 Flutter 的朋友,在看完一堆“Hello World”和基础组件之后,大概率都会撞上同一堵墙:StatefulWidget 里那堆 initState、build、dispose 方法,到底什么时候被调用?为什么顺序是那样?在里面到…

2026/10/14 0:00:33

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:33

macOS/iOS高精度计时:mach_absolute_time原理与实战

1. 项目概述:为什么mach_absolute_time是 macOS/iOS 时间测量的“黄金标准”在 macOS 和 iOS 开发中,我见过太多人用CFAbsoluteTimeGetCurrent()或NSDate.timeIntervalSinceReferenceDate做性能打点,结果在高精度场景下被系统时钟跳变、NTP 同…

2026/10/14 0:00:33

SCORM课件演示与测试全解析:从API通信到自动化验证

简介:这是一套遵循SCORM标准的交互式课件演示与测试资源,面向E-Learning课程开发者、LMS平台测试人员及在线教学从业者,用于验证课件在不同学习管理系统中的识别、传递与跟踪能力。压缩包共28个文件,约12.07MB,以swf动…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑