大家好,今天想和大家聊一个最近在项目里特别有感触的话题:怎么让大模型 Agent 从"看起来很聪明"真正变成"能干活、干得稳"。
这篇文章我会沿着 Agent痛点 → Skill 是什么 → 怎么写好一个 Skill → 一个真实案例 → 怎么让 Skill 更可靠 的路径,把我们踩过的坑和总结的方法讲清楚。
一、先说说 Agent 在落地时到底卡在哪
在动手做 Agent 的时候,开发者和用户经常会被几个问题反复折磨。具体表现主要有三个。
- Prompt 极度脆弱且难以复用:将所有逻辑塞入 System Prompt 会导致指令过载。一旦需要调整某个微小行为,往往引发"牵一发而动全身"的灾难性后果,且不同场景间的 Prompt 几乎无法复用。
- 工具调用(Tool Calling)的不稳定性:当 Agent 挂载的工具过多时,模型容易出现"幻觉",调用错误的工具、遗漏必填参数或陷入死循环。
- 上下文窗口溢出与注意力分散:复杂任务需要极长的上下文,不仅增加 Token 成本,还会导致大模型在执行多步推理时"遗忘"最初的目标或中间状态。
这三个痛点其实指向同一件事:我们一直在用"对话"的方式驱动 Agent,但真实工程需要的是"规格"。
二、Skill 机制:从"对话"到"工程"的一次范式跃迁
Skill 到底是个啥
一句话讲清楚:Skill 不是一段 Prompt,而是一个自包含的、结构化的能力封装单元。
你可以把它理解成 Agent 的"专业培训模块"。打个比方:
- 没加载 Skill 的 Agent,像一个什么都懂一点、但从没真正干过活的实习生,让他做事全靠你一句一句教。
- 加载了 Skill 的 Agent,更像一个揣着"标准作业流程(SOP)"的资深专家,活儿怎么干、什么时候该停、出问题怎么处理,都写在册子上。
差别就在于:前者靠灵感,后者靠规格。
一个完整的 Skill 长什么样
一个像样的 Skill,通常由七个核心要素组成。
- 元信息 --- Skill 的"身份证":名称见名知意(如 page-generator),描述说清它解决什么问题,标签用于分类检索(如 React、Ant Design)。
- 触发语义 --- 定义"什么时候该用我"。触发可以是显式的(用户说 /generate-form),也可以是隐式的(检测到用户打开了组件目录且在描述表单需求)。好的触发语义做到该触发时不漏,不该触发时沉默。
- 上下文与前置条件 --- 声明运行前需要什么。比如 page-generator 的前置条件:已安装 Ant Design、路由配置已存在。不满足直接终止,避免跑到一半才发现环境不对。
- 执行流程 --- Skill 的核心,将任务拆解为原子步骤序列,每步有明确的输入、输出和工具白名单。好的流程让 Agent 按蓝图执行,不需要"发挥创意"。
- 工具约束 --- 遵循最小权限原则。比如 component-builder 只需要读组件库文档和写组件文件,不需要调接口、改路由、跑部署。
- 验证与护栏 --- Skill 质量的生命线。每步完成后有断言:组件生成 → 跑 ESLint + type check;页面完成 → 验证 loading/空态/错误态的覆盖。验证失败时护栏接管:可自动修复的重试,需人工判断的升级,不可恢复的终止并清理。
- 领域知识 --- 将组织的隐性知识显性化:编码规范、架构约束、历史事故教训。随项目演进持续更新,是 Skill 区别于一次性 Prompt 的根本所在。
Skill 和 Prompt 到底差在哪
直接上对比:
| 维度 | Prompt | Skill |
|---|---|---|
| 组织方式 | 一段线性文本 | 结构化模块 |
| 复用性 | 靠复制粘贴 | 声明式引用 |
| 激活方式 | 始终生效 | 按需触发 |
| 可测试性 | 很难验证 | 可单测、可回归 |
| 组合能力 | 拼一起就打架 | 能编排组合 |
| 版本管理 | 几乎没有 | 可追溯、可回滚 |
这不是量变,是质变。当能力被封装成 Skill,Agent 就从"一段对话"升级成了"一个可编排的执行引擎"。
Skill 的完整调用流程
一个 Skill 从被触发到完成,会走完如下五个阶段的生命周期。
阶段一:识别与匹配。 根据触发语义做意图路由。结果可能有三种------零个 Skill 匹配(那就走通用对话)、刚好一个匹配(直接激活)、多个候选(按置信度排序,或者让用户选)。
阶段二:上下文装配。 按需加载领域知识、校验前置条件、绑定工具权限。装配完成后,Agent 就从"通用大脑"切换成"专才模式",眼里只剩下当前任务需要的信息,不再被无关上下文干扰。
阶段三:逐步执行。 按 SOP 以"执行---验证"的双拍节奏推进。断言通过就走下一步,失败就触发护栏。
阶段四:终态验证。 整体跑完后再做一次总检查。比如页面生成完,验证路由能不能跳转、样式一致不一致、表单校验和联动规则是不是都生效了。
阶段五:反馈闭环。 结果给到用户,执行轨迹写进日志。生成的组件符不符合编码风格?用户改了几次才满意?这些数据反过来驱动 Skill 持续迭代。
三、怎么写好一个 Skill:实操五步法
写 Skill 之前,推荐先用 Ant Skill Creator 这个脚手架工具来辅助。它会用结构化对话引导你完成 Skill 的初始设计。
打开 Creator,它会先抛给你四个问题:做什么、何时触发、产出什么、怎么验证。这四个问题正好对应下面五步法的前三步------界定边界、拆解流程、定义验证规则。
Step 1:界定边界(先想清楚再动笔)
动笔前先回答三个问题:
- 这个 Skill 做什么? 一句话说清输入和输出。比如:"给定一个页面需求描述和接口文档,生成一个符合 Ant Design 规范的中后台 CRUD 页面,包含搜索表单、分页表格、新增/编辑弹窗。"
- 这个 Skill 不做什么? 把不处理的场景明确排除掉。比如:"不处理路由注册、不做接口联调验证、不处理复杂的流程图类交互。"
- 谁来用这个 Skill? 是 React 中后台开发?还是小程序开发?不同受众决定了术语体系和粒度。
边界一旦清晰,你就不会写出那种"听起来无所不能、实际啥都干不好"的 Skill。
Step 2:拆解流程(把活儿切成原子步骤)
把"完成这件事"拆成 3 到 7 个原子步骤。每一步都要满足三个条件:
- 单一职责:一步只干一件事
- 可独立验证:做完就能判断对错
- 有明确交付物:输出是能检查的东西,不是"我感觉做完了"这种模糊状态
每一步都很具体,Agent 照着干就行。
Step 3:定义验证规则(这一步决定了 Skill 是不是摆设)
为每一步、每个最终结果定义验证条件。
| 验证层级 | 时机 | 例子 |
|---|---|---|
| 前置条件 | 执行前 | 是否已安装 antd?项目是否有全局路由配置? |
| 步骤断言 | 每步后 | Step 3 生成的表单,是不是包含了所有接口字段对应的表单项? |
| 终态核对 | 全流程后 | 页面是否通过 TypeScript 编译?表单校验是不是覆盖了必填、格式、边界?表格操作列按钮有没有 loading / disabled 态? |
写验证条件的关键是"具体、可机械化判断"。 千万别写"页面功能完整"这种 Agent 自己读完都心虚的东西,要写"ESLint 零 error、TypeScript strict mode 编译通过"------这种能直接跑出结果的。
Step 4:注入领域知识(把团队的经验喂进去)
把团队沉淀下来的东西写进 Skill:
- 编码规范:你们用 CSS Modules 还是 styled-components?状态管理用 Zustand 还是 Redux Toolkit?
- 模板示例:放一些代码模板、参考片段进去。
- 历史教训:上次那个审批页面上线后各种白屏,就因为没处理接口异常时的 ErrorBoundary------那就把"每个页面必须有错误边界"加成护栏。
领域知识不是一次写完的,而是每次翻车后补充进去的。每一次翻车,都是让 Skill 变聪明的机会。
Step 5:迭代打磨(上线只是开始)
Skill 上线不是终点,持续打磨才是它从"能用"走到"好用"的关键。除了被动从执行数据里发现问题,还有三种主动打磨方式。
- 失败反哺机制
每次失败都自带打磨素材------失败场景 + 人工最终是怎么修好的。
- 记录:这次 Agent 卡在哪一步?人工最后是怎么救回来的?
- 归类:按周聚合一下,找高频失败模式。比如"生成的表格总是缺少操作列的权限控制逻辑"。
- 回写:把模式沉淀进 Skill------更新前置条件校验、补充领域知识、加新的护栏。
核心心法是:别浪费任何一次失败。每次翻车都是免费的质量测试用例。
- 同行互审(Skill Review)
代码要 code review,Skill 也一样。可以问几个问题:
- 别人能不能光看你的 Skill 定义就懂它要干嘛?
- 触发条件有没有漏洞,会不会在不该触发的时候触发?
- 护栏够不够严,某一步挂了恢复策略合不合理?
- 领域知识有没有过时,废弃的规范现在还在用吗?
形式可以很轻:每两周花 20 分钟,一个人讲、两个人挑刺,比任何自动化检查都更能发现"你没想到的情况"。
- 对抗性测试
主动用刁钻的输入去试探 Skill 的边界:
- 故意输入不完整的信息("帮我生成个表单",但不说有哪些字段)
- 故意制造矛盾(同时要求"最简化实现"和"覆盖所有交互态")
- 故意输入领域外的任务(让一个写医疗前端的 Skill 去配 Webpack)
对抗性测试的目的不是让 Skill 什么都能干,而是确认它在不该干的时候能干净利落地拒绝。一个好的 Skill,会优雅地说:"这需求我不太清楚,能再确认一下吗?"
打磨不是一次性动作,是个习惯。推荐节奏:每周花 30 分钟,做一轮用例回归 + 翻最近的失败记录 + 挑一个边界场景做对抗测试。 时间不长,但坚持三个月后,成熟度差距会非常明显。
四、扩展:融合 Harness Engineering --- 让 Agent 从"能跑"到"可运营"
Harness Engineering 是什么
Harness Engineering(Harness 工程)是围绕 AI Agent 构建脚手架系统的一门工程学科。这个概念由 Vivek Trivedi(LangChain)首次明确提出,其核心公式为:
Agent = Model + Harness
你不是模型,那你就是 Harness。
Harness 是模型之外的一切------系统提示词、工具调用、文件系统、沙箱环境、编排逻辑、钩子中间件、反馈回路、约束机制。模型本身只是能力的来源,只有通过 Harness 把状态、工具、反馈和约束串起来,它才真正变成一个 Agent。
六层架构体系
一个成熟的 Harness 体系分为六层,从"定义边界"到"兜底恢复"形成完整闭环:
| 层级 | 名称 | 解决什么问题 | 关键设计 | 类比(新员工) |
|---|---|---|---|---|
| L1 | 信息边界层 | Agent 该知道什么 | 定义角色与目标,裁剪无关信息 | 岗位说明书 |
| L2 | 工具系统层 | 怎么跟外部世界交互 | 工具选拔、调用时机、结果提炼 | 办公工具 |
| L3 | 执行编排层 | 多步骤任务怎么串 | 理解→判断→分析→生成→检查 | 标准操作流程 |
| L4 | 记忆与状态层 | 长任务中间结果怎么管 | 独立管理状态、中间产物、长期记忆 | 项目管理系统和笔记本 |
| L5 | 评估与观测层 | 怎么知道做对了 | 独立于生成的验证机制 | 质检流程 |
| L6 | 约束校验与恢复层 | 出错了怎么办 | 预设规则拦截错误,重试或回滚 | 红线规则和应急预案 |
💡 落地建议:不要试图一开始就搭齐六层。从 L1(信息边界)和 L6(约束与恢复)入手,这两层投入产出比最高。
一个真实案例
lifecycle 是一个工作流编排器,解决的是前端项目启动前那条漫长的前置链路:理解需求 → 写系分文档 → 设计设计稿 → 搭建项目 → 连接 API。用户只需说一句话(比如"帮我生成一个xxx系统的前端系分并开始开发"),Agent 自动走完 几 个阶段,最终产出一个能直接跑起来的项目脚手架。
设计思想
这个 Skill 的设计思路其实很简单,核心就四句话:
编排不执行。 编排器自己不写代码、不生成文档、不画设计稿。它只做一件事------按顺序调度子 skill,把它们的产物串起来。就像工地上的项目经理,不搬砖不砌墙,但知道什么时候该叫谁来干什么。
只认产物,不靠记忆。 阶段之间怎么衔接?不靠 Agent 的"记忆力",靠文件。上游产出了 SDD 文件,下游读取 SDD 路径才能启动。上游产出了设计稿,下游拿着设计稿列表继续。每一个阶段的"入场券"是上一阶段的产物,不是 Agent 脑子里记得"我好像干到第三步了"。
多入口归一。 用户给的可能是语雀 PRD 链接、一段文字需求、或者现成的 SDD 文件。编排器在入口处识别类型、分拣路由,不管哪种输入,最终都汇入同一条管道,产出统一的东西。
中断了能继续。 几 个阶段的流程,不可能每次一口气跑完。编排器把当前进度、中间产物路径持久化下来,用户下次说"继续",直接从断点恢复。
它踩中 Harness 六层的地方
回头看,这些设计思路恰好落在了 Harness 六层框架上:
- L1 信息边界:入口路由识别输入类型,让 Agent 在最开始就知道这次任务的视野范围------是从 PRD 起步还是直接复用 SDD?不用在所有信息里大海捞针。
- L2 工具系统:每个阶段有明确的工具组合。翻译层用 yuque + Read,可视化层用 SVG 生成,工程化层用模板 + Bash。工具按需装配,不乱调。
- L3 执行编排:最显性的一层。决策树判断输入类型,状态机管理阶段推进,几 个阶段拆成标准化的步骤序列,Agent 照着跑就行。
- L4 记忆与状态:持久化 JSON 记录当前阶段、SDD 路径、设计稿列表、服务层路径。阶段间靠这些产物显式传递,不靠 Agent 的上下文窗口"回忆"。
- L5 评估与观测:设计稿生成后和 SDD 页面列表逐项比对,项目启动后验证编译通过。每步都有可检查的基准,不是"看着差不多就行"。
- L6 约束校验与恢复:OneAPI 权限不足 → 提示用户处理,子 skill 缺失 → 提示安装后重试,Axure 链接不可访问 → 降级为纯文字需求理解。每种失败都有对应的出口。
具体怎么做 - 用 Harness 思想来写 Skill
五步法 + 六层架构怎么配合
上面讲的写好skill的五步法是实操手册:界定边界 → 拆解流程 → 定义验证 → 注入知识 → 迭代打磨,告诉你"怎么写一个 Skill"。六层 Harness 体系是验收清单,告诉你"写到什么程度 Agent 才能可靠执行"。两者不是替代关系,是操作手册和质检标准的互补。
五步法已经覆盖的,六层让它更严谨:
- Step 1 界定边界 ↔ L1 信息边界层。 五步法问了三个好问题:做什么、不做什么、谁来用。Harness 补一条:
- 边界定义放在 SKILL.md 最显眼的位置,让 Agent 一进来就看清视野。视野太大注意力涣散,太小信息又不够。
- Step 2 拆解流程 ↔ L3 执行编排层。 五步法要求每步单一职责、可独立验证、有明确交付物。Harness 再补两条:
- 工具显式化(L2):每步开头标注工具清单,比如"本步工具: Glob, Read, Grep"。Agent 不用从段落里推测该用什么工具,天然形成最小权限约束。
- 状态归一化(L4):多步骤 Skill 的中间产物(文件路径、用户选择、配置项)统一收敛到一份结构化的 Context JSON。所有步骤的产出写进去、入口条件从中读出。
- Step 3 定义验证规则 ↔ L5 评估与观测层。 五步法已经强调"验证要具体、可机械化"。Harness 把它推到极致------验证必须是 Agent 实际执行的操作,不能是 Agent 读完就能说"我确认了"的文字。对比一下:
不产生工具调用痕迹的验证不算验证。 五步法给了方向,Harness 给了及格线。
- 弱验证:"确保移动端适配"------Agent 读完点头说好的,过了
- 强验证:"用 Playwright 分别在 375px 和 414px 视口截图,和设计稿叠图对比偏移量"------Agent 必须调工具、拿真实结果
- Step 4 注入知识 / Step 5 迭代打磨,在六层里没有直接对应。这不是 Harness 漏掉了------六层管的是"结构质量"(骨架结不结实),Step 4-5 管的是"内容质量"(血肉鲜不鲜活)。两者关系是:先用六层搭好框架,再通过持续打磨往里填经验。
五步法漏掉的,六层补上:
五步法讲了怎么写正常流程、怎么验证、怎么打磨,但没有系统性回答一个问题:某一步出错了怎么办? 这正是 L6 约束校验与恢复层要解决的。
不需要额外的工作量------在 Step 2 拆解流程时,给每个关键步骤多加三行:
- 可自动恢复:子 Skill 缺失 → 提示安装后重试
- 可降级处理:某 MCP 不可用 → 从已有文件提取信息
- 需人工介入:接口权限不足 → 暂停流程,提示用户处理后再继续
多问自己一句"这一步如果挂了 Agent 该做什么",Skill 就从'演示环境专用'变成了'生产环境可用'。
写在最后
六层架构的意义,不在于把 Skill 拆成六个独立模块,而在于提醒 Skill 作者三件事:
- 你的 Skill 是一张地图,不是一个仓库(L1-L3)
- 你的验证标准应该是一串操作,不是一段建议(L4-L5)
- 你的失败处理不是附录,是正文(L6)
做到这三条,Skill 就从"一个人写给自己看的操作手册",变成了"一份 Agent 能机械执行的可靠规格"。不需要平台支持,不需要新工具------只改变写作习惯。
从 Prompt 到 Skill,是第一次质变------能力从对话中"结晶"成了结构化模块。用 Harness 思想让 Skill 的可靠性持续进化,是第二次质变的前奏------当平台支撑就绪时,这份结构化规格可以直接被读成可编排的执行计划。
希望今天分享的这些东西,能帮大家在写 Skill 的时候少踩点坑、多积累点真正能用的资产。