
最近做Agent项目时绕不开的一个东西就是 agent-skills也就是技能库。我一开始觉得它就是普通的工具调用封装实际用下来才发现它解决的远不止能不能调API这个层面。真正头疼的是模型面对没见过的文件格式、一连串需要前后衔接的操作、还有反复出错的任务时怎么让它稳定地高质量完成。如果你也在搞Agent应用、自动化办公脚本或者正在被模型很聪明但一操作就废的问题折磨这篇文章应该能帮到你。我会按照自己踩过的坑和复盘出来的路径把技能库从设计思路、目录结构、核心文件怎么写到多技能组合工作流再到排查问题的方法完整过一遍。内容偏工程实操不堆概念尽量给直接能用的东西。1. 为什么需要Agent Skills1.1 模型的天花板纯靠推理解决不了操作型任务大语言模型本身是语言模型它擅长的是文本理解和生成而不是执行操作。你可以让它写出打开文件的Python代码但如果你真给它一个上百页的PDF让它自己提取表格、处理合并单元格、输出规范的Excel它往往会在生成的代码里漏掉编码处理、忘记处理空值、甚至直接编造一个不存在的库。原因不是模型不聪明而是这类任务涉及大量文件格式细节、系统环境差异、异常分支光靠模型在对话窗口里临场写代码成功率非常不稳定。我做个类比模型像一个理论功底很好但从不进厨房的厨师。你让他说一道菜的菜谱他能说得头头是道但真要他上手切菜、掌握火候、面对锅糊了怎么办他就懵了。Agent Skills就是给这位厨师配备一套处理好的半成品食材、标准化的操作卡和专用厨具他只需要按照操作卡调用对应工具就能稳定做出一道菜来。1.2 从工具调用到技能调用的进化早期Agent靠Function Calling也就是把每个API封装成一个函数让模型根据用户需求选函数并填参数。这个模式在简单场景下够用但问题很快暴露出来一个任务往往不是一次函数调用能完成的。比如帮我分析这份财报并生成PPT你需要先读取PDF再提取关键指标再算同比增长再做图表再排版PPT。如果把这些都摊成一个一个细粒度的函数模型很容易在选函数和拼参数的过程中迷失上下文被大量函数定义塞满真正有用的对话内容反而被挤掉。技能库的思路就不一样把一套完整的能力打包成技能。每个技能自带说明文档、脚本、依赖、甚至运行环境。模型不需要理解内部实现细节只需要知道遇到PDF提取任务时调用pdf_extract技能传文件和目标路径。这种封装极大地降低了模型的决策负担也让能力的复用变得非常自然。1.3 技能库解决的核心问题用下来我觉得技能库至少解决了三个核心问题。第一是能力标准化。以前每个人调文件解析的方式都不一样有人用PyPDF有人用pdfplumber处理结果五花八门。技能库把一套成熟方案的调用方式固定下来所有Agent共用输出格式也统一。第二是安全边界。技能脚本通常在受限沙箱里运行有文件读取白名单、网络限制、执行超时控制。这比让模型随意执行自己生成的代码安全得多至少不会因为一句提示词注入就删库跑路。第三是调试友好。技能是独立模块可以单独测试。哪一步出了问题可以精准定位到具体技能而不是在一堆模型生成的代码里大海捞针。2. 核心架构与设计思路拆解2.1 一份技能由哪几部分组成一个标准的技能目录通常包含下面这些内容。我拿最常见的文件解析类技能举例pdf-extractor/ ├── SKILL.md # 技能说明文档核心中的核心 ├── scripts/ │ ├── extract.py # 实际执行逻辑 │ └── requirements.txt # 依赖清单 ├── assets/ # 可选资源模板文件等 └── metadata.json # 版本、作者、描述等元信息这里面最重要的是 SKILL.md。它决定模型在什么场景下会想到用这个技能、怎么用、有哪些坑需要避开。脚本只是执行细节是手SKILL.md是脑模型完全是靠读它来做决策的。2.2 SKILL.md是核心不是脚本很多新手会把精力全放在写脚本上脚本写得挺复杂SKILL.md就随便写两句结果Agent根本不会主动调用这个技能。我后来才明白模型不会去读你的代码它只看你写的说明。所以SKILL.md必须包含几块关键信息功能概述一句话说清楚这个技能做什么。触发条件什么情况适合用、什么情况绝对不要用。输入参数每个参数的格式、示例、是否必填。输出格式返回什么结构的数据方便模型进一步处理。使用步骤最好给一个具体的命令行示例。注意事项已知的坑比如大文件会超时、某些PDF是扫描版需要OCR等。我见过一个写得很好的SKILL.md开头就有这么一句当用户要求提取PDF中的文字或表格且文件路径是本机路径时使用本技能。如果PDF是扫描图片型请先告知用户可能无法提取或建议使用OCR技能。 这种描述就非常精准模型一看就知道该不该用。2.3 沙箱与权限隔离技能执行环境需要隔离。我目前遇到的主流做法是容器化或轻量虚拟机每个技能独立跑在一个环境里有CPU、内存、文件系统限制。参数通过环境变量或命令行传入结果通过标准输出返回。这样模型就算被恶意PDF内容引导也做不了超出边界的事。实际项目中我倾向于把技能分成可信和不可信两类像本地文件处理、计算类技能权限可以放开一些像网络搜索、下载内容解析这类就必须严格隔离执行完后清理所有临时文件。3. 实操从零接入一个技能库3.1 安装与目录约定接入技能库的第一步是确定技能放哪里。现在不少Agent框架支持在项目根目录建一个skills文件夹或者通过配置项指定SKILLS_DIR。我自己习惯的目录结构是project/ ├── skills/ │ ├── pdf-extractor/ │ ├── pptx-builder/ │ └── chart-renderer/ ├── agent_config.yaml └── main.py然后在配置里注册技能目录Agent启动时会自动扫描。注册完之后可以写一条测试消息比如从test.pdf里提取文字看日志里有没有出现技能加载记录。如果没有八成是路径没对或者SKILL.md头部格式不符合框架要求。3.2 写一个自己的技能以长文本摘要为例为了让你有体感我现场走一遍自己写技能的过程。假设我现在要做一个分段摘要技能解决超长文本模型放不下的问题。第一步建目录。mkdir skills/chunked-summarizer cd skills/chunked-summarizer第二步写 SKILL.md。--- name: chunked-summarizer description: 将超过上下文长度的长文本分段后逐段总结适合处理书籍、长报告等。 --- # Chunked Summarizer 对长文本进行分段摘要避免截断。输入必须是纯文本文件的路径输出为JSON格式包含每段摘要和总体摘要。 ## 触发条件 - 用户要求总结的文本明显超过模型上下文窗口长度 - 用户提供一个或多个长文本文件需要概括要点 ## 输入参数 - input_paths: 字符串数组表示待处理的txt文件路径 - chunk_size: 可选默认3000字符 - overlap: 可选默认200字符 ## 示例 python scripts/summarize.py --input_paths /tmp/a.txt --chunk_size 3000第三步写脚本。下面是个简化的可实现版本import argparse import json def split_text(text, chunk_size3000, overlap200): chunks [] start 0 while start len(text): end start chunk_size chunks.append(text[start:end]) start end - overlap return chunks def summarize(chunk): # 这里可以调用LLM也可以使用简单的抽取式摘要 # 实际项目我会把chunk发送给模型并附上摘要指令 return chunk[:100] ... if __name__ __main__: parser argparse.ArgumentParser() parser.add_argument(--input_paths, nargs, requiredTrue) parser.add_argument(--chunk_size, typeint, default3000) parser.add_argument(--overlap, typeint, default200) args parser.parse_args() results [] for path in args.input_paths: with open(path, r, encodingutf-8) as f: text f.read() chunks split_text(text, args.chunk_size, args.overlap) chunk_summaries [summarize(c) for c in chunks] results.append({ path: path, chunk_count: len(chunks), summary: .join(chunk_summaries) }) print(json.dumps(results, ensure_asciiFalse))这里我没有接具体的大模型接口实际用的时候你可以在summarize函数里调用自己的模型服务。重点不是代码本身而是要让脚本的输入输出足够清晰模型能无障碍地调用它。第四步测试。我强烈建议先脱离Agent框架在终端里手动跑一遍脚本确认输入参数和输出格式没问题再放回技能库。不然到时候分不清是脚本错误还是模型调用错误。3.3 让Agent在对话中调起技能技能接入后Agent会在对话中尝试调用它。有的框架会在日志里打印类似 Use skill chunked-summarizer with args {...} 的信息。这时候多观察调用的次数和频率。如果模型一直不调用我通常做两件事一是检查SKILL.md里的功能描述是否和用户表达习惯匹配二是把技能调用示例放进系统提示词里给模型一个示范。我还发现一个细节很多模型对技能是否会改变系统状态有顾虑。如果SKILL.md里明确写了本技能只读文件、不修改原始内容、不调用网络模型调用意愿会高很多。这可能是因为模型觉得风险低所以更愿意使用。4. 多技能协作与工作流编排4.1 技能组合文档解析到自动生成报表单一技能是零件多个技能组合起来才是完整流水线。我做过一个财务周报自动化流程整个过程用到了三个技能pdf-extractor解析供应商发来的PDF账单提取金额、日期、项目名称。>