1. 从「人读文档」到「AI读文档」的范式转移
过去两年,我一直在做 AI Agent 相关的工程落地,从最早的 Prompt 工程到后来的工具调用、多 Agent 协作,踩过的坑比写过的代码还多。但最近半年,一个明显的变化让我意识到风向真的变了:GitHub 上那些涨星最快的项目,不再是某个炫酷的模型或者框架,而是一堆看起来「不像代码」的东西——技能包、能力描述文件、Agent 行为规范文档。
superpowers、deepseek-harness 这类项目霸榜,本质上反映了一个被大多数人忽略的事实:当模型能力逐渐趋同,决定 Agent 实际表现的,不再是模型本身,而是你喂给它的「说明书」写得好不好。
这个判断听起来有点反直觉。毕竟过去我们习惯的思路是「模型越强,效果越好」,但实际做过 Agent 落地的人都知道,同一个模型,换一套工具描述文档,任务成功率能从 40% 跳到 85%。这不是玄学,而是因为 Agent 的工作机制决定了它对「结构化上下文」的依赖远超普通对话场景。
所谓「写给 AI 看的文档」,核心就是一件事:用 AI 能高效解析、准确执行的方式,把人类的知识、流程、约束条件编码成结构化文本。它和传统技术文档最大的区别在于,读者不是人,而是模型。人读文档可以靠常识补全、靠经验推断,但 AI 不行——你没写清楚的,它就真的不知道;你写模糊的,它就自由发挥。
这篇文章适合三类人看:一是正在做 Agent 应用开发但效果不稳定的工程师;二是想把内部流程、领域知识封装成 Agent 能力的产品或运营同学;三是对「技能包」这个新物种好奇、想知道它到底解决什么问题、怎么落地的人。我会从实际项目经验出发,把技能包的设计逻辑、文档结构、常见坑和优化技巧全部拆开讲清楚。
2. 技能包到底解决什么问题:Agent 能力落地的三层困境
2.1 第一层困境:模型知道怎么做,但不知道你要它怎么做
这是最容易被忽视的问题。大模型在预训练阶段已经见过海量的代码、文档、教程,它「知道」怎么写一个 React 组件、怎么调一个 REST API、怎么做数据清洗。但知道归知道,它不知道你的项目用什么构建工具、你的 API 鉴权方式是什么、你的数据字段命名规范是什么。
我见过太多团队在这个问题上浪费时间:反复调 Prompt、换模型、加 few-shot 示例,但效果始终不稳定。根本原因在于,他们把「领域约束」和「任务指令」混在一起塞进对话里,导致模型每次都要在大量噪声中重新理解上下文。
技能包的做法是把这部分「领域约束」抽出来,做成独立的、可复用的结构化文档。模型在执行任务前先加载技能包,相当于拿到了一份「项目专属操作手册」,不需要每次从零推断。
2.2 第二层困境:工具描述的质量决定了工具调用的准确率
Function Calling 是 Agent 的核心能力,但很多人写工具描述的方式极其随意。我见过一个真实案例:某团队定义了一个search工具,描述只写了一句话「搜索相关信息」。结果模型在需要查数据库的时候调它,需要查网页的时候也调它,甚至需要做计算的时候还在调它。后来他们把描述改成「根据关键词在内部知识库中检索文档片段,返回最相关的前 5 条结果,适用于事实性查询,不适用于数值计算和实时数据获取」,调用准确率直接从 52% 提升到 89%。
这个案例说明一个关键点:工具描述不是给人看的注释,而是给模型看的接口契约。它需要明确回答三个问题——这个工具做什么、什么时候用、什么时候不用。大多数技能包项目之所以有效,就是因为它们把这部分做到了极致。
2.3 第三层困境:多步骤任务的编排逻辑需要显式编码
单个工具调用好解决,难的是多步骤任务的编排。比如「分析一份销售数据并生成报告」这个任务,人类知道要先清洗数据、再做聚合、然后选图表类型、最后写结论。但模型不会自动按这个顺序走,它可能跳过清洗直接聚合,也可能在写结论的时候编造数据。
技能包在这里的作用是提供「流程模板」——把多步骤任务的执行顺序、每步的输入输出、步骤之间的依赖关系全部写清楚。这本质上是一种「显式编排」,用文档的形式把隐性的流程知识固化下来。
注意:流程模板不是越细越好。我试过把每个步骤拆到原子级别,结果模型反而因为步骤太多而迷失,执行到一半就开始跳步。后来发现,单个技能包的步骤控制在 5-9 步之间效果最好,超过这个范围就应该拆成多个技能包。
3. 一份合格技能包的解剖结构:六个必备模块
3.1 元信息层:让 Agent 知道「我是谁、我能干什么」
元信息层是技能包的门面,也是模型决定是否加载这个技能包的依据。它通常包含技能名称、一句话描述、适用场景标签、版本号。看起来简单,但写好不容易。
我见过最常见的错误是描述写得太泛。比如「数据处理技能包」这种描述,模型根本判断不出什么时候该用它。好的描述应该像这样:「清洗 CSV 格式的销售数据,处理缺失值、异常值和重复行,输出标准化后的数据表,适用于结构化数据的预处理阶段」。
这里的关键是场景锚定——用具体的输入格式、处理动作、输出形态来限定技能的适用范围。模型在做技能路由时,靠的就是这些锚点信息。
3.2 能力边界层:明确「能做什么」和「不能做什么」
这一层是区分专业技能包和业余技能包的分水岭。大多数人只写「能做什么」,但「不能做什么」同样重要,甚至更重要。
举个例子,一个「文本摘要」技能包,如果只写「对长文本生成摘要」,模型可能会把代码、表格、JSON 都塞进去让它摘要。但如果你明确写上「不适用于代码文件、结构化数据和长度少于 200 字的文本」,模型就会在这些场景下主动寻找其他技能包。
能力边界的写法建议用「适用/不适用」的对照结构,比单纯列功能清单清晰得多。我在实际项目中验证过,加上「不适用」说明后,技能误用率平均下降 35% 左右。
3.3 输入输出契约层:把接口定义做到无歧义
这一层是工程化程度最高的部分。输入契约需要说明:需要哪些参数、每个参数的类型和格式、哪些是必填哪些是可选、参数的取值范围。输出契约需要说明:返回什么结构、字段含义、可能的错误码。
我习惯用类似 JSON Schema 的方式来写,但不是直接贴 Schema,而是用自然语言加示例的方式表达。原因是模型对自然语言的理解比对纯 Schema 更灵活,尤其是在处理模糊输入时。
输入: - 数据文件路径: 字符串, 必填, 支持 .csv 和 .xlsx 格式 - 目标字段: 字符串列表, 必填, 指定需要处理的列名 - 缺失值策略: 枚举, 可选, 默认 "drop", 可选值: drop/fill_mean/fill_median 输出: - 处理后的数据: 保存到原路径同级的 output 目录 - 处理报告: 包含处理前后的行数对比、各字段的缺失率变化这种写法比纯 Schema 啰嗦,但模型执行时的准确率明显更高。我的理解是,自然语言描述提供了「意图上下文」,而结构化格式提供了「执行约束」,两者结合效果最好。
3.4 执行流程层:把隐性知识显性化
执行流程层是技能包的核心,也是最考验编写者对业务理解深度的地方。它需要把「一个熟练工做这件事的步骤」完整写出来,包括每步的操作、判断条件、异常处理。
写这一层的时候,我建议用「步骤 + 判断 + 回退」的结构。比如:
- 读取数据文件,检查文件是否存在且格式正确
- 如果文件不存在,返回错误码 E001 并提示用户检查路径
- 解析数据,统计各字段的缺失率
- 如果某字段缺失率超过 50%,标记为「建议删除」并在报告中说明
- 按缺失值策略处理剩余缺失值
- 检测异常值(超过 3 倍标准差),标记但不自动删除
- 输出去重后的数据和处理报告
这种写法的好处是,模型不仅知道「做什么」,还知道「遇到什么情况该怎么处理」。实测下来,带异常处理分支的技能包,任务成功率比不带的高出 20 个百分点以上。
3.5 示例层:用具体案例锚定预期行为
示例层是很多技能包忽略的部分,但它对模型的行为校准非常关键。一个好的示例应该包含:输入样例、期望的输出、以及关键的处理逻辑说明。
我通常会在示例层放 2-3 个案例,覆盖典型场景和边界场景。比如一个数据清洗技能包,我会放一个「正常数据」的案例、一个「大量缺失值」的案例、一个「格式错误」的案例。这样模型在面对不同输入时,有参照物可以对齐。
提示:示例不要写太多,3 个左右足够。写多了会占用大量上下文窗口,反而挤占了模型处理实际任务的空间。而且示例之间要有多样性,不要三个都是同一种情况。
3.6 约束与禁忌层:划出不可逾越的红线
这一层是安全兜底。它明确告诉模型:哪些操作绝对不允许、哪些输出格式必须遵守、哪些情况下必须停下来询问用户。
比如一个涉及数据修改的技能包,约束层应该写明:「禁止在未备份的情况下直接覆盖原始文件」「禁止删除任何字段,只能标记」「如果处理后的行数减少超过 30%,必须暂停并请求用户确认」。
这些约束看起来是常识,但模型没有常识。你不写,它就敢直接覆盖原文件。我踩过这个坑,一个批量重命名的技能包没写备份约束,结果模型把一批测试文件的原始名称全改了,恢复起来极其麻烦。
4. 技能包设计的五个反直觉经验
4.1 写得越详细,效果不一定越好
这是我最开始做技能包时最大的误区。我以为把每个细节都写清楚,模型就能执行得更准确。结果恰恰相反——当技能包超过一定长度后,模型开始「丢失重点」,把注意力分散到无关紧要的细节上。
后来我总结出一个经验:技能包的详细程度应该和任务的复杂度匹配,而不是和你的知识量匹配。一个简单的格式转换任务,技能包控制在 300 字以内就够了;一个涉及多步骤决策的复杂任务,可以到 1500 字左右。超过 2000 字的技能包,就应该考虑拆分了。
拆分的逻辑是按「决策边界」拆,而不是按「功能模块」拆。比如一个「数据分析」技能包,不要拆成「数据清洗」「数据聚合」「图表生成」三个,而是拆成「探索性分析」和「报告生成」两个——因为这两个任务的决策逻辑完全不同。
4.2 否定式描述比肯定式描述更有效
这个发现来自一次 A/B 测试。我们有两个版本的技能包,A 版写「适用于处理结构化数据」,B 版写「不适用于处理非结构化文本、图像和音频」。结果 B 版的技能误用率比 A 版低了 40%。
我的理解是,模型在判断「是否适用」时,否定条件比肯定条件更容易匹配。因为肯定条件往往是开放的(「结构化数据」的边界很模糊),而否定条件是封闭的(「非结构化文本」的边界很清晰)。
所以我现在写技能包,会刻意多写「不适用」场景,而且写得越具体越好。比如不写「不适用于大数据」,而是写「不适用于单文件超过 100MB 或行数超过 50 万行的数据集」。
4.3 技能包的「触发词」需要精心设计
技能包不会自动生效,需要模型判断「当前任务是否应该加载这个技能包」。这个判断依据就是触发词——技能包描述中那些和任务匹配的关键词。
触发词设计有个技巧:用任务的动作词,而不是领域的名词。比如一个「合同审查」技能包,触发词不要写「合同」「法律」「条款」这些名词,而要写「审查」「比对」「提取关键条款」「检查风险点」这些动作词。因为模型在路由时,匹配的是「用户想做什么」,而不是「用户提到了什么领域」。
我做过对比测试,用动作词做触发词的技能包,路由准确率比用名词的高出 25% 左右。
4.4 版本管理比你想的重要
技能包是需要迭代的。每次模型更新、业务规则变化、发现新的边界情况,都需要修改技能包。如果没有版本管理,你很快会陷入「不知道当前生效的是哪个版本」的混乱。
我的做法是给每个技能包加版本号,并且在元信息层写清楚「本版本相对于上一版的变更点」。这样当效果出现波动时,可以快速定位是不是技能包变更导致的。
另外,技能包的修改建议走「小步快跑」的策略——每次只改一个点,改完立刻测试。不要一次性大改,否则出了问题根本不知道是哪个改动导致的。
4.5 技能包需要「测试用例」来验证
这是很多团队忽略的环节。技能包写完后,不能凭感觉觉得「应该没问题」就上线,需要用一组标准测试用例来验证。
我的测试用例通常包含三类:正常场景(验证基本功能)、边界场景(验证异常处理)、对抗场景(验证约束是否生效)。每类 3-5 个用例,覆盖技能包的主要路径。
测试的时候重点看两个指标:任务成功率(能不能正确完成)和约束遵守率(有没有违反禁忌)。两个指标都达标才算通过。我见过太多技能包功能没问题,但约束遵守率很低,模型总是「顺手」做了不该做的事。
5. 从零构建一个技能包的完整实操
5.1 第一步:确定技能边界,画一张能力地图
动手写之前,先想清楚这个技能包要覆盖什么、不覆盖什么。我习惯画一张简单的能力地图:横轴是输入类型,纵轴是处理动作,把要覆盖的组合标出来。
比如做一个「文档处理」技能包,输入类型有 PDF、Word、Markdown,处理动作有提取文本、提取表格、格式转换、内容摘要。如果全都要覆盖,这个技能包会非常臃肿。更好的做法是聚焦——比如只做「PDF 文本提取和摘要」,其他场景交给别的技能包。
这一步的产出是一句话的技能定位:「本技能包用于从 PDF 文档中提取正文文本并生成结构化摘要,不处理扫描件、不处理表格、不做格式转换。」
5.2 第二步:写元信息和能力边界
元信息要简洁,能力边界要具体。我通常先写能力边界,再反过来提炼元信息。因为能力边界写清楚了,元信息自然就出来了。
能力边界的写法参考:
- 适用输入:文本型 PDF,单文件不超过 50 页
- 不适用输入:扫描件、加密 PDF、包含大量表格的文档
- 适用任务:正文提取、章节识别、生成 200 字以内的摘要
- 不适用任务:表格数据提取、图像识别、格式转换
5.3 第三步:定义输入输出契约
这一步要具体到字段级别。输入参数要说明类型、是否必填、默认值、取值范围。输出要说明结构、字段含义、错误码。
我习惯用表格来组织这部分内容,清晰直观:
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
| file_path | string | 是 | 无 | PDF 文件的绝对路径 |
| summary_length | int | 否 | 200 | 摘要字数上限,范围 50-500 |
| extract_tables | bool | 否 | false | 是否提取表格,当前版本不支持 |
输出契约同样用表格,加上错误码说明。错误码要覆盖常见异常:文件不存在、格式不支持、解析失败、内容为空等。
5.4 第四步:编写执行流程
执行流程用有序列表写,每步包含操作和判断。我通常会把「正常路径」和「异常路径」分开写,正常路径用主流程,异常路径用「如果...则...」的格式补充。
写流程的时候有个技巧:用动词开头,用具体的操作描述,避免抽象词汇。比如不写「处理文档」,而写「使用 PDF 解析库读取文件,提取所有页面的文本内容,按页码顺序拼接」。越具体,模型执行时越不容易跑偏。
5.5 第五步:补充示例和约束
示例放 2-3 个,覆盖典型和边界场景。约束部分列出所有「绝对不能做」的事情,以及「必须停下来询问」的情况。
约束的写法要强硬,用「禁止」「必须」「不得」这类词。不要用「建议」「尽量」这种软性表述,模型对软性表述的执行率很低。
5.6 第六步:测试和迭代
写完后用测试用例跑一遍,记录成功率和约束遵守率。不达标的地方,回到对应模块修改。通常需要 2-3 轮迭代才能达到稳定状态。
迭代的时候有个原则:每次只改一个模块,改完立刻回归测试。不要同时改多个地方,否则无法定位问题来源。
6. 技能包生态的下一步:从单点能力到能力网络
单个技能包解决的是单点问题,但真实任务往往需要多个技能包协作。这就引出了下一个阶段的问题:技能包之间怎么组合、怎么路由、怎么处理冲突。
我目前看到的趋势是,技能包正在从「独立文件」向「能力网络」演进。每个技能包不仅描述自己的能力,还描述它和其他技能包的衔接关系——它的输出可以作为哪些技能包的输入,它在什么情况下应该把任务转交给其他技能包。
这种「技能包间协议」目前还没有统一标准,但已经有一些项目在尝试。比如用统一的元数据格式来描述技能包的输入输出,让路由层可以自动匹配上下游。这个方向如果跑通,Agent 的能力组合会变得非常灵活——就像搭积木一样,需要什么能力就加载什么技能包。
不过现阶段,我的建议还是先把单个技能包做到极致。因为技能包的质量决定了能力网络的上限,如果每个技能包本身就不稳定,组合起来只会更混乱。先把「写给 AI 看的文档」这件事做扎实,生态的事情可以边走边看。
在实际项目中,我现在会花大约 40% 的时间在技能包的设计和迭代上,这个比例还在上升。因为越来越明显地感觉到,Agent 的竞争力不在于用了什么模型,而在于你把领域知识编码成了什么样的技能包。这件事没有捷径,就是理解业务、拆解流程、反复测试、持续迭代。