跳至主要內容

程式碼模式

新增於: @mastra/core@1.38.0

beta

此功能目前為 beta 版本。在 API 穩定之前,即使主要版本號不變,亦可能會有破壞性變更。

程式碼模式讓 Agent 在隔離的 Sandbox 中執行涉及多個 Tool 的運算,並將結果以單一而更準確的回應傳回。

模型不會每次輪流呼叫一個 Tool,而是針對用戶查詢編寫專用函式。該函式會將你現有的 Tool 編排為 external_* 函式,並歸納或匯總其結果,產生一個結構化答案。

createCodeMode() 會傳回此 Tool,其預設 idexecute_typescriptid 可自行設定,因此一個 Agent 可同時擁有數個程式碼模式 Tool,而每個 Tool 可限定使用不同的一組 Tool(請參閱為多個程式碼 Tool 設定 Tool 範圍)。

何時使用程式碼模式
何時使用程式碼模式 的直接連結

當 Agent 需要使用多個 Tool 來回答用戶查詢或執行複雜運算時,可使用程式碼模式:

  • 減少往返次數:涉及多個 Tool 的查詢只需一次 Tool 呼叫即可執行,毋須為每次 Tool 選擇重複執行 Agent 迴圈。
  • 縮小上下文:函式可在將大型 Tool 回應傳回 Agent 前,先行歸納或匯總內容。
  • 準確運算:總和、平均值及其他算術運算會以 JavaScript 執行,而非透過 token 預測完成。
  • 預先規劃:篩選、匯總及分支邏輯均在函式內進行,而非分散於不同輪次。

運作方式
運作方式 的直接連結

不使用程式碼模式時,涉及多個 Tool 的查詢可能會多次執行 Agent 迴圈。模型會選擇一個 Tool 並讀取結果,再按需要重複此過程。

每一輪都會將完整的 Tool 回應加入 Agent 的上下文視窗,可能導致推理質素下降,並增加 token 用量。

使用程式碼模式時,你的 Tool 仍會在主機上執行,並保留完整的驗證、請求上下文及追蹤功能。只有模型編排 Tool 的程式碼會在 Sandbox 中執行。每次呼叫 external_* 都會橋接回主機上實際的 Tool,而函式可先歸納或匯總結果,再向 Agent 傳回單一回應。

函式會在 Workspace Sandbox 中執行。程式碼模式會執行由模型編寫的程式碼,因此必須使用 Sandbox,並審慎選擇執行邊界。你可以透過 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 },
})

當用戶問「銷量最高的五款產品是甚麼?每款產品的平均評分又是多少?」時,模型會發出一次 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 並行執行呼叫,程式碼模式最能發揮作用。

請參閱 createCodeMode() 參考資料,了解設定選項、傳回值、結果結構及如何檢視指示。

為多個程式碼 Tool 設定 Tool 範圍
為多個程式碼 Tool 設定 Tool 範圍 的直接連結

createCodeMode() 會擷取其本身的允許清單。多次呼叫此函式,即可為 Agent 提供數個程式碼 Tool,並讓每個 Tool 限定使用不同的 Tool 子集。程式碼 Tool 只能呼叫傳入其本身 createCodeMode() 呼叫的 Tool 所對應的 external_* 函式,因此各個子集會保持隔離。

請為每個 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 的直接連結

程式碼模式預設使用一種 Transport,將程式寫入主機檔案系統,再透過 node 執行。這種方式適用於與主機共用環境的 LocalSandbox,但不適用於在其本身 micro-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 的情況下取得安全邊界,可使用 @mastra/isolated-vm 提供的 IsolatedVmCodeModeTransport。它會在程序內的 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 參考資料