摘要

1) 一句话总结 Letta API 现已支持编程式工具调用,允许任何 LLM 智能体通过动态编写和执行代码来调用工具并自定义工作流,从而提升上下文效率并降低调用成本。

2) 关键要点

  • 全面兼容 LLM:Letta API 在其 harness(外壳)层实现了编程式工具调用,因此该功能兼容任何连接到 Letta API 的大语言模型。
  • 核心实现方式:通过为智能体附加 run_code_with_tools 工具,智能体可以编写 Python 脚本来直接调用其他已附加的工具(包括 MCP 工具、自定义工具和内置工具)。
  • 服务端执行:Letta 工具的执行完全在服务器端进行,客户端无需进行任何代码更改即可启用该功能。
  • 动态自定义工作流:智能体可以通过脚本自行定义任意工作流(如 map-reduce 模式)和链式工具调用,无需依赖开发者预先硬编码的工作流。
  • 优化上下文:智能体可以通过代码对外部工具(如 MCP 工具)返回的杂乱数据进行后处理,防止无效信息污染 LLM 上下文。
  • 降低成本与 Token 消耗:支持在脚本中并发执行多个工具(并行工具调用),从而大幅减少 LLM 的调用次数和 Token 使用量。
  • 支持有状态智能体:有状态工具在调用者智能体的作用域内运行,能够使用该智能体的环境变量,并通过 LETTA_AGENT_ID 访问智能体 ID。

3) 风险与不足

  • 实验性功能:该功能目前处于实验阶段,开发者可能需要为智能体添加额外的提示词(prompting),才能确保智能体有效地使用该工具。

正文

上周,Anthropic 在 Claude API 中发布了内置的编程式工具调用(programmatic tool calling)支持。尽管让智能体(agents)通过运行任意代码来执行操作的想法并不新鲜(例如 CodeAct 研究论文,以及 Cloudflare 为 MCP 提供的 Code Mode 扩展),但从历史上看,智能体一直依赖于从推理时指定的预定义工具集中挑选单个工具按顺序执行(例如 MCP 服务器提供的工具),而不是动态执行代码。

然而,随着大语言模型(LLM)在编程方面变得极其熟练,智能体可以更多地依赖动态代码执行,而不是基础的工具调用。编程式工具调用允许智能体编写并执行调用工具的代码,将动态代码生成与预定义工具结合起来。这种模式非常强大,因为它允许通用智能体自行定义和执行工作流,而不需要开发者预先定义。换句话说,编程式工具调用允许智能体编写自己的工作流。

在 Letta API 中添加编程式工具调用

Letta API 现在支持为任何 LLM 模型提供编程式工具调用。附加了 run_code_with_tools 工具的智能体可以编写脚本,直接调用附加到该智能体的其他工具。这包括:

  • MCP 工具(由外部 MCP 服务器执行的工具)
  • 自定义工具(由 Letta 执行的用户定义工具)
  • 内置工具(Letta 支持的内存/文件系统/实用工具)

Letta 工具在服务器端执行,因此客户端不需要采取任何操作即可启用编程式工具调用。如果 Letta API 上存在某个工具,那么任何 LLM 都可以通过编程方式调用它,而无需在客户端进行任何更改。

当附加了 run_code_with_tools 时,智能体可以编写一个 Python 脚本来调用附加到该智能体的任何工具。例如,智能体可以编写并执行如下脚本:

Image

这使得智能体能够编写动态调用可用工具的脚本。例如,下面的智能体拥有用于在外部数据库上执行 SQL 查询和搜索网络的 MCP 工具。这意味着智能体可以编写一个脚本,循环遍历数据库查询的结果,并将每个结果传递给网络搜索。在下图中,我们要求智能体在网络上搜索数据库中的每个模拟用户:

Image

智能体生成的代码调用了 MCP 工具 execute_sql 来获取员工列表,然后调用 MCP 工具 web_search_exa 在循环中搜索每个员工(生成的代码如下所示):

Image

编程式工具调用在 Letta 的 harness(测试框架/外壳)层实现,因此它可以与连接到 Letta API 的任何 LLM 一起使用。

为什么要使用编程式工具调用?

编程式工具调用允许智能体更高效地运行工具,并定义在脚本中组合工具调用的任意工作流。

在通用智能体 Harness 中支持工作流与链式工具

许多 LLM 应用程序中的组件其功能更像是工作流而不是智能体——例如,将一个 MCP 工具调用的输出作为另一个工具的输入传递。因此,许多 LLM 框架支持硬编码的工作流来增强智能体。编程式工具调用允许智能体本身根据需要定义工作流。例如,智能体只需运行如下脚本:

Image

即可定义一个组合工具的 map-reduce 工作流模式。结合技能(skills,可以存储定义工作流的代码片段),这使得通用智能体能够执行类似于标准 LLM 框架的预定义工作流。

上下文效率:转换和组合工具输出

外部工具(例如 MCP 工具)通常会返回杂乱或结构不佳的输出。借助编程式工具调用,智能体可以对输出数据进行后处理,从而避免污染 LLM 上下文。

LLM 成本:减少 LLM 调用次数和 Token 使用量

编程式工具调用支持并行工具调用,因为程序可以并发调用多个工具。在下面的示例中,智能体通过编程方式调用内存工具,仅用一次 LLM 调用和一次工具调用,就为数据库中的每个用户(共 10 个)创建了内存块:

Image

针对有状态智能体的编程式工具调用

由于 Letta API 是围绕有状态智能体(stateful agents)设计的,许多智能体都拥有操作智能体状态(例如内存或文件)的有状态工具。

借助编程式工具调用,有状态工具仍然在调用了 run_code_with_tools 的调用者智能体的作用域内运行。这意味着这些工具使用作用域限定于该智能体的环境变量,并且可以通过特殊的 LETTA_AGENT_ID 环境变量访问智能体的 ID。您还可以通过 SDK 直接为智能体调用工具。

后续步骤

要开始使用编程式工具调用,请将 run_code_with_tools 附加到您的 Letta 智能体上。这是一个实验性功能,因此您可能需要添加额外的提示词(prompting),才能让您的智能体有效地使用该工具。

关联主题