跳到主要内容

Code mode

新增于: @mastra/core@1.38.0

beta

此功能目前处于测试阶段。在 API 稳定之前,可能会发生不伴随主版本号升级的破坏性变更。

Code mode 让 Agent 能够在隔离的 Sandbox 中运行涉及多个 Tool 的计算,并将结果作为一个更准确的响应返回。

模型不再逐轮调用 Tool,而是根据用户查询编写一个专用函数。该函数将现有 Tool 编排为 external_* 函数,并将其结果归并或聚合为一个结构化答案。

createCodeMode() 会返回此 Tool,其默认 idexecute_typescriptid 可配置,因此一个 Agent 可以同时拥有多个 Code mode Tool,每个 Tool 的作用域均限定为不同的 Tool 集合(请参阅在多个 Code Tool 之间限定 Tool 作用域)。

何时使用 Code mode
何时使用 Code mode的直接链接

当 Agent 需要使用多个 Tool 来回答用户查询或执行复杂计算时,可使用 Code mode:

  • 减少往返次数:涉及多个 Tool 的查询只需一次 Tool 调用即可运行,无需针对每个 Tool 决策重复 Agent 循环。
  • 缩小上下文:函数可以在将大型 Tool 响应返回给 Agent 前对其进行归并或聚合。
  • 准确计算:求和、平均值和其他算术运算由 JavaScript 执行,而不是通过令牌预测完成。
  • 预先规划:筛选、聚合和分支均在函数内部完成,无需跨多个轮次执行。

工作原理
工作原理的直接链接

不使用 Code mode 时,涉及多个 Tool 的查询可能要多次运行 Agent 循环。模型选择一个 Tool 并读取结果,然后根据需要重复该过程。

每一轮都会将完整的 Tool 响应添加到 Agent 的上下文窗口,这可能导致推理质量下降并增加令牌用量。

使用 Code mode 后,Tool 仍在宿主环境中运行,拥有完整的验证、请求上下文和 Tracing。只有模型生成的编排代码会在 Sandbox 中运行。每个 external_* 调用都会桥接回宿主环境中的真实 Tool,函数可以在向 Agent 返回一个响应前归并或聚合结果。

函数在 Workspace Sandbox 中运行。Code mode 会运行由模型生成的代码,必须明确选择执行边界,因此 Sandbox 是必需的。可以通过 sandbox 传入,也可以在提供 Sandbox 的 Workspace 中运行 Agent。要在宿主机器上执行,请明确传入 new LocalSandbox()。这样会使用宿主权限将函数作为宿主 node 进程运行,因此只能用于可信代码或本地开发。

自身提供执行边界的 Transport 是例外:使用 IsolatedVmCodeModeTransport 时,程序会在进程内 V8 isolate 中运行,不需要 Sandbox(请参阅进程内隔离)。

快速入门
快速入门的直接链接

createCodeMode() 会返回 Tool 和生成的指令。未提供 id 时,Tool 使用 execute_typescript 这一名称。将两者都添加到 Agent 中:

import { Agent } from '@mastra/core/agent'
import { createCodeMode, createTool } from '@mastra/core/tools'
import { LocalSandbox } from '@mastra/core/workspace'
import { z } from 'zod'

const getTopProducts = createTool({
id: 'getTopProducts',
description: 'Get top selling products',
inputSchema: z.object({ limit: z.number() }),
outputSchema: z.object({
products: z.array(z.object({ id: z.string(), name: z.string(), totalSales: z.number() })),
}),
execute: async ({ limit }) => fetchTopProducts(limit),
})

const getProductRatings = createTool({
id: 'getProductRatings',
description: 'Get ratings for a product',
inputSchema: z.object({ productId: z.string() }),
outputSchema: z.object({ ratings: z.array(z.object({ score: z.number() })) }),
execute: async ({ productId }) => fetchRatings(productId),
})

const { tool, instructions } = createCodeMode({
tools: { getTopProducts, getProductRatings },
sandbox: new LocalSandbox(), // required; runs on the host — see "How it works"
})

const agent = new Agent({
id: 'shop-assistant',
name: 'shop-assistant',
instructions: ['You are a helpful shopping assistant.', instructions],
model: 'openai/gpt-5.6-sol',
tools: { execute_typescript: tool },
})

