Agent 技能是让 AI Agent 在特定任务上表现更好的最简单方式。正因为它们如此简单,也很容易出错。是的,我们将介绍构建这些技能的五大最佳实践,并简要回顾一下什么是技能:它是赋予 AI Agent 的程序性知识。模型已经掌握大量事实,但它不知道的是你处理特定工作的独特方式。因此,技能就是教它这一点。其格式几乎荒谬地简单:基本上就是一个 skill.md 文件,即文件夹中的 Markdown 文本。
但马丁,这里让我担心的是:Agent 技能是将一个概率模型和文件夹中的文本交给它去执行脆弱的多步任务,并信任它能完成。是的,而且技能还可以包含和运行代码。所以从互联网上排序意味着在你的机器上运行陌生人的软件。虽然 agentskills.io 定义了开放的 Agent 技能标准,但在创建 AI Agent 技能时,我们需要考虑以下事项。马丁,我们要开始讨论最佳实践吗?第一点:让我们开始吧!
最佳实践一:描述是触发器。我的意思是,Agent 的描述决定了技能是否真正运行。你说的“描述”是指什么?每个 skill.md 文件都像这个例子一样,以一段 YAML 开头。在这里我们定义名称和描述。简短地说,根据 agentskills.io 的规定,名称最多为 64 个字符,描述(说明技能实际做什么)限制在 1,024 个字符以内。假设我安装了 100 个这样的技能,Agent 无法一次性读取所有内容而不填满其上下文窗口。
因此在启动时,它只加载每个技能的名称和描述。最佳实践就在这里发挥作用了:是的,没错。因此,名称和描述本身必须包含足够的信息,以便 Agent 知道何时使用它。例如,“合规技能生成报告”可能有点太模糊了。对,对的。解决办法是说明技能做什么以及 Agent 何时应该使用它。给我一个好的描述版本?啊,这听起来像是一个测试,但幸运的是我之前做过一个示例:从内部数据生成月度合规报告;当有人询问合规报告或月报时使用。
它说明了技能做什么,也说明了何时做。我还听说描述应该稍微“强势”一点?强势?模型往往触发不足,可能会跳过本该使用的技能。因此,稍微夸大描述比低估它更安全哦,就像 LinkedIn 帖子一样,明白了吗?所以这是让技能触发。一旦触发后里面放什么?这部分是你的专长,布莱夫。好吧,是的,很多技能就在这里走偏了,因为诱惑是让 LLM 为你编写技能。
我创建的前几个技能都是这样:我说“嘿,AI Agent,为我写一个做 X 任务的技能”,它生成了内容。老实说,我当时只是扫了一眼就调用该技能了,结果构建完全成功。但你得到的只是一团非常通用的糊状物:适当处理错误、验证输入等,这些都是模型已经知道的东西。这就引出了最佳实践二:基于真实专业知识构建。这到底是什么意思?
技能的核心在于你执行特定工作的独特方式。因此,内容必须来自模型无法自行获取的地方。有两种方法:一是你亲手执行任务一次并记录下实际有效的方法,包括你在过程中做出的修正;二是从已有的工件中综合提炼出来,比如旧报告、运行手册、审查意见或 PR 反馈。是的,英国同行西蒙·威利森有一句名言:保留领域专业知识,让 Agent 处理例行公事的部分。没错,威利森先生在这方面绝对正确:你提供专业知识,模型负责打字工作。
这对 skill.md 正文意味着什么?我觉得我已经画过这个框几次了。是的,你确实画过了。这意味着技能正文中价值最高的部分是“陷阱”(gotchas)。那些违背合理假设的环境特定事实。每次你手动纠正 Agent 时,那个修正就是一个陷阱。把它写下来。否则下周、下下周你都会做同样的纠正。嗯哼,你说得对。
现在,即使你做对了所有事情,也不一定能一次成功。我为月度合规报告构建了一个技能,基于我实际做过的真实报告,这正是我们讨论的真实专业知识。但在第一次运行时,行总计与总合计对不上。所以数学计算是对的?不,数学是错的。在合规报告上出错?是的,但这是种“好”错,因为你能发现它。我们稍后会回到这一点。关键是:一个好的技能正文必须详尽无遗。
而详尽意味着它可能会变得……非常、非常长。是的,而且事实证明,越长越昂贵。这就引出了最佳实践三:明智地花费上下文资源。在启动时,Agent 只能看到名称和描述,但当它选择某个技能时,才会真正阅读其余部分。现在我们查看 skill.md 文件的正文并将其带入上下文。这个上下文与上下文窗口中已有的所有内容共享是的,技能正文中的每一行现在都在争夺模型的注意力。
这意味着目标是“写得精简”。这感觉与我们上一个最佳实践有些相悖,因为技能正文越详细、越详尽越好。你会这么想,但模型已经很聪明了。它知道什么是 PDF,知道数据库迁移做什么。因此只写下 Agent 自己不知道的东西:那些不属于 AI 模型训练数据的内容。我们可以用数字来说明:建议将 skill.md 的正文保持在约 500 行文本以内,或者说大约五千个 token,就保持在这个水平。
如果超过这个数量呢?那就把它拆分出来。技能文件夹实际上可以容纳一个名为 references 的子文件夹,这是一个目录,Agent 只有在真正需要时才会打开其中的文件。这是一种称为“渐进式披露”的模式:仅在需要时才披露额外信息,比如这样保持精简。
这是其中一方面,但有些步骤你绝对不希望代理去猜测。那到底是在猜什么?每当模型运行你的技能时,它都会阅读指令并据此即兴发挥。对于松散的步骤来说,这没问题;很多路径都能导向正确答案。但对于那些每次都必须完全正确的关键步骤,你并不希望模型在运行时现场重新生成逻辑。
这听起来像是最佳实践第四条?没错,那就是:使用确定性脚本。根据步骤的脆弱程度来调整指令的强制性程度。如果是松散步骤,就写文字说明;如果是易错的关键步骤,就直接编写代码。好的,那这些代码放在哪里呢?技能文件夹中包含一个名为 scripts 的目录。
这个脚本目录的理念与引用文件类似。你只需把脚本放进去,比如命名为 script one。然后在技能主体中告诉代理“运行这个”即可。由于脚本不会被加载到上下文中,这还能节省 token 用量。而且,相比于让模型每次都从头开始即兴发挥,这种方式更加可靠。
不过,你必须明确表达意图对吧?这样模型才不会仅仅把脚本当作参考资料来阅读。没错,比如明确指出“运行此脚本”或“将此作为参考”。不要把这种关键指示留给模型去猜测。
这在 Claude Code 中有效,但这并非 Anthropic 独有的特性。OpenAI Codex 的操作方式也大致相同。回到我之前的合规报告例子,就是那个需要对行进行汇总和对账的报告。对,就是涉及数学运算的那个。
现在,复杂的计算部分已改为确定性的数学脚本。模型不再自己进行数字相加,而是调用一个脚本来完成加法运算。这样一来,整类错误就彻底消失了。没错,因为脚本不会去猜测。这个数学脚本是在运行代码。
答案不是“多写点测试”。你可以通过测试建立信任,但测试只能捕捉到你已经想到要去检查的内容。正确的做法是:对于那些必须准确无误的部分,把猜测从流程中剔除。
对,这就是要从概率性的模式(代理默认的工作方式)转向更确定性的模型。我在构建技能时经常这样做:如果某些逻辑可以硬编码为确定性规则,我就不希望代理去猜测。因为一旦代理需要做出概率性决策,这些决策在多次运行中往往无法保持一致。
所以,如果你自己构建、阅读过并对易错步骤进行了加固的技能,那就是你可以信任的技能。但并非你运行的所有技能都是你自己构建的,对吧?没错。那那些来自陌生人的技能呢?这就引出了最佳实践第五条:在运行前审查技能。
我说过,技能可以执行代码,这就像在你机器上运行陌生软件一样危险。因此,如我们之前所说,技能文件夹可以包含可执行脚本,这些脚本能够访问各种资源。例如,它们可能访问你电脑上的本地文件系统,甚至获取你随意存放的任何 API 密钥。
这正是技能如此强大的原因所在。但我看到今年早些时候的一项审计扫描了近 4000 个公共技能,其中超过 35% 存在某种安全漏洞,13% 涉及严重问题,如提示注入或直接的恶意软件。
这意味着我们必须像对待任何其他依赖项一样对待代理技能,就像我们在将随机包引入项目前会检查它一样:阅读它的功能并核查它所访问的资源。因此,仅仅因为代理技能是开放标准,并不意味着某个特定技能就是安全的。
这就是我们的五大最佳实践:一个好的技能应该是……代理真正会触发的、基于真实实操经验构建的、保持精简以避免填满上下文窗口的,并在猜测会带来危险或不一致时使用确定性脚本的,且在运行前经过审查的技能。
而且你看,这一切发展迅速。这是一个开放标准,越来越多的代理平台正在采用它。所以这份清单还会增长。这实际上是在问我们是否遗漏了什么?如果你构建过代理技能,或者你有很棒的实践建议,欢迎在评论区分享。最好不是恶意软件的那种。