首页
/ 如何配置 Mastra code mode 让代理在隔离沙箱中执行多工具计算

如何配置 Mastra code mode 让代理在隔离沙箱中执行多工具计算

2026-09-12 22:57:21作者:劳婵绚Shirley

当代理需要连续调用多个工具才能回答一个问题时(比如“取前 5 名产品并计算每个的平均评分”),默认行为是 agentic loop 每轮选一个工具、把完整工具响应追加进上下文,重复若干轮。Mastra 的 code mode(@mastra/core@1.38.0 起提供,目前处于 beta,API 稳定前可能有 breaking changes)改变了这一过程:模型为查询写出一个定制的 TypeScript 函数,在隔离沙箱中把配置好的工具当作 external_* 函数编排起来,做归约、聚合和运算,最后只向代理返回一个结构化结果。

这篇文章完成一件事:把 code mode 工具配置到你的 Agent 上,选一个合适的隔离执行边界,并验证生成的程序确实只在沙箱内运行。

准备条件

  1. @mastra/core 版本不低于 1.38.0
  2. 按你要选择的执行边界安装对应包(三种都是可选,装哪个取决于第三节的选型):
# 进程内 V8 隔离
npm install @mastra/isolated-vm
# 或:QuickJS(WebAssembly,无原生二进制)
npm install @mastra/quickjs
# 或:远程微 VM 沙箱
npm install @mastra/e2b

isolated-vm 是原生插件,常见平台提供预编译二进制;只有在不匹配的平台才需要 C++ 工具链从源码编译。@mastra/quickjs 只包含 WebAssembly 模块,安装即复制文件,无需其他设置。

主路径:用 createCodeMode() 创建工具并挂到 Agent

createCodeMode() 返回工具本身和一段生成好的 instructions。不指定 id 时,工具名默认是 execute_typescript。两样都要加到 Agent:instructions 合并进 instructions 数组,工具以同一个 id 注册进 tools

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(),
})

export const shopAgent = 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 },
})

示例中的 fetchTopProducts / fetchRatings 是文档示例里假定的数据获取函数,替换为你自己的实现;model: 'openai/gpt-5.6-sol' 是文档示例展示的模型标识,可按你接入的模型替换。

配置项的适用条件(来自 createCodeMode() reference):

  • tools:暴露给生成代码的工具,以 external_<id> 函数形式出现。生成代码只能调用传给这次 createCodeMode() 的工具,别的不行。
  • sandbox:执行生成代码的沙箱。除非 Agent 运行在自带沙箱的 workspace 中,或 transport 自带执行边界,否则必须显式传入。
  • timeout:执行超时(毫秒),默认 30000
  • id:生成的工具 id,默认 execute_typescript

注意 new LocalSandbox() 的含义:它和主机共享文件系统,生成的程序以主机 node 进程、带主机权限运行,只应用于受信任的代码或本地开发。生产边界见下一节。

选择隔离执行边界

code mode 的隔离边界由 transport 决定。三种 transport 都在主机侧执行同一套白名单、工具校验和 tracing,区别在程序本身能触达什么、主机需要提供什么(对照表来自 QuickJsCodeModeTransport 文档):

StdioCodeModeTransport(默认) IsolatedVmCodeModeTransport QuickJsCodeModeTransport
隔离边界 Workspace sandbox V8 isolate QuickJS WebAssembly runtime
需要沙箱
原生二进制 沙箱内的 Node.js runtime
Node.js 标志 Node.js 20 及以后需要 --no-node-snapshot
可在浏览器运行
执行速度 最快 最慢

进程内 V8 隔离:IsolatedVmCodeModeTransport

不需要沙箱、不派生进程、不写临时文件,适合没有 OS 级沙箱的 serverless 或多租户主机。把 transport 作为 createCodeMode() 的第二个参数传入,配置里不再需要 sandbox

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

const { tool, instructions } = createCodeMode(
  { tools: { getTopProducts, getProductRatings } },
  new IsolatedVmCodeModeTransport({ memoryLimitMb: 128 }),
)

硬性前提:在 Node.js 20 及以后,宿主进程必须带 --no-node-snapshot 启动,否则创建 isolate 会崩溃,构造器会以错误形式报告缺少该标志:

NODE_OPTIONS=--no-node-snapshot npm run dev

isolate 没有文件系统、网络、进程或模块访问能力,唯一能力就是回调到主机的 external_* 函数。memoryLimitMb(默认 128)是 V8 isolate 堆上限(MiB),超限的程序被终止,工具返回错误结果。每次运行创建全新 isolate,运行结束后销毁。

替代分支:QuickJS(主机装不了原生插件时)