当用户询问“排名前 5 的产品是什么?它们各自的平均评分是多少?”时,模型只会发出一次 execute_typescript 调用,而不是进行多次单独的 Tool 调用:

const top = await external_getTopProducts({ limit: 5 })
const ratings = await Promise.all(
top.products.map(p => external_getProductRatings({ productId: p.id })),
)
return top.products.map((product, i) => {
const scores = ratings[i].ratings.map(r => r.score)
const avg = scores.reduce((sum, s) => sum + s, 0) / scores.length
return {
name: product.name,
sales: product.totalSales,
averageRating: Math.round(avg * 100) / 100,
}
})

所有五次评分查询会并行运行,平均值由 JavaScript 计算,而 Agent 只会收到一个结构化结果。

要让 createCodeMode() 获得良好效果,请注意以下建议:

  • 让每个 Tool 专注于一项任务,以便模型在代码中组合它们。
  • 当调用可以使用 Promise.all 并行执行时,Code mode 的帮助最大。

有关配置选项、返回值、结果结构和指令检查,请访问 createCodeMode() Reference

在多个 Code Tool 之间限定 Tool 作用域
在多个 Code Tool 之间限定 Tool 作用域的直接链接

createCodeMode() 会捕获自己的允许列表。多次调用它,可以为 Agent 提供多个 Code Tool,每个 Tool 的作用域均限定为不同的 Tool 子集。它只能调用 external_* 函数,而这些函数对应于传递给自身 createCodeMode() 调用的 Tool,因此各子集会保持隔离。

为每个 Tool 指定不同的 id 以避免 ID 冲突,并将每个 Tool 的指令添加到 Agent:

const sales = createCodeMode({
id: 'sales_code',
tools: { listRecentOrders, getCustomer },
sandbox,
})

const inventory = createCodeMode({
id: 'inventory_code',
tools: { listProducts, getSupplier },
sandbox,
})

const agent = new Agent({
id: 'ops-assistant',
name: 'ops-assistant',
instructions: ['You are an ops assistant.', sales.instructions, inventory.instructions],
model: 'openai/gpt-5.6-sol',
tools: { sales_code: sales.tool, inventory_code: inventory.tool },
})

sales_code 生成的代码无法调用库存 Tool,反之亦然。这样可以实现最小权限作用域,并减小每个 Tool 的提示词范围。

远程 Sandbox
远程 Sandbox的直接链接

默认情况下,Code mode 使用一种 Transport:它会将程序写入宿主文件系统,并对其运行 node。这适用于与宿主共享环境的 LocalSandbox,但不适用于在自身微型 VM 中运行的远程 Sandbox(例如 E2B),因为宿主路径在其中并不存在。

远程 Sandbox 需要使用能将程序写入 Sandbox 文件系统的 Transport。对于 E2B,请将随附的 E2BCodeModeTransport 作为第二个参数传递给 createCodeMode

import { createCodeMode } from '@mastra/core/tools'
import { E2BSandbox, E2BCodeModeTransport } from '@mastra/e2b'

const { tool, instructions } = createCodeMode(
{ tools, sandbox: new E2BSandbox() },
new E2BCodeModeTransport(),
)

进程内隔离
进程内隔离的直接链接

要在不生成进程或运行远程 Sandbox 的情况下获得安全边界,请使用 IsolatedVmCodeModeTransport,它由 @mastra/isolated-vm 提供。它会在进程内 V8 isolate 中运行程序,因此不需要 Sandbox:isolate 无法访问文件系统、网络或进程,唯一能力是通过桥接调用宿主环境中 Tool 的 external_* 函数。

import { createCodeMode } from '@mastra/core/tools'
import { IsolatedVmCodeModeTransport } from '@mastra/isolated-vm'

const { tool, instructions } = createCodeMode(
{ tools }, // no sandbox needed
new IsolatedVmCodeModeTransport({ memoryLimitMb: 128 }),
)

isolated-vm 是原生插件;在 Node.js 20 及更高版本中,必须使用 --no-node-snapshot 标志启动宿主进程。设置详情请参阅 IsolatedVmCodeModeTransport Reference