跳到正文
LangChain:Blog·· 1 小时前精选AI 评分60

LangChain 重构 Deep Agents 的 Skills 支持,新增工具绑定、固定技能与线程内重载

Revamping Skills in Deep Agents

AI 导读

LangChain 重构 Deep Agents 的 Skills 支持,针对企业技能库增至数千个技能的场景推出三项更新:工具可绑定到技能、仅在该技能被读取时加载,用户可通过 /meeting-prep 之类的显式请求固定技能以在首次模型调用前加载,长线程可通过将 skills_metadata 设为 None 重载新增或变更的技能。

推荐理由

原文详解了 Deep Agents 技能机制的三项升级和加载原理,读者可以据此评估大规模技能库的上下文管理方案。

正文 · AI 翻译

技能是为智能体提供领域知识的最佳方式之一。技能是一个包含指令、脚本和参考文件的文件夹,教会智能体如何做事,比如像你的销售团队那样准备客户会议或审阅通话记录。Agent Skills 是一项开放标准,可与任何模型配合使用,并受到数十种智能体产品的支持。你也不需要懂技术才能编写一个:其核心就是一个 markdown 文件。

技能之所以有效,是因为渐进式披露。智能体一开始只能看到每个技能的名称和描述,只有在任务需要时才读取完整指令。这样可以让上下文保持精简,而上下文工程是构建高效智能体的关键。

随着使用规模扩大,团队对技能的需求也在变化。我们看到企业技能注册表增长到数千个技能,跨团队和智能体共享。我们改进了 Deep Agents 中的技能支持,以解决一些常见需求:

  • 将工具绑定到技能:绑定到某个技能的工具只有在智能体读取该技能时才会加载。
  • 固定技能:当用户明确请求某个技能时,例如 /meeting-prep,你的应用可以在下一次模型调用前加载它。
  • 技能重新加载:长时间运行的线程可以获取新增或更改的技能,而无需重新开始。

技能如何工作

一个技能是一个目录,其中包含一个 SKILL.md 文件:带有 name 和 description 的 YAML frontmatter,后面是智能体遵循的指令。一个技能还可以在 scripts/、references/ 和 assets/ 下捆绑支持文件(规范)。

Only a skill's name and description are always in context. The agent reads the instructions on demand, and loads scripts, references, and assets only when needed.

只有技能的名称和描述始终在上下文中。智能体按需读取指令,并且只在需要时加载脚本、参考资料和资产。

在本文中,我们将使用我们的 GTM 智能体作为贯穿始终的示例。它构建在 Deep Agents 之上,其包含 50 多个技能的库涵盖了销售代表的重复性工作,例如 meeting-prep、call-transcripts 和 competitive-intel-card。

技能分三个层级加载:

  1. 发现。启动时,智能体在其系统提示中看到每个技能的 name 和 description。
  2. 激活。当任务匹配某个技能时,智能体读取带有 read_file 的完整 SKILL.md。
  3. 执行。智能体遵循指令,并且只在需要时读取脚本或参考文件。

The agent's context grows only by what the task needs: every skill's name and description at startup, then one skill's instructions, then one reference file.

智能体的上下文只按任务所需增长:启动时每个技能的名称和描述,然后是一个技能的指令,然后是一个参考文件。

在技能被使用之前,它只占用系统提示中的一行,因此一个库可以容纳大量技能的引用,而不会挤占上下文。现在让我们深入了解我们在 Deep Agents 中做出的增强。

将工具绑定到技能

技能通常会告诉智能体如何使用特定工具,而有些工具只有在智能体读取了这些指令后才能很好地工作。到目前为止,技能和工具是分开披露的。你可以通过工具搜索将工具模式排除在上下文之外,但没有任何东西将工具与解释它的技能绑定在一起:智能体可以在不读取其技能的情况下找到并调用工具,或者读取了技能却仍然不得不搜索其工具。

现在你可以将工具绑定到技能,这样技能及其工具会一起被披露。绑定的工具在 agent 读取其技能之前不会被加入上下文,在此之前调用它会因未知工具而失败。这样可以保持上下文精简,也意味着 agent 在调用工具之前已经阅读了如何使用它。在我们的GTM agent中,call-transcripts 解释了如何搜索通话和阅读转录文本,因此它是绑定这些工具的自然位置。

在技能 frontmatter 的 metadata.include_tools 下列出工具:

call-transcripts SKILL.md frontmatter listing include_tools: search_calls get_transcript

将这些工具传给 SkillsMiddleware,而不是传给 agent:

Python: create_deep_agent with SkillsMiddleware(tools=[search_calls, get_transcript])

Reading call-transcripts unlocks search_calls and get_transcript. They arrive in a new system message, so the cached prefix above it stays unchanged.

