最近社区里流行一句非常凝练的概括“Agent Skills Skills 架构的 Agent”。乍看像句废话但真正把 Agent 项目从“单体智能”推向“技能编排”的人基本都会认可这句话点破了要害Agent 本身不再需要把一切都塞进提示词它只是一个有调度能力的壳真正干活的是一个个独立、可复用、可测试的 Skills。这个思路在 Claude Code、Codex、OpenCode 和 LangChain/LangGraph 的 harness 开发里已经越来越常见也是吴恩达 Agent 教程里强调的“模型 工具 编排”的延伸。这篇文章我想从一个实际做 Agent 开发的角度把 Skills 架构的核心概念、标准结构、落地步骤和踩坑经验一次性讲清楚。不管你是刚开始接触 Agent 开发还是已经在用 Claude Code 手动装 GitHub 上的 Skills都可以从里面找到能直接拿去用的东西。1. 先厘清概念Agent 与 Skills 到底什么关系1.1 一个看似简单但总有人搞混的问题很多初学者会把 Skills 理解成工具的另一种叫法或者干脆当成 Agent 的插件。这个理解不能说全错但会直接影响后续的架构设计所以值得掰开讲。工具tool是执行单个动作的最小单元比如一个函数、一条命令、一次 API 调用。Skill 则是一个围绕完整能力的自包含包它可能包含多个工具调用、一段脚本、一份说明文档、依赖清单甚至包含测试用例。Agent 是持有模型、上下文和调度逻辑的主体它负责理解用户意图、决定在什么时机调用哪些 Skills并把结果汇总成最终答案。用一个生活化的类比工具是刀Skill 是“会做川菜的厨师”Agent 是“根据客人点菜安排厨师干活的后厨主管”。如果只给 Agent 一堆刀它还是要靠模型现想怎么做能力再强也容易翻车给它一组 Skill它就只需要做选择题。很多人做 Agent 失败不是因为模型不够聪明而是因为把太多动作细节堆在提示词里却没有把它们沉淀成可复用的技能包。1.2 等式到底在说什么“Agent Skills Skills 架构的 Agent”这句话本质上是在讲一种架构选择把 Agent 的能力拆成一组 Skills 之后Agent 本身被“降级”为框架和壳Skill 成为真正的一等公民。这个等式不是说 Agent 和 Skills 是同一个东西而是说——当你采用 Skills 架构时Agent 的核心工作就不是“自己做所有事”而是“编排和调度”。这种架构带来的直接好处非常明显。新增能力不需要改 Agent 主逻辑只需要新增一个 Skill修 bug 不用碰整个系统只动对应 Skill复用能力也简单把一个 Skill 目录拷到另一个项目里就行。社区里大量 Agent 项目之所以迅速转向这个思路就是因为单体 Agent 的维护成本实在太高了。1.3 为什么大家都从单体提示词转向这个架构从单体 prompt 到 Skills 架构的演进我是被三个现实问题逼着走过来的。第一个是上下文窗口的浪费把技能说明、示例、代码全部塞进 system prompt窗口很快被无关内容占满模型在长对话里还会被这些冗余信息干扰。第二个是能力边界不清晰在单体 Agent 里加一个新功能要重新设计整套提示词改一处行为可能影响所有任务。第三个是不可测试、不可回滚技能出了问题你无法单独验证只能回滚整个对话记录或者整个 Agent。Skills 架构把这些痛点拆开了。每个 Skill 有自己的描述文件、代码、依赖和测试Agent 只在需要时把对应技能说明加载进上下文执行完就卸载。这样上下文更干净、故障隔离更彻底、能力真正可插拔。如果让我给团队推荐一个起点我会说先别追求复杂的 Agent 框架先把一个 Skill 跑通再谈编排。2. Skills 架构的整体设计与拆解2.1 三个核心层调度层、技能层、运行时层一个标准 Skills 架构的 Agent 通常可以拆成三层。调度层负责理解用户意图、决定调用哪些 Skills、传递参数并汇总结果它内部可能包含意图识别、路由规则、上下文管理技能层是若干独立 Skill 的集合每个 Skill 内部是“说明文档 代码 依赖 测试”运行时层提供实际执行环境包括 Python 解释器、Node 运行时、沙箱、文件系统访问权限等。设计时最重要的原则是调度层不写业务逻辑技能层不感知调度细节。两者通过统一的输入输出协议沟通最简单的方式就是全程用 JSON 输入、JSON 输出。这样做的好处是 Agent 壳可以随意更换Skill 完全不用改。我见过有人把业务判断写在 Skill 脚本里结果换了一个调度框架整个技能库都要重写这就是边界没划清楚带来的代价。2.2 一个 Skill 的标准结构长什么样以目前社区普遍接受的规范为例一个 Skill 目录大致是这样的my-skill/ ├── SKILL.md # 技能说明含触发条件、参数、用法示例 ├── script.py # 主逻辑也可能是一个命令行工具 ├── requirements.txt # 依赖 ├── assets/ # 静态资源、模板 ├── test/ # 测试用例 └── meta.json # 元信息名称、版本、作者SKILL.md 是整个 Skill 的入口也是模型唯一会认真读的文件。模型不会去读所有源码它先读这个 Markdown判断“这个技能是否适用于当前任务、怎么调用、要传什么参数”。所以 SKILL.md 是写给模型看的说明书不是写给人类看的 README。关键部分包括技能名称和一句话描述、适用场景与禁用场景、参数定义与示例、调用示例含输入输出、常见错误提示。2.3 为什么 SKILL.md 比代码本身更重要我第一次写 Skill 时犯过一个典型错误把大量时间花在写 Python 脚本SKILL.md 只写了三行话。结果 Agent 根本不主动调用或者调用时参数乱传。原因很简单——模型面对几十个技能时只会扫一眼描述来决定用哪个它不可能把所有技能代码都读完再判断。写 SKILL.md 有点像给商品写标题和详情页。搜索匹配靠标题用户下单靠详情。你必须在前十行内说清楚这个技能是干什么的、什么场景下用然后把参数的边界和示例写清楚。社区里做得好的 SkillSKILL.md 往往比代码还长这不是没必要的冗长而是在替模型降低决策成本。我当时调整了写法之后同一个 Skill 的调用率提高非常明显。所以如果你发现 Agent 不调用某个技能第一反应不应该是“模型太笨”而是先检查你的 SKILL.md 是不是像在写产品说明书。2.4 工具、Skill、Agent 三者的边界再理一遍结合我前面说的类比这里用一张表把三者的区别收拢一下概念本质类比粒度工具Tool单个可执行函数/命令刀最小技能Skill自包含能力包含说明、代码、依赖、测试专项厨师中等智能体Agent持有模型、上下文和调度逻辑的主体后厨主管最大理解这个边界对后续开发特别重要。如果你发现自己在一个 Skill 里塞了太多跨领域的逻辑那它其实已经变成了一个微型 Agent应该拆开。如果你发现自己写的调度层里出现了具体业务处理代码那也应该停下来重构否则你最终得到的只是一个“带技能功能的单体应用”。3. 动手实现一个 Skills 架构的 Agent3.1 主流框架怎么选目前的实践路径大致有三类。第一类是基于 Claude Code 或者 Codex CLI直接在终端里使用支持读取项目下的 .claude/skills 或 .codex/skills 目录适合个人快速验证想法。第二类是基于 LangChain/LangGraph 自建 harness灵活度高可以插入记忆、人工审核、并行调度等自定义编排逻辑适合需要深度定制的中大型项目。第三类是基于 OpenCode 或 Continue 这类开源 IDE 工具适合前端开发和本地代码生成场景插件生态比较丰富。我的建议是如果你只是想体验 Skills 架构先别急着从零写框架。直接用 Claude Code 或 Codex 的 skills 目录把一个现成 GitHub 仓库里的 Skill 手动放进去跑通一次“Agent 主动调用 Skill”的流程再回到 LangGraph 自己实现调度这样学习曲线会平滑很多也能避免一开始就被框架的细节淹没。3.2 手动安装 GitHub 上的 Skills完整步骤很多人问我“Claude Code 怎么手动装 GitHub 上的 Skills”这里给一个适用性很广的流程。第一步在 GitHub 找到目标 Skill 仓库优先看有没有 SKILL.md没有的直接跳过因为后续接入成本会非常高。第二步把仓库克隆或下载到本地解压后确认目录结构是否规范。第三步进入项目根目录找到 skills 配置目录。Claude Code 通常看的是项目根目录下.claude/skills/也有全局的~/.claude/skills/Codex 看.codex/skills/OpenCode 看.opencode/skills/。不确定时就去查对应框架的文档这一步不能靠猜。第四步将 Skill 目录复制到对应的 skills 目录下保持目录名唯一。第五步用框架命令检查技能是否被识别可以问 Agent 自己有哪些 Skills也可以跑一个最小任务去触发它。第六步如果 Skill 有依赖先按照它的 requirements.txt 装好依赖再用它自带的测试脚本验证一遍。这一步最容易被忽略的是目录权限和目录名。某些框架要求 Skills 目录名不能带空格和特殊字符SKILL.md 的一级标题必须和目录名一致否则识别不出来。我踩过好几次这种坑复制完才发现 Agent 里根本没有加载回头一点点对配置浪费了一整个下午。3.3 写一个最小可用的 Skill图片生成示例假设我们要做一个图片生成 Skill目录结构如下image-gen/ ├── SKILL.md ├── generate.py └── requirements.txtSKILL.md 的骨架可以写成这样# image-gen 根据用户描述生成一张图片并保存到指定路径。 ## 适用场景 - 用户需要配图、封面、海报草稿 - 需要将文字想象转化为图片 ## 参数 - prompt: 必填描述画面内容尽量包含主体、风格、光线 - size: 可选默认 1024x1024 - output: 可选保存路径默认 ./output.png ## 调用示例 Input: {prompt: 一只戴眼镜的橘猫在写代码卡通风格暖色调, size: 1024x1024} Output: {status: ok, path: ./output.png}generate.py 就按普通 Python 脚本写唯一要注意的是所有输入输出都用 JSON别在脚本里写交互式input()否则 Agent 执行到一半会卡住错误信息也不直观。写好之后放到 skills 目录重启 Agent用一句话触发它。如果 Agent 没有调用先检查 SKILL.md 的描述是否足够显眼再检查上下文里是否真的加载到了这个技能。3.4 让 Agent 学会“按需调用” Skills按需调用有两种实现方式值得展开。第一种是“描述即路由”Agent 每次决策前拿到所有 Skill 的名称和一句话描述就像拿着一张索引表由模型自己选择。这种方式实现简单但当 Skill 数量超过 20 个以后命中率会明显下降因为描述之间会互相干扰模型可能被相似的关键词带偏。第二种是“分类路由”你自己写一个路由器先判断用户请求属于哪一类比如“写代码”“画图”“查资料”再只把对应类别的 Skill 描述交给模型。这种方式更稳适合生产环境。在 LangGraph 里实现时通常的做法是设计一个 router 节点节点里用一个分类提示词或一个小模型做意图识别输出结构化类别然后根据类别进入不同的 Skill 执行子图。这里有一个必须处理的分支未匹配。如果你不做“未匹配”处理Agent 面对一个没有对应 Skill 的任务就会报错或者强行调用一个不相关的技能生成一堆无用结果。我建议路由节点一律返回三值一是匹配的类别二是置信度三是“未匹配”标记调度层再根据标记触发兜底回复或让模型自由发挥。4. 踩坑实录与排查技巧4.1 高频报错agent execution terminated due to error社区里问得最多的错误就是 agent execution terminated due to error。这个错误本身只是一个笼统的封装真正的原因藏在后面要靠日志一层层剥。我通常按下面的顺序排查。先看是不是依赖没装。Skill 的 requirements.txt 没有被自动安装时脚本在 import 阶段就会失败Agent 执行被终止。解决办法是在 Skill 里加启动检查缺依赖时报一个可读性强的错误而不是让框架抛出一堆堆栈信息。再看是不是上下文超限。Agent 把 SKILL.md 和太多代码塞进上下文长对话后超限执行直接被终止。解决办法是让 SKILL.md 保持精简把冗长示例放到独立的示例文件里Agent 需要时再读。然后是权限问题。有些框架默认禁止 Skill 写文件、执行网络请求脚本一运行就被拦下。这时要检查框架的权限配置按最小权限原则放开对应能力不要图省事直接给全部权限。最后是模型输出格式的问题。Agent 返回的 JSON 不合法、参数类型不对也会在调度层直接终止。可以在路由节点后加一个 JSON 校验节点失败时让模型重新输出一次。排查时最忌讳的是看到报错就去翻框架源码。先把 verbose 日志打开把每一步的输入输出打出来定位到具体 Skill 后再处理。这个习惯能帮你节省大量时间因为大多数问题其实都出在你自己的 Skill 里。4.2 Skill 之间打架依赖冲突与命名冲突Skills 架构看起来干净但用多了以后依赖冲突几乎是必然的。每个 Skill 都声明自己的 requirements.txt装到一起就出现版本覆盖。比如 A Skill 要求 requests 2.xB Skill 要 requests 3.x后装的把先装的顶掉结果其中一个 Skill 开始报错。比较好的方案是给每个 Skill 单独建虚拟环境或者用支持隔离的运行时比如 Docker 容器。如果只是本地试验可以约定一个规则公共依赖统一定版本Skill 内部用相对路径 import 自己的代码不依赖全局安装的包。这样冲突面会小很多。命名冲突是另一种坑。两个 Skill 都叫 translateAgent 根本不知道该用哪个。我的建议是给每个 Skill 名字加命名空间前缀比如 code-review-frontend、code-review-go同时在 SKILL.md 里写清适用边界路由器也更容易匹配。别偷懒名字起得清晰一点后面能少很多麻烦。4.3 常见问题速查表现象常见原因处理办法Agent 不调用已安装的 SkillSKILL.md 描述不清晰或目录未被加载重新加载/检查 skills 目录精简描述、突出触发场景调用 Skill 后返回空结果脚本输出格式不标准统一 JSON 输出并打印关键字段辅助定位Skill 执行报权限错误沙箱或 ACL 未放行检查框架权限配置按需开放文件、网络权限长对话后响应变慢上下文被 Skill 文档占满精简 SKILL.md将示例移到子文件按需加载两个 Skill 功能相近被误调描述重叠、命名不唯一增加命名空间前缀写明不适用场景这张表是我在实际项目里整理出来的适用面很广。遇到没列出来的问题原则都是一样的先复现再定位是 Skill 内部的问题还是调度层的问题最后对症下药大部分问题都能自己解决。5. Skills 生态去哪找、怎么选、怎么避坑5.1 常用 Skills 源网站与仓库目前找 Skills 的主要渠道有几个。GitHub 直接搜 awesome skills、claude skills、codex skills能找到很多聚合仓库里面按领域整理了社区里评价比较好的技能。OpenCode 和 Codex 的官方示例库是个很好的起步参考里面的结构通常最标准。还有一些专门的 Skills 导航站会按“前端开发”“图片生成”“数学建模”“PPT 生成”等分类收录技能省去自己一个个翻仓库的时间。需要提醒的是Skills 本质上是可执行代码从第三方仓库拿回来一定要先看 SKILL.md 和源码。不要直接运行来历不明的安装脚本尤其是那些要求授权文件系统、网络、环境变量的技能。正规的 Skill 一般会写明它需要哪些权限、会在哪里创建文件、有没有外部依赖。你花五分钟做一次安全审查远比事后收拾烂摊子划算。5.2 按场景挑 Skills从数学建模到前端开发从社区热搜里能看到很多人在问“数学建模 Skills 推荐”“前端开发 Skills”“图片生成 Skills 安装包”“AI 漫剧常用 Skills”这说明 Skills 已经被用到非常具体的生产场景里了。拿数学建模来说好用的 Skills 通常包含数据预处理、特征工程、模型对比、论文图表生成这几个子能力前端开发类的 Skill 更像一个多文件代码生成器能根据需求产出组件、样式和页面的骨架代码图片生成类的 Skill 则通常封装了提示词优化和文生图 API 调用。挑选的时候不要只看标题大而全。一个号称“全能开发”的 Skill往往不如三个各司其职的小 Skill 好用因为 SKILL.md 描述越长模型匹配的准确率越低。这也是 Skills 架构的设计哲学之一小而专、可组合。你完全可以找一个数据清洗 Skill、一个可视化和一个建模 Skill组合成自己的分析链路。5.3 下载安装后必做的三件事第一件事是校验目录结构。确认有没有 SKILL.md、入口脚本、依赖清单缺少任何一样都可能导致安装失败。第二件事是安装依赖后单独跑测试。几乎每个 Skill 都自带或者应该自带一个最小验证脚本先跑通再交给 Agent不要拿 Agent 当小白鼠。第三件事是观察 Agent 的调用日志。第一次调用时把日志打开看模型读取了 SKILL.md 的哪一段、传了什么参数、脚本输出了什么。这样可以快速判断是描述问题还是实现问题。很多所谓的“Skill 装了没用”问题本质上就是这三件事没做到位。6. 从 Skills 架构反推 Agent 设计一点个人心得做了几个项目之后我越来越觉得“Agent Skills Skills 架构的 Agent” 的真正价值不是让你去堆砌技能而是逼你重新思考 Agent 的边界。如果你发现自己一直在给 Agent 的 system prompt 加规则、加例子很可能该做的是把这些内容沉淀成一个 Skill如果你发现某个 Skill 经常被误调用那问题多半不是模型笨而是描述写得不够清楚。我的另一个习惯是给所有 Skill 写测试。传统开发里测试是为了防回归在 Agent 场景里测试更像是给 Skill 加上一个“可被信任”的标签。因为模型本身有随机性一个没有测试、没有固定输出格式的 Skill会让整个链路变得不可控。哪怕只是一个几百行的脚本也值得写一个最小用例这些用例在你换模型、换框架的时候会成为救命稻草。最后分享一个小技巧开发调试时先让 Agent 用只读模式调用 Skill确认它生成的信息正确再放开写文件权限。这样可以把技能本身的正确性和执行环境的权限问题分开排查。等你积累了一套自己的 Skills 库再回头看会发现 Agent 的开发模式已经从“写提示词”变成了“搭积木”这才是 Skills 架构真正改变工作方式的地方。