主机既不能装原生插件也不能设 Node.js 标志(serverless 平台常见)时,用 @mastra/quickjsQuickJsCodeModeTransport。执行边界相同——程序无文件系统、网络、进程、模块访问——代价是执行更慢:QuickJS 是解释执行,计算密集循环可比 V8 isolate 慢几十倍;而主要时间在 await external_* 上的程序两者表现接近,Code Mode 程序通常属于后者。

import { createCodeMode } from '@mastra/core/tools'
import { QuickJsCodeModeTransport } from '@mastra/quickjs'

const { tool, instructions } = createCodeMode(
  { tools: { getTopProducts, getProductRatings } },
  new QuickJsCodeModeTransport({ memoryLimitMb: 128 }),
)

参数:memoryLimitMb(默认 128,MiB 堆上限,超限程序被终止并返回错误结果);maxStackSizeBytes(默认 1048576,字节,通常由失控递归触发)。

替代分支:远程微 VM 沙箱(E2B)

默认的 StdioCodeModeTransport 把程序写到主机文件系统再跑 node,这只有在沙箱与主机共享文件系统(如 LocalSandbox)时成立。E2B 这类在自己微 VM 里运行的远程沙箱没有主机路径,需要把程序写进沙箱文件系统的 transport。@mastra/e2b 提供 E2BCodeModeTransport,作为第二个参数传入:

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

const { tool, instructions } = createCodeMode(
  {
    tools: { getWeather, getForecast },
    sandbox: new E2BSandbox({ timeout: 60_000 }),
  },
  new E2BCodeModeTransport(),
)

使用前需要可用的 E2B API key:E2BSandboxapiKey 参数缺省时回退到 E2B_API_KEY 环境变量。E2BCodeModeTransport 会在沙箱未运行时自动启动它,在主机侧用 esbuild 剥离 TypeScript(不依赖沙箱内的 Node 版本),在 VM 内运行 node,并在结束后清理程序文件。更多 E2B 沙箱参数见 E2B 集成文档

验证配置是否生效

验证分两层:

  1. 行为层:向 Agent 提出一个需要组合多个工具的问题,例如文档示例中的 “What are the top 5 products and the average rating for each?”。配置正确时,模型发出一次 execute_typescript 调用,而不是多次分开的工具调用。文档示例展示的生成程序如下(示例代码,你的工具不同则不同):
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 中算出,代理收到一个结构化结果。

  1. 返回值层:生成的工具返回 CodeModeToolResult
  • success: boolean——生成代码是否无抛错地跑完;
  • result: unknown——生成代码的返回值(可选);
  • logs: string[]——按顺序捕获的 console.log / console.info / console.warn / console.error 输出(可选);
  • error: { message, name?, line? }——代码抛错或执行失败时的错误详情(可选)。

successfalse 时看 error.messageerror.line 定位生成代码的问题;正常跑完但结果不对时,logs 是调试入口。

如果只想检查注入给模型的提示内容,用 createCodeModeInstructions()

import { createCodeModeInstructions } from '@mastra/core/tools'

console.log(
  createCodeModeInstructions({
    tools: { getTopProducts, getProductRatings },
  }),
)

输出包含使用约定和每个工具一行带类型的 declare function external_<id>(...)。工具 id 会被净化成合法 TypeScript 函数名;净化后重名会抛错——如果这里报错,说明你的工具 id 命名冲突。

另外,只有需要单独管理 instructions 时才用 createCodeModeTool();多数 Agent 应使用 createCodeMode(),让工具和配套 instructions 保持绑定。

限制与注意事项

  • beta:code mode 相关 API 在稳定前可能无 major 版本号升级就发生 breaking change。
  • LocalSandbox 无隔离:程序以主机权限的 node 进程运行,只用于受信任代码或本地开发;生产请用 V8 isolate、QuickJS 或远程沙箱。
  • Node.js 20+ 的启动标志:漏掉 --no-node-snapshot 时,IsolatedVmCodeModeTransport 的构造器会报错,这是最典型的启动问题。
  • 内存与超时memoryLimitMb 超限、或超过 createCodeMode()timeout(异步挂起和同步死循环都覆盖,运行结束后 isolate/runtime 即销毁)都会导致程序被终止、工具返回错误结果。
  • 最小权限隔离:一个 Agent 可以挂多个 code mode 工具,多次调用 createCodeMode()、每次给不同 id 和不同的 tools 子集,各工具只能调用自己那次调用声明的 external_* 函数,互不可达。instructions 要每个都加进 Agent。

完整文档见 Code modecreateCodeMode() reference;沙箱本身的概念见 Sandbox overview

登录后查看全文
热门项目推荐
相关项目推荐