Agent Skill 体系全解:从渐进式披露到生产级管控

📅 2026/8/2 3:28:18
Agent Skill 体系全解:从渐进式披露到生产级管控
一、什么是 Skill从「硬编码 Prompt」到「可组合的 SOP 包」在没有 Skill 之前Agent 工程里最常见的「领域能力复用」就是把一段固定的 Prompt 拼到 System Message 末尾、或者封装成一个 Go/Python 工具函数。这种方式的问题很明显上下文爆炸每个领域 SOP 几百行10 领域一次性全部塞进 system prompt首轮 token 就爆了。模型选择刚性文档解析、代码生成、数据清洗三种工作流可能各自需要不同的模型但 System Prompt 级别的拼法无法做到某段流程切模型。版本管理混乱Prompt 写在 Go 字符串里改一行 SOP 重新编译发布跨项目复制粘贴 分叉漂移。Skill以SKILL.md为载体是 2025 年由 Anthropic 确立、并被 CloudWeGo/eino 等主流 Agent 框架实现的一种开放式 AI 代理构建标准。它本质上是「一份标准化操作手册SOP」「一组执行策略元数据」的打包体由框架在运行时按需加载。一份典型的 Skill 目录结构textskills/ ├── pdf-batch/ │ ├── SKILL.md ← 技能定义YAML FrontMatter Markdown Body │ ├── scripts/ │ │ └── extract.py ← Skill 正文里引用的辅助脚本 │ └── examples/ │ └── config.yaml ← Skill 正文里提到的参考文件 └── web-research/ └── SKILL.mdSKILL.md采用 YAML FrontMatter Markdown Body 双段结构markdown--- name: pdf-batch description: 批量 PDF 提取文本并重命名。当用户提到PDF 提取、批量 PDF2txt、扫描目录 PDF时使用单个小 PDF 文件不要使用。 context: fork # 执行模式inline | fork | fork_with_context agent: worker # 交给哪个子 Agent 执行仅 fork 模式生效 model: gpt-4o # 执行时切换的模型仅 fork / inline 模式生效 --- # PDF 批量处理工作流 ## 前置检查 先用 ls 确认输入目录存在不存在先跟用户确认。 ## 步骤 1枚举 ls {input_dir}/*.pdf → 拿到文件列表50 个建议先分组并发 ## 步骤 2提取 调用 {BaseDir}/scripts/extract.py --input abs_path --output out_dir 失败回退python pypdf 直接实现 ## 步骤 3命名 从首页提取 Author / Year / Title格式 {Author}-{Year}-{Title}.txt 重命名冲突先 (1)不要覆盖用户已有文件Skill 的双重身份对框架来说它是{Name, Description, Context, Agent, Model} Content BaseDir的结构化数据。对模型来说它同时是「名片」NameDescription做召回和「操作手册」Content指导后续执行步骤。二、完整执行流程5 个节点串联抛开所有技术术语Skill 的完整运行流程可以拆解为 5 个核心节点节点 1启动时扫目录但只看标题Agent 启动时扫描指定的 Skill 存放目录。只做一件事把每个 Skill 文件夹的名字和一句话介绍摘出来记在一个列表里。绝对不看那些几百行的详细操作步骤。结果把这个名字介绍列表放进 Agent 的初始系统提示里同时在工具箱里只放 1 个名叫skill的工具。节点 2根据用户问题选一个匹配的用户发来一个问题比如帮我把这些 PDF 合并一下。Agent 把这个问题和自己系统提示里的名字介绍列表做比对。如果发现某个 Skill 的介绍和用户问题对得上Agent 就调用那唯一的skill工具并把选中的 Skill 名字作为参数传进去。节点 3真正去读操作手册并决定谁来做skill工具被调用后① 去硬盘里找到对应的 Skill 文件夹把完整的SKILL.md操作手册读出来② 检查手册头部标注的context类型inline把读出来的完整操作手册原文作为结果返回给当前 Agent。fork新建一个独立的子 Agent把操作手册丢给它让它在后台从头做到尾。等子 Agent 做完后只把最终结果压缩成一段话返回。fork_with_context同上但子 Agent 会携带父对话历史。节点 4照着操作手册一步步执行仅inline模式当前 Agent 拿到节点 3 返回的完整操作手册这是它第一次看到具体步骤。于是它照着手册里的描述一步步调用各种基础工具运行脚本、读文件、写文件等把手册上的每个步骤都执行完。节点 5整理结果回复用户Agent 把执行完的所有结果汇总整理成一段通顺的自然语言发送给用户。三、四种注入位置Skill 向 Agent 传递信息的 4 个通道注入位置注入内容发生时机作用① System Promptavailable_skills列表所有 Skill 的 Name DescriptionAgent 启动时节点 1让模型知道有哪些技能可用做召回决策② Tool Schema1 个名为skill的工具参数为{skill: string}Agent 启动时节点 1让模型能够通过调用工具来触发 Skill 加载③ ToolMessageSKILL.md的完整正文操作手册skill工具被调用后节点 3inline模式让模型第一次看到完整步骤开始执行④ 子 Agent 初始消息SKILL.md的完整正文 父对话历史仅fork*模式skill工具被调用后节点 3fork*模式让子 Agent 直接带着操作手册开始干活注意一个反直觉事实不管你有 10 个还是 100 个 Skill在 Tools 集合里都只会出现一个工具即②中的skill工具。这是「渐进式披露」的前提条件。四、三种执行模式context字段的三种取值SKILL.md头部的context字段控制拿到操作手册后谁来执行、怎么执行模式执行方式上下文隔离适用场景inline默认当前 Agent 自己读手册自己一步步执行不隔离所有中间步骤都在主对话里SOP 需要和用户交互、需要结合其他上下文fork新建独立子 Agent手册丢给它子 Agent 从头做到尾只返回最终结果完全隔离父 Agent 看不到中间过程SOP 很重、步骤多、会输出大量中间信息避免撑爆主上下文fork_with_context新建独立子 Agent但会把父对话历史也一并复制给它隔离但带上下文子流程需要知道用户的历史输入如之前给的路径五、渐进式披露解决 Context Bloat 的核心设计5.1 为什么要「渐进」如果不做渐进式披露支持 100 个 Skill 的系统首轮 System Prompt 就是 100 × 几百行 几万 token 起步同时「Description 太泛 → 模型误选」「Description 太细 → Token 爆炸」的 trade-off 永远无解。Skill 体系的解法非常克制只在合适的层级提供合适粒度的信息。5.2 四层披露金字塔层级信息内容展示时机消费方L1 名片仅Name 1-3 行Description每个模型首轮推理都能看到节点 1模型做召回决策Token 开销极小L2 阻塞语义强制约束命中时必须先调skill工具首轮 System ToolInfo 同时节点 1约束模型不要跳过 Skill 直接干活L3 操作手册SKILL.md的 Markdown Body完整步骤只有成功执行skill工具后才注入节点 3Agent 拆解具体动作L4 资源文件脚本、配置、示例等辅助文件只有当 SOP 正文提到并触发execute/read_file后才被读取Agent 按需加载不占上下文5.3 渐进式披露的两个关键锚点L1 永远只返回名片Backend.List()只读取 FrontMatter不读任何 Skill 的 Content。L3 才读正文skill工具的InvokableRun内部才调用Backend.Get(name)真正读取SKILL.md。六、敏感操作监测三层拦截机制Skill 体系本身不自动监测敏感操作而是通过三层人为配置实现拦截层级 1SOP 正文里写死强制确认指令在SKILL.md操作手册里由编写 Skill 的人主动标注危险步骤markdown## 步骤 3删除临时文件 **⚠️ 危险操作必须执行确认** 调用 user_confirm 工具传入 - message: 即将删除目录 /tmp/cache 下所有临时文件是否继续 - risk_level: high 仅当 user_confirm 返回 confirmedtrue 后才执行下一步的 rm 命令。层级 2WrapToolCall 中间件拦截在框架层加一个全局拦截器在执行任何工具调用之前先检查命令或参数是否包含敏感关键词检查维度敏感关键词示例命令本身rm -rf、truncate、drop table、kubectl delete目标路径/etc/、/prod/、/data/live/工具名称delete_file、remove_directory命中后先调用user_confirm向用户发起确认请求收到确认后才放行。层级 3Skill Registry 白名单在节点 1启动加载阶段就不把敏感 Skill 加载给普通用户yamlname: db-drop-production description: 删除生产环境数据库表 permission: admin-only # 只有管理员才能看到Backend.List()根据当前用户角色过滤不匹配的 Skill根本不会出现在available_skills列表里普通用户连误选的机会都没有。三层如何串联层级拦截时机覆盖范围谁负责配置层级 1SOP 写确认执行到某一步时只覆盖写了的步骤Skill 编写者层级 2中间件拦截任何工具调用前全局自动覆盖框架运维者层级 3白名单过滤Agent 启动加载时整个 Skill 不可见权限管理员生产组合方式层级 3 让普通用户根本看不到高危 Skill层级 2 在最后关头兜底拦截层级 1 作为第一道防线在 SOP 里明确告知 Agent 必须先确认。七、生产级管控8 条工程规范7.1 元数据治理Description是召回率生命线L1 名片是模型唯一的预触发信息。写得好 模型选得准写得差 该用不用或乱用。写 Description 的模板yamldescription: | [触发条件正向]当用户提到 关键词 时使用 [适配反例] 不要用于 明确不适用的场景给出替代做法 [上下文条件] 需要 某个前置配置 才能工作 [产物说明] 产出 具体产物类型 到 约定路径7.2 路径治理让 Agent 绝不写错路径Agent 执行execute时经常忘记加BaseDir这是排名第一的 Skill 失败原因BuildContent 预渲染绝对路径推荐将{{BaseDir}}/xxx在返回前全部替换为skill.BaseDir /xxx。SKILL.md顶部加硬约束ALL FILE REFERENCES MUST USE ABSOLUTE PATH: skill.BaseDir。WrapToolCall cwd 注入自动前置cd BaseDir 。7.3 目录治理一级子目录约定Eino 自带的FilesystemBackend只扫描BaseDir/*/SKILL.md的一级子目录。需要分类层级时可方案 A保留一级目录Name写 qualified name如office-suite/pdf-batch。方案 B自行实现Backend接口递归扫描**/SKILL.md。7.4 模式选择治理决策表场景推荐模式不推荐原因SOP 需要和用户交互、和其他工具混用inlinefork后父子隔离做不到澄清SOP 很重会输出大量中间信息forkinline会把父 Context 撑爆子流程需要知道用户历史输入fork_with_contextfork看不到父历史需要切换专属模型且严格隔离forkmodelinline模型切换延迟一轮生效7.5 依赖治理自检 SOP 失败回退链markdown## Step 0环境自检必须先跑 1. 先执行BaseDir/scripts/selfcheck.sh - 成功 → 进入 Step 1 - 失败 → 尝试 pip install xxx仍失败走降级路径 2. 降级路径不用脚本用内联实现 3. 仍失败 → 通知用户给出三条手动替代命令7.6 权限治理Skill 级白名单 破坏性操作强制审批敏感 Skill 只在特定 RBAC 角色下才出现在available_skills中。高危命令在 SOP 里明确写执行前先调用user_confirm。7.7 版本治理Skill Registry 变更审计所有 Skill 放独立 Git 仓库加version字段发布走 MR/PR。Backend按project env拉取不同 tag 的 Skill。开启 Callbacks 打点记录skill_name, skill_version, success/failure, latency按版本号定位并一键回滚。7.8 用户体验治理区分「加载说明书」和「真正执行」inline模式下默认返回Launching skill: xxx让用户误以为已经在跑。应改写为Loaded instructions for skill: xxx下一步将按此步骤执行并在前端附加轻提示。八、总结Skill Prompt 工程 配置管理 Agent 编排 的交集维度Tool本地函数MCP远程函数SubAgenttaskSkillSKILL.md本质可执行函数远程可执行函数协议拉起一个独立 Agent 端到端跑一份 Markdown SOP 运行时策略被模型看到的方式每个工具一条 ToolInfo每个工具一条 ToolInfo每个 SubAgent 一条 desc所有 Skill 的 NameDesc 拼进1 个skill工具的描述任务执行形态一次调用 一次原子动作同上一次调用 子 Agent 全流程跑完inline 先加载 SOP后续 N 轮执行fork* 内部独立 Agent 跑完模型切换不支持不支持SubAgent 级别可切通过model字段切换动态参数注入通过函数参数通过 JSON 参数通过inputs传递通过CustomToolParams钩子注入并渲染进 SOP上下文隔离不隔离不隔离默认隔离inline不隔离fork*隔离改动成本改代码 → 重新编译改 MCP Server 部署改配置 重新编译改SKILL.md→ 发布目录即可如果把 Tool 比作「螺丝刀」MCP 是「外采的电动工具」SubAgent 是「外包同事」那么 Skill 更像一份放在抽屉里、随时取出、上面还贴着步骤图解和质检清单的《标准作业指引》——它不改变底层工具有多少、同事能力有多强但把「怎么组合这些东西能稳定地、合规地、可审计地把一件事做完」的知识沉淀到了独立可复用的载体里。这就是为什么生产级 Agent 体系无论底层框架怎么换Skill或类似SKILL.md格式的标准载体一定会成为工程化落地的基础构件。