본문으로 건너뛰기

코드 모드

추가된 항목: @mastra/core@1.38.0

:::실험적

이 기능은 베타 버전입니다. API가 안정될 때까지 주요 버전 변경 없이 주요 변경 사항이 발생할 수 있습니다.

:::

코드 모드를 사용하면 Agent가 격리된 샌드박스에서 다중 Tool 계산을 실행하고 결과를 보다 정확한 단일 응답으로 반환할 수 있습니다.

Tool을 한 번에 하나씩 호출하는 대신 Model이 사용자 쿼리에 맞는 사용자 지정 함수를 작성합니다. 이 기능은 기존 Tool을 external_* 함수로 제공하며, 하나의 구조화된 답변을 반환하기 전에 결과를 축소하거나 집계합니다. createCodeMode()는 기본 idexecute_typescript인 Tool을 반환합니다. id는 구성할 수 있으므로 Agent가 서로 다른 Tool 집합으로 범위가 지정된 여러 코드 모드 Tool을 동시에 보유할 수 있습니다(여러 코드 Tool 간 Tool 범위 지정 참조).

코드 모드를 사용하는 경우
코드 모드를 사용하는 경우에 대한 직접 링크

Agent가 사용자 쿼리에 응답하거나 복잡한 계산을 수행하기 위해 여러 Tool을 사용하는 경우 코드 모드를 사용합니다.

  • 왕복 횟수 감소: 모든 Tool 결정에 대해 Agent 루프를 반복하는 대신 다중 Tool 쿼리가 하나의 Tool 호출로 실행됩니다.
  • 더 작은 컨텍스트: 이 기능은 대규모 Tool 응답을 Agent에 반환하기 전에 축소하거나 집계할 수 있습니다.
  • 올바른 수학: 합계, 평균 및 기타 산술은 토큰 예측이 아닌 JavaScript로 실행됩니다.
  • 사전 계획: 필터링, 집계 및 분기는 별도의 차례가 아닌 함수 내에서 발생합니다.

작동 원리
작동 원리에 대한 직접 링크

코드 모드가 없으면 다중 Tool 쿼리가 Agent 루프를 여러 번 실행할 수 있습니다. Model은 Tool을 선택하고 결과를 읽습니다. 필요에 따라 프로세스를 반복합니다.

매 턴마다 Agent의 컨텍스트 창에 전체 Tool 응답이 추가되어 추론이 저하되고 토큰 사용량이 증가할 수 있습니다.

코드 모드를 사용해도 Tool은 전체 유효성 검사, 요청 컨텍스트, 추적을 적용받으며 호스트에서 계속 실행됩니다. Model의 오케스트레이션 코드만 Sandbox에서 실행됩니다. 각 external_* 호출은 호스트의 실제 Tool로 다시 연결되며, 함수는 Agent에 하나의 응답을 반환하기 전에 결과를 축소하거나 집계할 수 있습니다. 이 기능에는 Workspace Sandbox가 필요합니다. 코드 모드는 Model이 작성한 코드를 실행하므로 실행 경계를 신중하게 선택해야 하며, 따라서 Sandbox가 필수입니다. sandbox를 통해 전달하거나 Sandbox를 제공하는 Workspace에서 Agent를 실행하세요. 호스트 머신에서 실행하려면 new LocalSandbox()를 명시적으로 전달합니다. 그러면 함수가 호스트 권한을 가진 호스트 node 프로세스로 실행되므로 신뢰할 수 있는 환경이나 로컬 개발에만 사용하세요. 자체 실행 경계를 제공하는 전송은 예외입니다. IsolatedVmCodeModeTransport를 사용하면 프로그램이 프로세스 내 V8 격리 환경에서 실행되므로 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개 제품과 각 제품의 평균 평점은 무엇입니까?"라고 질문하면 Model은 여러 Tool 호출 대신 하나의 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,
}
})

5개의 평가 조회는 모두 병렬로 실행되고 평균은 JavaScript로 계산되며 Agent는 하나의 구조화된 결과를 받습니다.

createCodeMode()가 원활하게 작동하도록 다음 팁을 유의하세요.

  • Tool에 집중하여 각 Tool이 한 가지 작업을 잘 수행하고 Model이 Tool을 코드로 구성하도록 합니다.
  • 코드 모드는 호출을 병렬화할 수 있는 경우 가장 도움이 됩니다.Promise.all.

구성 옵션, 반환 값, 결과 형태, 지침 검사에 관한 내용은 createCodeMode() 참조를 확인하세요.

여러 코드 Tool에 대한 범위 지정 Tool
여러 코드 Tool에 대한 범위 지정 Tool에 대한 직접 링크

createCodeMode()는 자체 허용 목록을 캡처합니다. Agent에 서로 다른 Tool 하위 집합으로 범위가 지정된 여러 코드 Tool을 제공하려면 이 메서드를 여러 번 호출하세요. 각 Tool은 자체 createCodeMode() 호출에 전달된 Tool의 external_* 함수만 호출할 수 있으므로 하위 집합이 서로 격리됩니다. ID가 충돌하지 않도록 각 Tool에 고유한 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의 Prompt 영역을 작게 유지하세요.

원격 샌드박스
원격 샌드박스에 대한 직접 링크

기본적으로 코드 모드는 프로그램을 호스트 파일 시스템에 쓰고 해당 프로그램을 대상으로 node를 실행하는 전송을 사용합니다. 이 방식은 호스트를 공유하는 LocalSandbox에서는 작동하지만, 자체 마이크로 VM에서 실행되어 호스트 경로가 존재하지 않는 원격 Sandbox(예: E2B)에서는 작동하지 않습니다. 원격 Sandbox에는 프로그램을 Sandbox 파일 시스템에 작성하는 전송이 필요합니다. E2B의 경우 포함된 E2BCodeModeTransportcreateCodeMode의 두 번째 인수로 전달합니다.

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-vmIsolatedVmCodeModeTransport를 사용하세요. 프로그램이 프로세스 내 V8 격리 환경에서 실행되므로 Sandbox가 필요하지 않습니다. 격리 환경에서는 파일 시스템, 네트워크, 프로세스에 접근할 수 없으며, 호스트의 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 참조를 확인하세요.