
Anthropic 推出Agent Skills时,我最初对它所解决的问题持怀疑态度——我们难道不能只用提示和工具吗?——但后来我逐渐认识到它的价值,并在我们内部的代理框架中明确地实现了技能功能。这篇文章将探讨技能所解决的问题、Imprint 的工程团队是如何实现它们的、它们在我们这里的效果如何,以及我们未来可能在哪些方面继续使用它们。
这是“打造内部代理”系列文章的一部分。
智能体技能解决了什么问题?
代理技能是一系列技术,旨在解决三个重要的工作流程问题:
- 利用渐进式披露来更有效地利用受限的上下文窗口
- 尽量减少上下文窗口中冲突或不必要的上下文
- 提供可重用的代码片段来解决重复出现的问题,避免工作流程创建者反复处理诸如 Slack 格式设置或处理大文件等重复性问题。
在我们开始构建内部工作流程时,这三个问题最初看起来都微不足道,但当内部工作流程的数量达到几十个时,它们都变得难以管理。如果没有可重用的代码片段,我就无法一次性改进所有工作流程;如果没有逐步披露,客服人员会收到大量无关内容,这可能会让他们感到困惑,尤其是在 Markdown 和 Slack 的mrkdwn格式语言不一致的情况下,而这两种格式对于我们工作流程中使用的不同工具都至关重要。
我们如何实现代理技能
需要说明的是,我意识到并非必须实现代理技能,因为您可以集成例如Claude 的代理技能 API 支持。然而,我们的设计决策之一是尽可能做到平台无关,以便能够在不同的模型提供商之间切换,因此我们决定在我们的框架中实现技能功能。
解决了这个问题后,我们开始着手实施,首先查阅了agentskills.io上的 Agent Skills 文档,并将他们的 Python 参考实现skills-ref克隆到我们的存储库中,以便 Claude Code 可以访问它。
最终实现方案具有以下核心特性:
-
技能位于
skills/仓库中,每个技能都包含一个子目录和一个SKILL.md文件。 -
每个技能都是一个 Markdown 文件,其中包含如下元数据:
--- name : pdf-processing description : Extract text and tables... metadata : author : example-org version : "1.0" ---在每个工作流程开始时,可用技能列表(包括来自元数据的描述)会被注入到系统提示中,并且--- name : pdf-processing description : Extract text and tables... metadata : author : example-org version : "1.0" --- -
load_skills工具可供代理使用,将整个文件加载到上下文窗口中。 -
更新了工作流程配置,可以选择指定必需技能、允许技能和禁止技能,以修改注入到系统提示符中的已公开技能列表。
我猜想,要求特定技能才能完成特定工作流程有点反模式,“让代理自己决定!”,但实现起来很简单,而且我认为将来可能会有用。
-
使用 Notion MCP 检索我们提示库中所有现有的提示,识别我们创建的提示中现有的隐含技能,编写这些初始技能,并确定要编辑哪些 Notion 提示以消除提示中现在冗余的部分。
然后我们就把它投入生产了。
他们是如何工作的
人总是会犯错。例如,我见过几十个由用户提交的 JIRA 工单,这些工单并没有解释清楚他们遇到的实际问题。人们对此习以为常,当人犯错时,他们会责怪人。然而,当智能体犯错时,相当一部分人却将其视为智能体这一类别本身的固有缺陷,而不是想到“哦,我应该去更新一下提示信息”。
技能功能对于我们持续优化处理这些特殊情况非常有用,因为之前我们依赖的是隐式行为,而要明确具体行为实在太繁琐了。举个例子,我们要求每条 Slack 消息都以指向引发该回复的提示的链接结尾。这种方法一直有效,但格式细节却总是变化不定,令人烦恼且分散注意力:有时是[title](link) ,有时是link ,有时是[link](link) 。有了技能功能,现在(几乎总是)格式一致,而且无需任何人特意在工作流程提示中添加这些说明。
同样,处理大型文件需要一系列不同的工具,这些工具受益于上下文学习(又称 ICL,这是一个比较专业的术语,指的是包含一些正确和错误用法的示例),虽然绝对没有人会将其添加到工作流程提示中,但它对于改进工作流程使用这些工具的方式非常有效。
对于我最初深感怀疑的事情,我现在真希望自己能早点运用这些技能。
我们接下来可能会去哪里?
虽然我们目前的技能运用情况良好,但未来我还想抓住一些机会:
-
添加
load_subskill技能,以支持skills/{skill}/*目录下除SKILL.md文件之外的其他文件。目前为止,这尚未造成重大阻碍,但随着某些技能变得越来越复杂,将不同的使用场景拆分到不同的文件中,将有助于我们更好地利用技能进行渐进式披露。 -
Anthropic 相较于我们的一项显著优势在于其沙盒化的 Python 解释器,它允许技能中包含完整的 Python 脚本,并由工具进行指定和运行。例如,可以将解析 PDF 的脚本包含在技能中,这非常方便。我们目前还没有现成的沙盒化解释器可供我们的智能体使用,但理论上,这可以显著减少我们需要实现的自定义技能数量。
至少,在需要可靠数学运算的操作上,它会比依靠 LLM 尽力执行数学运算做得更好。
我认为这两个功能其实都很容易实现。第一个功能很简单,Claude 几分钟就能搞定。第二个功能实现起来比较麻烦,但其实也可以在不到一个小时内完成:运行一个使用Pyodide运行 Node.js 的 Lambda 函数,并将该 Lambda 函数作为工具公开。只是让 Python 进程调用 Node.js 进程来运行沙盒化的 Python 代码实在太不优雅了,所以我还没完全实现。