Agent 工具工程化方法
引言
很多人第一次写 Agent 工具时,会把它理解成“把一段提示词保存起来”。这当然有用,但很快会遇到三个问题:任务稍微复杂一点,提示词就变成长文;流程涉及脚本、检查清单、外部工具时,模型不知道什么时候该读取什么;最后即使 Agent 给出结果,也很难判断它是不是真的完成了任务。
addyosmani/agent-skills 是 Addy Osmani 开源的一套面向 AI coding agent 的工程技能库。项目把软件研发过程拆成 DEFINE → PLAN → BUILD → VERIFY → REVIEW → SHIP 等阶段,并提供 20 个左右的 Skill、多个专家 Persona、slash command、检查清单和会话 Hook,用来约束 Agent 在需求澄清、任务拆解、增量实现、测试验证、代码审查和发布前检查中的行为。
这个项目给了一个更工程化的答案:把复杂任务拆成可触发、可执行、可验证、可复用的 Agent Skill。它不是知识库,也不是提示词合集,而是一套面向 AI coding agent 的工作流系统:用 Skill 描述“怎么做”,用 Command 触发“什么时候做”,用 Persona 提供“由谁从哪个视角做”,再用 Reference、Script、Hook 和验证清单控制上下文成本与执行质量。
本文会基于对该项目的分析,总结一套可复用的方法。读完后,你应该能把自己的复杂任务,比如发布前检查、日志排障、技术博客翻译、PR 审查、运维变更评审,构建成一个真正可用的 Agent 工具。
先明确:Agent 工具不是提示词,而是工程系统
Anthropic 的 Agent Skills 文档把 Skill 定义为一种模块化能力:一个目录里包含 SKILL.md、元数据、可选脚本和资源,Claude 会在相关任务出现时自动加载。它的关键是 progressive disclosure,也就是分层加载:
- Metadata:启动时只加载
name和description,用于发现 Skill。 - Instructions:任务匹配时再加载
SKILL.md正文。 - Resources / Scripts:只有被指令引用时才读取参考资料或执行脚本。
Cursor 的 Agent Skills 文档也采用类似结构:Skill 是可移植、可版本化、可包含脚本和模板的能力包,可以放在项目级或用户级目录中。MCP 则从另一侧解决“外部系统能力”问题:服务器暴露工具,客户端通过 tools/list 发现工具,再通过 tools/call 调用,并且官方文档强调敏感操作应保留 human-in-the-loop。
这意味着一个可靠的 Agent 工具至少要回答四个问题:
- 什么时候触发:哪些用户意图、文件类型、工作阶段应该启用它?
- 如何执行:步骤是什么?哪些步骤不能跳?
- 如何取上下文:哪些内容常驻,哪些按需加载,哪些交给脚本或 MCP?
- 如何证明完成:用什么输出、测试、检查清单或运行结果作为证据?
agent-skills 项目之所以值得学习,是因为它把这些问题都变成了文件结构和工作流约束。
从 agent-skills 项目抽象出的三层模型
分析这个项目时,最有价值的不是某一个 Skill 的内容,而是它的分层方式。
第一层:Skill 负责“怎么做”
项目里的每个 Skill 都是一个独立目录,例如:
1 | skills/ |
docs/skill-anatomy.md 给出的标准结构很清楚:SKILL.md 需要包含 frontmatter、触发条件、工作流、常见借口、红旗信号和验证清单。这里的重点是 Process over knowledge:Skill 不是百科资料,而是 Agent 必须照着执行的 SOP。
一个好的 Skill 描述应该类似这样:
1 |
|
description 里必须同时写清楚“做什么”和“什么时候用”。如果把完整流程塞进 description,Agent 可能只读摘要就开始执行,反而绕过 SKILL.md 正文。
第二层:Command 负责“什么时候启动一组流程”
agent-skills 项目把软件研发生命周期拆成 DEFINE → PLAN → BUILD → VERIFY → REVIEW → SHIP,并提供 /spec、/plan、/build、/test、/review、/ship 等命令。命令本身不是复杂逻辑,而是一个薄入口,用来告诉 Agent:现在进入哪个阶段,应调用哪个 Skill 或哪些 Persona。
例如 /ship 的思路是:发布前不是让一个 Agent 从头看到尾,而是并行启动多个专家视角:
code-reviewer检查正确性、可读性、架构、安全、性能。security-auditor检查 OWASP、密钥、鉴权、依赖风险。test-engineer检查测试覆盖、边界场景、并发和错误路径。
主 Agent 最后只做合并,输出 GO 或 NO-GO 决策和 rollback plan。
第三层:Persona 负责“由谁看”
Persona 不是流程本身,而是审查视角。agent-skills 的 agents/ 目录里有 code-reviewer、test-engineer、security-auditor 等角色。它们适合做同一个产物的不同视角评估。
这里有一个关键约束:Persona 不要互相调用。如果让 code-reviewer 再去调用 security-auditor,就会引入多次摘要、上下文丢失和成本不透明。更好的做法是由用户或命令做编排,多个 Persona 独立产出报告,主 Agent 负责合并。
一套可复用的工程方法
把复杂任务做成 Agent 工具,可以按下面六步走。
第一步:定义任务边界
先不要写 SKILL.md。先写清楚这个任务的边界:
- 输入是什么:代码 diff、日志文件、网页 URL、需求文档、会议记录,还是自然语言目标?
- 输出是什么:报告、补丁、部署决策、翻译稿、命令执行结果,还是结构化 JSON?
- 什么时候应该触发:用户说了哪些关键词,或当前处于哪个工作阶段?
- 什么时候不应该触发:任务太小、信息不足、需要人工决策、涉及高风险操作?
- 完成证据是什么:测试通过、报告字段完整、截图、日志、CI 状态,还是人工确认?
这一步决定 Agent 工具是否可控。没有边界的 Agent 工具,会变成“什么都想做,什么都做不稳”。
第二步:把流程拆成阶段,而不是堆成长提示词
复杂任务通常不是一个 prompt 能解决的,而是一个有依赖关系的流程。agent-skills 用生命周期拆分工程任务,我们也可以用类似方式拆自己的任务:
1 | Clarify -> Collect Context -> Execute -> Verify -> Report -> Next Action |
以发布前检查为例:
1 | Identify change -> Collect diff -> Run focused checks -> Merge findings -> Decide GO/NO-GO -> Produce rollback plan |
如果步骤之间存在依赖,就保留顺序流程;如果步骤彼此独立,就考虑并行 fan-out。不要为了“自动化”强行让一个总控 Agent 从头代理所有阶段,因为每多一次摘要,都会增加信息丢失和误判风险。
第三步:设计上下文加载策略
上下文窗口不是仓库,也不是网盘,它是预算。生产级 Agent 工具要主动控制什么进入上下文:
- 常驻内容:只放触发条件、核心规则和必须执行的步骤。
- 按需资料:长检查清单、模板、规范放到
references/。 - 确定性逻辑:文件扫描、格式校验、报告生成放到
scripts/。 - 外部系统:数据库、CI、工单、监控平台通过 MCP 或已有工具连接。
这就是 context engineering 的核心:让 Agent 在正确时间看到正确信息,而不是把所有材料一次性塞给模型。
第四步:把脚本当作“确定性执行层”
Agent 擅长理解意图、做判断和组织输出,但不适合反复执行机械且可验证的逻辑。以下内容更适合放脚本:
- 收集 git diff、最近 commit、变更文件列表。
- 校验 Markdown frontmatter、JSON schema、YAML 格式。
- 生成报告骨架。
- 调用内部 API 并输出结构化 JSON。
- 检查文件大小、依赖版本、敏感关键字。
脚本的原则是:输入输出清晰、副作用可预期、结果机器可读。脚本越可靠,Agent 就越少靠猜。
第五步:把验证写进 Skill,而不是写进愿望
agent-skills 里一个很重要的模式是 Verification 和 Common Rationalizations。这不是装饰,而是在对抗 Agent 常见的跳步行为。
比如不要只写:
1 | Make sure the release is safe. |
而要写成:
1 | ## Verification |
如果结果不能被验证,就不要宣称完成。
第六步:选择正确的编排模式
references/orchestration-patterns.md 里最值得借鉴的是编排选择。可以简化成四种常用模式:
- 直接调用:一个任务、一个视角、一个产物。成本最低。
- 单 Skill / 单命令封装:同一个流程反复出现,就封装成 Skill 或 slash command。
- 并行 fan-out + merge:多个独立视角同时分析同一输入,主 Agent 合并结果。
- 用户驱动的顺序流水线:步骤之间有依赖,且每一步都需要人工判断。
判断是否需要并行 fan-out,可以问四个问题:
- 子任务是否真正独立?
- 每个视角是否能产生不同类型的发现?
- 合并结果是否足够小,能放回主上下文?
- 节省的等待时间或提升的质量,是否值得额外成本?
如果答案不明确,就从单 Skill 开始,不要一上来设计“Agent 团队”。
具体例子:构建一个发布前检查 Agent 工具
下面用一个完整例子演示如何把复杂任务做成 Agent 工具。场景是:每次准备发布前,让 Agent 自动收集变更信息、执行发布前检查、输出 GO / NO-GO 决策和 rollback plan。
这个例子可以放在支持 Agent Skills 的工具中,例如:
1 | .cursor/skills/pre-ship-guardian/ |
如果你使用 Claude Code,也可以放到:
1 | .claude/skills/pre-ship-guardian/ |
1. 编写 SKILL.md
SKILL.md 是 Agent 工具的入口。它不要写成“发布知识百科”,而要写成一个可执行流程。
1 | --- |
这个 Skill 已经包含了触发条件、排除条件、工作流、输出格式、常见跳步借口和验证清单。Agent 看到这个文件后,不需要再猜“发布前检查应该做什么”。
2. 把长检查清单放到 references
发布检查清单可能很长,不适合全部放在 SKILL.md。可以放到 references/launch-checklist.md:
1 | # Launch Checklist |
这样做的好处是:只有当发布检查 Skill 被触发时,Agent 才需要读取这份清单;平时不会占用上下文。
3. 用脚本收集变更事实
让模型“根据记忆总结 diff”是不可靠的。更好的方式是用脚本收集事实,并输出 JSON。
scripts/collect_change_summary.py 可以这样写:
1 | #!/usr/bin/env python3 |
脚本只负责收集事实,不做复杂判断。判断交给 Agent,事实来源交给脚本,这就是清晰的职责边界。
4. 触发方式
在支持自动发现 Skill 的工具中,用户可以直接说:
1 | 请检查当前分支是否可以发布到生产环境。 |
或者显式指定:
1 | 使用 pre-ship-guardian 检查当前变更,给出 GO/NO-GO 和 rollback plan。 |
如果你使用支持 slash command 的环境,也可以再做一个薄命令,把触发词固化下来。命令只负责入口,不要把所有检查逻辑复制进去:
1 | Invoke the pre-ship-guardian skill. |
这和 agent-skills 项目里的 /ship 思路一致:命令是入口,Skill 是流程,Persona 或子 Agent 是独立视角。
5. 什么时候升级成并行 fan-out
上面的 pre-ship-guardian 是单 Skill。对于小团队或低风险项目,这已经够用。等你发现发布前检查经常需要多个独立视角,再升级成并行 fan-out:
1 | -> code-reviewer -> code quality report |
升级前要确认三件事:
- 三个视角能独立工作,不需要互相等待。
- 每个视角的输出有明显差异,不是在重复同一份检查。
- 主 Agent 能在剩余上下文里合并报告,而不是再次丢失细节。
如果这些条件不满足,就继续使用单 Skill。Agent 工具的目标是稳定完成任务,不是展示复杂架构。
Skill、Script、MCP、Subagent 怎么选
构建 Agent 工具时,经常会混淆这些能力。可以按职责区分:
- Skill:封装流程、规则、触发条件和验证要求。
- Reference:保存长文档、检查清单、领域规则、模板。
- Script:执行确定性逻辑,输出结构化结果。
- MCP Tool:连接外部系统,例如 CI、监控、工单、数据库。
- Subagent / Persona:提供独立上下文和独立视角。
举例来说,发布前检查里:
- 用 Skill 定义发布检查流程。
- 用 Reference 保存发布清单和安全清单。
- 用 Script 收集 git 事实和生成报告骨架。
- 用 MCP 查询 CI、监控或工单状态。
- 用 Subagent 并行做代码、安全、测试三类审查。
不要把所有东西都塞进 Skill 正文。Skill 应该像一个任务说明书,告诉 Agent 什么时候读资料、什么时候运行脚本、什么时候调用外部工具、什么时候停止并要求人工确认。
常见坑
坑一:把 Skill 写成知识库
如果 SKILL.md 里充满背景知识,但没有明确步骤、输入输出和验证,Agent 读完也不知道该做什么。知识可以放到 references/,SKILL.md 应该保留可执行流程。
坑二:description 写得太像完整流程
description 是发现入口,不是执行说明。它应该简短说明“做什么”和“何时用”。如果把完整步骤写进去,Agent 可能不会再读取正文。
坑三:没有验证闭环
“检查完成”“看起来没问题”“应该可以发布”都不是证据。可靠的 Skill 必须要求可验证输出,例如测试结果、命令输出、报告字段、截图或人工确认。
坑四:脚本副作用不清晰
脚本应该默认只读,除非 Skill 明确说明它会修改文件、提交代码或调用外部系统。涉及生产、密钥、网络请求、数据删除的脚本必须有人工确认。
坑五:过度编排
不是所有任务都需要多个 Agent。单视角、单产物、低风险任务,直接调用一个 Skill 最便宜也最稳定。并行 fan-out 只适合子任务独立、视角差异明显、合并成本可控的场景。
坑六:把上下文窗口当存储
长文档、完整日志、历史对话、工具 schema 全塞进去,会让模型注意力分散。更好的做法是分层加载、按需读取、脚本输出摘要、外部系统保留原始数据。
落地清单
当你准备把一个具体任务做成 Agent 工具时,可以按这个清单执行:
- 写一句话目标:这个工具帮助 Agent 完成什么任务?
- 写触发条件:用户说什么、看到什么文件、处于什么阶段时启用?
- 写排除条件:哪些情况不要用,必须先问人?
- 定义输入输出:输入来自哪里,最终交付什么?
- 拆流程:按阶段写成编号步骤。
- 分配上下文:核心流程进
SKILL.md,长资料进references/,确定性逻辑进scripts/。 - 写验证清单:没有证据时不能宣称完成。
- 写常见借口:把 Agent 容易跳过的步骤提前拦住。
- 先从单 Skill 运行,再根据重复性和独立性决定是否加入 Command、Persona 或并行 fan-out。
- 像维护代码一样维护 Skill:版本管理、评审、测试、审计脚本。
总结
从 agent-skills 项目可以提炼出一个核心原则:好的 Agent 工具不是更长的提示词,而是把人的工程流程转化为可执行、可验证、可组合的系统。
真正可复用的方法包括:
- 用
description做精准触发,用SKILL.md写可执行流程。 - 用
references/和scripts/控制上下文成本。 - 用验证清单和常见借口约束 Agent 不跳步。
- 用 Command 和 Persona 做轻量编排,而不是堆叠多层代理。
- 用 MCP 接外部系统,但保留安全边界和人工确认。
如果你要为自己的团队构建 Agent 工具,建议先选一个高频、边界清晰、有明确交付物的任务开始。例如“发布前检查”“PR 审查”“日志排障”“技术文章翻译”。先做成一个单 Skill,跑通后再逐步加入脚本、参考资料、外部工具和并行审查。这样构建出来的 Agent 能力,才会从一次性的聊天技巧,变成团队可持续复用的工程资产。
参考资料
- Agent Skills | Cursor Docs
- Agent Skills | Anthropic Docs
- Extend Claude with skills | Claude Code Docs
- Tools | Model Context Protocol
- addyosmani/agent-skills
本文由 AI 辅助生成,如有错误或建议,欢迎指出。