阅读通话转录文本会解锁 search_calls 和 get_transcript。它们会出现在一条新的系统消息中,因此其上方已缓存的 prefix 保持不变。

在对话中途添加工具过去意味着要编辑请求的工具列表,这会使 prompt 缓存失效。Anthropic 和 OpenAI 现在允许较新的模型在对话中途接受工具,因此在这些模型上,Deep Agents 会在技能被读取后立即添加该技能绑定的工具,且已缓存的 prefix 保持不变(Anthropic 和 OpenAI 集成文档)。在其他模型上,工具会像以前一样追加到请求中。

列表适用于大多数技能。为了获得更多控制,技能可以列出一个标签而不是工具名称,而你传给 SkillsMiddleware 的函数会将每个标签转换为工具。这样你可以:

  • 披露整个工具组,例如 MCP 服务器上的所有工具,用一个名称表示,而无需在技能中逐一列出每个工具。
  • 根据运行时权限限制工具。该函数会接收图的运行时,因此它可以检查用户是谁,并只返回他们被允许使用的工具。

在这里,call-transcripts 获取 calls MCP 服务器上的所有工具,pipeline-forecast 获取 CRM 工具,但只有经理可以更新预测:

SKILL.md frontmatter for call-transcripts (include_tools: call_tools) and pipeline-forecast (include_tools: crm_tools)

Python: resolve_skill_tools returns every calls MCP tool for call_tools, and update_forecast only for managers

更多内容请参见向技能添加工具。

固定技能

有时用户已经知道自己想要哪个技能。在我们的 GTM agent 中,销售代表可以输入 /meeting-prep for my Acme call tomorrow。如果不固定,模型只能看到技能的描述,并且必须读取它。这会在工作开始前增加一次往返,而且模型不保证会加载正确的技能。使用固定技能后,你的应用会在消息中找到技能名称(或从 UI 中解析),并将它们传入 pinned_skills,中间件会在下一次模型调用前将每个技能的指令添加到对话中。Deep Agents 本身不解析消息,因此语法由你选择:

Typing /meeting-prep names the skill, so the app can pin it for the agent's next model call.

输入 /meeting-prep 会指定该技能,因此应用可以为 agent 的下一次模型调用固定它。

Python: parse /meeting-prep from the message and pass it as pinned_skills to agent.invoke

A pinned skill's instructions are already in the conversation, so the agent starts the work on model call 1 instead of model call 2.

固定技能的指令已经在对话中,因此 agent 会在第 1 次模型调用时就开始工作,而不是第 2 次。

这降低了延迟,并使行为更可预测:指令保证在上下文中,而且固定技能绑定的工具也会随之而来。每个固定技能都会作为一条带标签的消息添加一次,因此较早的消息永远不会改变,prompt 缓存保持有效,聊天 UI 可以将该技能显示为标签,而不是显示其全文。

在线程中途重新加载技能

技能会在每个线程开始时加载,并保存在 agent 状态中,因此之后的每一轮都会复用同一组技能。现在你可以在调用 agent 时将 skills_metadata 设置为 None,从而使此列表失效。如果队友向库中添加了一个 competitive-intel-card 技能,应用可以选择使技能列表失效,下一次运行将重新扫描每个来源:

Python: agent.invoke with skills_metadata set to None

Setting skills_metadata to None makes the next run rescan the skill library and pick up a skill added since the last run.

将 skills_metadata 设为 None 会让下一次运行重新扫描技能库,并拾取自上次运行以来新增的技能。

重新加载时若发现新技能,会改变系统提示词,从而使提示词缓存失效。对于已经闲置一段时间的线程,这一成本通常已经支付过了:提供商的缓存通常在闲置几分钟到一小时后过期(Anthropic、OpenAI),因此当代表回来时缓存已经变冷。

由于重置只是运行输入,你也可以把控制权交给用户。例如,客户端上的一个 /reload 命令:

Python: a /reload command sets skills_metadata to None in the run payload

你也可以从 update_state 或中间件进行重置,这样你的应用就能控制技能重新加载的时机。参见重新加载技能。

开始使用

技能是为智能体提供有组织的领域知识的行业标准机制。这些更新让它们更易于大规模运行:工具仅在技能需要时才加载,工作流所需的技能会预先加载,长时间运行的线程会随着你的技能库变化而保持最新。而且由于技能是开放标准,你的团队编写的技能可跨模型和智能体使用。

所有这些都可在最新的 deepagents 中使用。阅读技能文档开始使用,并通过 GitHub issues、论坛或 X 告诉我们你的想法。

致谢

感谢 Rich Scarrott 主导这些新功能的开发,以及 Hunter Lovell 进行功能与博客审阅!

来源:LangChain:Blog · langchain.com