Code mode
新增于: @mastra/core@1.38.0
此功能目前处于测试阶段。在 API 稳定之前,可能会发生不伴随主版本号升级的破坏性变更。
Code mode 让 Agent 能够在隔离的 Sandbox 中运行涉及多个 Tool 的计算,并将结果作为一个更准确的响应返回。
模型不再逐轮调用 Tool,而是根据用户查询编写一个专用函数。该函数将现有 Tool 编排为 external_* 函数,并将其结果归并或聚合为一个结构化答案。
createCodeMode() 会返回此 Tool,其默认 id 为 execute_typescript。id 可配置,因此一个 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。