我一直有个很深的体感AI Agent 写单点功能很利索可一旦让它把一个项目从需求做到交付就会在某个环节突然飘掉。不是它不聪明是它没有一套可依赖的工序。最近我把注意力全部放在一件事上——用Skills 给 AI Agent 配一套完整的工程工作流从需求澄清、方案拆分、编码实现、质量验证到文档交付一步步都固化成可复用的能力模块。这篇文章就是这次实践的完整记录工作流怎么拆、每个 Skill 的 SKILL.md 怎么写、文件系统怎么当共享内存以及我实测下来踩过的各种坑。如果你也在做 Agent 的工程化改造或者正被每次开新会话都要重新教一遍折磨这篇应该能给你一条可以直接上手的路线。1. 为什么靠提示词管不住 Agent缺的不是聪明是流程1.1 一个每天都在发生的失控现场先说一个我在好几个项目里反复遇到的场景。我在对话框里给 Agent 丢了一大段需求描述开头它表现非常正常能复述需求、能列计划、能写代码看起来完全进入了状态。但写到一半它开始自己加需求把没提到的功能擅自实现更离谱的是它写完代码不测试直接告诉我应该可以了我追问一句它又会改一堆东西然后上次已经确认过的设计决策被它自己推翻。这不是个别模型的毛病是工作方式的问题。你在一个超长对话里持续给指令Agent 会顺着对话惯性走上下文越长早期明确过的规则越容易被遗忘。你会发现一个规律每次新会话从头开始的效果往往比在一个已经聊了三千字的会话里继续要好。因为新会话等于清空了所有噪音但代价是你得把需求重新讲一遍讲完还是会重复上面的循环。这种失控的本质是Agent 有聪明但没有工序。它不知道一个工程任务应该先做什么、后做什么、每步产出什么、达到什么标准才算过。它只是在响应你的每一条消息而不是在执行一条流水线。1.2 提示词的边际效应衰减很多人的第一反应是那我写一个超级详细的系统提示词把所有规则都写进去。我试过有用但极其有限。问题出在提示词的形态上它是一次性的、全局的、静态的。一次性意味着每次新对话都要重新贴一遍或者你需要在系统配置里维护一份越来越长的文档全局的意味着它对所有任务生效但一个 Agent 要处理的事情往往不只有编程还有答疑、总结、闲聊一套规则不可能同时满足所有场景静态的意味着它无法根据当前任务动态加载合适的过程知识。更麻烦的是提示词越长单条指令的权重就越低。你可以对比一下给 Agent 说记住写代码必须配套测试和给它一份带检查点的验收清单哪个更可靠我实测下来前者在对话前几十轮有效后面就开始打折扣后者才真正能约束行为。1.3 我们把 Agent 当成实习生还是流水线打个比方。一个刚入职的实习生你口头叮嘱一次做事要规范他大概率记不住但如果你给他一份岗位手册里面写明每个环节怎么做、产出什么、怎么自检他就能稳定地输出。这里面对面授机宜的差别不在聪明程度而在流程是否被固化成了可查询、可复用、可版本化的东西。真实开发团队里靠的不是某个人的记忆力而是阶段门禁需求要评审、方案要通过、代码要 review、交付要有文档。每一步都有明确的输入和输出物。AI Agent 要承担工程任务就应该给它同样的东西。把一条完整流水线拆成若干个工序模块每个模块负责一个阶段阶段之间用文件交接Agent 按工序表一步步执行这才是给 Agent 配工程工作流的正确打开方式。2. Skill 的底层逻辑从一次性对话到可复用工序2.1 Skill 的标准形态一个目录就是一门手艺先把我理解的 Skill 讲清楚。它本质是一个目录里面装着一门手艺的完整作业指导书和配套资源。核心文件是SKILL.md文件头部有一段元信息通常包含技能名称和描述正文是分步操作指令告诉 Agent 拿到这个任务后按什么顺序做、每一步做到什么程度。目录里还可以放辅助脚本、参考资料、模板文件。一个典型的 Skill 目录长这样workspace-skills/ ├── requirement-analysis/ # 需求澄清技能 │ ├── SKILL.md │ └── templates/ │ └── requirement-template.md ├── task-planning/ # 方案与拆解技能 │ ├── SKILL.md │ └── references/ │ └── task-splitting-guide.md ├── code-implementation/ # 编码实现技能 │ ├── SKILL.md │ └── scripts/ │ └── format-check.sh ├── quality-verification/ # 质量验证技能 │ ├── SKILL.md │ └── references/ │ └── test-checklist.md └── documentation-delivery/ # 文档交付技能 ├── SKILL.md └── templates/ └── delivery-checklist.mdSKILL.md本身的写法很关键它决定了 Agent 会不会加载这个技能、加载之后按什么逻辑执行。我给出的标准骨架是先写清楚这个技能解决什么问题、在什么场景下使用再列前置条件然后写执行步骤最后写产出物和验收标准。步骤要具体到可执行而不是泛泛的写出高质量代码这类废话。2.2 Agent 是怎么想起一个 Skill 的description 是唯一门牌号这是整个机制里我最想强调的一点Agent 不是把所有 Skill 的内容都读一遍它是根据当前任务和每个 Skill 的描述信息做匹配匹配到了才加载正文。换句话说description 写得好不好直接决定了技能会不会被调起来。我以前犯过一个典型错误把某个技能的描述写成了用于处理开发相关的工作听起来覆盖面很广结果 Agent 几乎不触发它。因为开发相关太模糊了Agent 无法判断当前这个具体请求到底算不算。后来我改成任务触发式的描述效果立刻不一样--- name: 需求澄清 description: 当用户提出一个不完整的项目需求、功能想法或改进意向 且需要先弄清楚边界条件和验收标准时使用本技能。 典型触发词有个想法、做个工具、需要实现、帮我开发、需求文档。 ---这样写Agent 拿到一个新需求时能明确判断这个情况匹配从而加载对应工序。2.3 Skill、工具、系统提示词到底怎么分工很多刚接触的人会把这三样东西搞混我直接用一张表说清楚能力形态作用范围特点适用场景系统提示词全局恒定、所有会话生效但越长越稀释定义身份、底线、通用规范工具Tool原子操作一次性外部能力如搜索、执行命令、读写文件需要 Agent 操作外部环境时Skill一段完整工序可被动态加载、可版本化、可复用、可组合把复杂流程固化成稳定的作业指导打一个更生活化的比方系统提示词是公司的企业文化所有人都默认遵守工具是扳手和电钻需要的时候拿起来用Skill 是岗位的操作手册你被分配到某个岗位时才翻开对应的那一本。三者各管一段不要指望用系统提示词去模拟 Skill 的工序能力那等于让全公司所有人每天背一遍别人的岗位职责。3. 工程工作流的整体架构一条流水线拆成 Skill 组合3.1 先定义我们要哪六道工序给 Agent 设计工程工作流首先得把一条真实开发流水线翻译成 Agent 能执行的步骤。我根据自己跑项目踩坑的经验把流水线收敛成六道工序需求澄清、技术方案与任务拆分、编码实现、质量验证、评审修正、文档交付。这六道工序对应的不是操作步骤而是阶段门禁。每个阶段都有明确的输入物和输出物前一个阶段的输出就是后一个阶段的输入。例如需求澄清阶段输出需求清单方案与任务拆分阶段拿到需求清单后输出技术方案和任务列表编码实现阶段按任务列表逐项完成。这样切分的最大好处是每一道工序都能单独测试、单独改进出问题时不用把整条流水线推翻。3.2 单一职责每个 Skill 只管一个阶段设计 Skill 集合时我最看重的一条原则是单一职责。一个 Skill 只做一件事描述要精确边界要清晰。千万别做一个叫全能工程师的 Skill试图把需求分析、写代码、测试、文档全塞进去。原因有两个。第一路由会混乱。Agent 判断该调用哪个技能时靠的是描述匹配一个技能管的事情越多它的描述必然越笼统Agent 就越容易误判。第二迭代会失控。你改需求澄清逻辑时会连带影响编码模块改一处坏一片。拆开之后每个技能都是独立零件坏了换哪个一目了然。我实测下来六个独立 Skill 的维护成本远低于一个巨型 Skill。虽然文件数量多了但每个文件的逻辑都很简单修改时的影响面是可控的。3.3 两条组装路线单体 Skill 与 Skill 集合实际落地时有两条组装路线可以选。路线A一个工作流总控 Skill承载全流程。这个 Skill 的内部步骤就是六个阶段的顺序执行每个阶段里调用自己的检查逻辑适合中小型项目。优点是简单一套写完就能跑缺点是所有逻辑挤在一个文件里项目复杂度上来之后会变得臃肿。路线B一套 Skill 集合 总控联动。每个阶段是一个独立 Skill外加一个总控 Skill 负责按顺序调度并检查每个阶段的产出物是否达标达标才允许进入下一阶段。适合项目比较复杂、需要多人协作维护技能库的场景。我的建议是先用路线A把整条链路跑通确认每个阶段的产出物符合预期再按阶段边界拆成路线B。不要一上来就追求完美架构先让工作流运转起来再逐步优化拆分。4. 核心 Skill 逐个搭建需求、规划、编码、质检、交付4.1 需求澄清 Skill把模糊要求变成验收条目需求澄清是整条流水线的地基但也是最容易被跳过的一步。Agent 拿到一句话需求就闷头写代码写完大概率不是用户要的东西。这个 Skill 的核心目标是把模糊的、口语化的要求转换成可验收的条目清单。我写的需求澄清SKILL.md大致长这样--- name: 需求澄清 description: 当用户提出不完整的项目需求、功能想法或改进意向 且需要先明确边界和验收标准时使用。 典型触发词有个想法、做个工具、需要实现、帮我开发。 --- ## 前置条件 - 用户描述了原始需求无论多简短。 ## 执行步骤 1. 复述你对需求的理解列出核心目标。 2. 逐项追问以下信息 - 目标用户是谁 - 核心功能列表必须有的 vs 可选的 - 明确不做的事边界条件 - 验收标准怎么算完成 3. 将回答整理进 requirements.md使用模板。 4. 将中断的疑问写入 BLOCKED 清单禁止自行假设。 ## 产出物 - requirements.md编号、功能描述、优先级、验收标准、边界条件。这里我特别强调一个点Agent 对不确定的信息必须追问而不是假设。现实中很多项目翻车就是因为 Agent 悄悄替用户做了决定。在 SKILL.md 里明确写上禁止对优先级和边界做假设能大幅减少需求漂移。4.2 方案与任务拆分 Skill先想清楚再做需求清单到手之后下一步不是写代码而是出技术方案和任务列表。这个 Skill 的核心是让 Agent 完成一次先想后做的过程产出物是plan.md和tasks.md。plan.md聚焦技术选择用什么架构、有哪些模块、模块之间怎么通信、关键风险是什么。tasks.md是把方案拆成可执行的小任务每个任务必须小到一次调用能完成。我给出的任务粒度标准是一个任务只做一件事做完有明确产物且可以在十五分钟内验证。# tasks.md 示例 | 任务编号 | 内容 | 依赖 | 状态 | | --- | --- | --- | --- | | T01 | 搭建项目基础目录结构 | 无 | TODO | | T02 | 实现配置模块 | T01 | TODO | | T03 | 实现数据读取接口 | T02 | TODO | | T04 | 编写 T03 的单元测试 | T03 | TODO |任务拆分最忌讳的是粒度失控。任务太大Agent 一次做不完然后在没有明确产出物的情况下硬凑任务太小又会产生大量上下文切换开销。我建议一个中型项目控制在二十到四十个任务之间每个任务的描述里包含验收标准比如接口返回结构符合 requirements.md 中 R03 的定义。4.3 编码实现 Skill把约束都写进工序编码实现 Skill 不需要教 Agent 怎么写代码它已经会了。这个 Skill 真正要解决的是让代码产出符合团队约定。我总结了几条必写的约束只实现任务清单里的内容不擅自扩展功能不虚构不存在的接口、依赖或环境每条对外函数或接口必须写清输入、输出和异常行为提交代码前先自查一遍语法、逻辑、边界、命名。SKILL.md 里这些约束看起来像废话但如果你不写Agent 真的会在代码里写一个它自己编造的第三方库调用。实测中我见过太多次 Agent 给出一段代码引用的 API 根本不存在而它自己并没有感知因为代码在它的想象里能跑。在这个步骤里还可以给 Agent 提供项目专属的代码规范文件放在references/目录下让它写代码前先读一遍。这样既能保持约束的颗粒度又不会把 SKILL.md 正文撑得太长。4.4 质量验证 Skill没有测试记录等于没做质量验证是我加了之后工作流稳定性提升最明显的一个环节。这个 Skill 强制要求 Agent 在宣布完成之前先对可验证的部分做检查而且必须留下记录。没有记录就视为没做。质量验证的 SKILL.md 里我定义了三个层次静态检查、单元测试、关键路径冒烟。静态检查包括语法正确性、未使用的变量、明显的逻辑漏洞单元测试针对核心函数和接口关键路径冒烟则是把整个任务的入口跑一遍确认主流程通顺。输出物是一份测试结果文件# test-results.md 示例 ## 静态检查 - [x] 无语法错误 - [x] 无未定义变量 - [x] 无虚构依赖 ## 单元测试 - [ ] T03 数据读取接口3/5 通过 - [ ] 失败原因空文件场景未处理 ## 关键路径冒烟 - [ ] 主流程执行失败异常信息见 logs/error-001.log这里有一条我强烈建议的规则验证不通过必须回到编码实现阶段修正而不是直接改测试结果。让 Agent 自己给自己放水是工作流失效的最常见原因。你需要在 Skill 里明确写出测试失败的条目必须关联一个修复任务禁止直接修改测试结论。4.5 文档与交付 Skill流程的最后一道门最后一道工序是文档与交付。很多 Agent 项目做到代码能跑就结束了但工程工作流必须包含交付物。这个 Skill 负责把整个工作区整理成可交接的状态。交付清单包含三部分一是README.md写清楚项目启动方式、环境要求和基本使用说明二是变更记录列出这个迭代完成了哪些需求和修复三是运行说明包括如何验证产出、有哪些已知限制。我还会让 Agent 根据 requirements.md 逐条打钩标注每项需求的完成状态未完成项必须给出原因和后续建议。这道工序的价值不仅是文档本身更是倒逼整个工作流闭环如果需求清单里有一条没做完交付阶段就会暴露出来而不是藏在代码里假装成功。5. 状态传递与上下文管理文件系统才是 Agent 的共享内存5.1 为什么不能靠会话记忆传状态Skill 机制里有个容易被忽略的问题多个 Skill 之间的状态是怎么传递的我开始时天真的想法是让 Agent 自己在对话里记住结果很快撞了墙。原因有两个。第一上下文不是无限的长任务执行到后面早期阶段的结论和决策会被冲淡甚至遗忘。第二当你从需求澄清阶段切到编码实现阶段时Agent 不会自动带着前面所有细节它只是重新加载新的指令。所以我后来彻底换了一个思路把文件系统当成 Agent 的共享内存。所有阶段之间需要传递的信息都写到工作区的固定文件里每个 Skill 开头先读该读的文件末尾把状态和结论写回文件。会话记忆只负责执行流程不负责存储项目状态。5.2 工作区规范让每个 Skill 知道去哪读、往哪写为了让这套机制可靠我给每个项目固定了一个工作区目录结构workspace/ ├── requirements.md # 需求清单由需求澄清 Skill 产出 ├── plan.md # 技术方案由方案拆分 Skill 产出 ├── tasks.md # 任务列表由方案拆分 Skill 产出 ├── test-results.md # 测试结果由质量验证 Skill 产出 ├── progress.md # 阶段交接摘要所有 Skill 共同维护 └── delivery/ # 交付文档目录由文档交付 Skill 产出 └── src/ # 项目源码目录关键在于命名要固定每个 SKILL.md 里都要写清楚读取哪个文件、写入哪个文件不允许各写各的。一旦命名不统一Agent 就会在两个文件之间来回猜工作流立刻失稳。5.3 三个交接习惯摘要、清单、状态标记我在反复测试中沉淀了三个交接习惯现在每条 Skill 都会遵守。第一每个 Skill 结束前在progress.md里追加一段交接摘要内容包括本阶段完成了什么、产出了哪些文件、下一阶段需要注意什么、遗留了哪些问题。这相当于一个工作日志即便 Agent 完全丢失前面的上下文也能凭这份日志快速续上。第二每个 Skill 开头都要先执行读清单按固定顺序读 requirements.md、tasks.md、progress.md更新自己的上下文而不是直接开干。这样即使上一个 Skill 的收尾不完美下一个也能拿到基本盘。第三所有任务和阶段都带状态标记TODO、DOING、DONE、BLOCKED。BLOCKED是个很关键的标记它表示当前无法继续因为存在未解决的前置问题。强制使用这个标记之后Agent 就不会在遇到障碍时硬编一个假结果而是停下来报告阻塞点这个行为对工作流的可靠性提升非常大。5.4 上下文预算不要把所有文件都塞给 Agent还有一个很多人会犯的错为了让 Agent 掌握全部信息把 requirements.md、plan.md、tasks.md、test-results.md 全量塞进上下文。这会让指令被大量冗余信息淹没反而降低执行质量。我在 SKILL.md 里做了两条规定一是所有交接文件必须控制篇幅只写必要信息比如 requirements.md 只保留经过确认的需求条目二是阶段之间的信息传递用摘要而不是全文编码实现阶段真正需要的是 tasks.md 里当前任务的描述以及 requirements 里相关的编号与验收标准而不是整份文档。这样既保住了上下文预算也逼着每个阶段把信息提炼得更干净。6. 实测高频故障与排查思路不生效、串台、半途而废6.1 Skill 压根没被加载八成是 description 写坏了第一个高频问题是技能完全不触发Agent 好像根本不知道它的存在。排查思路从 description 开始是不是写得太笼统或者用了太多内部术语我测试过两种写法。一种是本技能用于开发工作另一种是当用户提出不完整的项目需求且需要先明确边界和验收标准时使用后者的触发率明显更高。原因是 Agent 做路由匹配时靠的是当前任务和描述之间的语义相关性描述越接近用户在什么情况下需要它越容易被命中。如果你发现某个技能始终不被加载可以做一个简单的冒烟测试用三条典型的用户请求去触发它看哪条能命中、哪条不能然后根据结果调整描述里的触发词。这比反复调整正文内容有效得多因为问题往往根本不在正文。6.2 两个 Skill 互相串台职责边界没划清第二个高频问题是串台一个需求澄清任务Agent 却跑去做编码或者方案拆分的任务Agent 顺手就把代码写了。这通常是因为两个 Skill 的 description 边界重叠或者都没有写反例清单。我的排查方法是给每个 Skill 加上一段不要触发的说明。比如需求澄清 Skill 里明确写如果用户已经给出了完整的、可验收的需求清单直接进入下一步不要重新追问编码实现 Skill 里明确写本技能只做任务清单中的编码不做架构设计。这些负向约束能有效减少路由歧义。6.3 流程走到一半断掉缺少显式下一步第三个问题是流程半途而废。Agent 完成了当前步骤然后停在那里不知道该干什么或者干脆开始和你闲聊。根因通常是 SKILL.md 正文里缺少显式的下一步指令。我给每个步骤的末尾都固定写一句完成本步骤后继续执行第 X 步如果阻塞记录 BLOCKED 并停止。同时阶段末尾必须输出明确的交接摘要。这样 Agent 就不会把流程的推进权交回给你而是按照工序表自动走下去。实测下来加不加这句话流程完成率的差别非常明显。6.4 SKILL.md 越写越臃肿把细节拆进 references随着经验积累你会忍不住把所有踩过的坑都写进 SKILL.md最终正文变得又长又杂Agent 加载时浪费大量上下文。这不是好事。我建议正文只保留步骤骨架、验收标准和交接规则那些详细的技术方案、代码规范、历史案例统一放到references/目录下让 Agent 在需要时按需读取。一个实用的判断标准是如果 SKILL.md 正文超过两三百行就该开始拆分。把内容拆出去之后路由加载更快执行也更聚焦。6.5 改完旧行为还在版本与缓存问题最后一种情况是你更新了 Skill 内容但 Agent 的行为还是旧的好像根本没有生效。我之前遇到过两次排查下来原因各异一次是 Agent 的对话上下文里还残留着早期加载的旧指令另一次是工作区里的任务文件缓存的旧状态。解决办法很简单但容易忽略Skill 目录里加版本号例如requirement-analysis-v2每次迭代后新开一个会话再测试工作区按项目隔离不要跨项目复用同一个工作目录。把这些习惯固化下来版本混乱的问题基本能根除。最后再分享一个我目前一直在用的习惯把 Skill 当成测试用例来维护。每新建或修改一个 Skill我都会准备三到五条典型的用户请求跑一轮冒烟测试确认该触发的能触发、不该触发的坚决不触发。这套冒烟清单平时不起眼但工作流出问题的时候它是定位故障最快的路径。给 Agent 配工作流这件事本质不是让模型更聪明而是让流程更可靠而流程的可靠性全靠这些不起眼的日常维护撑起来。
阅读完成 · 觉得有帮助?