인터프리터
인터프리터 (Interpreters)
Deep Agents 내부에서 가벼운 코드를 실행하여 도구를 구성하고, 서브에이전트를 조율하며, 구조화된 데이터를 변환합니다.
인터프리터는 에이전트에게 에이전트 루프 내부의 프로그래밍 가능한 인메모리 작업공간을 제공합니다. 에이전트가 작업을 완료하기 위해 코드를 작성하고, 런타임이 이를 실행해 관련 결과만 반환합니다. 중간 결과는 모델 컨텍스트의 일부가 되지 않습니다.
샌드박스가 환경(예: 명령 실행, 의존성 설치, 파일 편집)에 작용하는 코드 우선 방식이라면, 인터프리터는 도구 구성, 상태 유지, 모델로 돌아갈 정보 결정을 위한 코드 우선 방식입니다.
인터프리터를 왜 쓸까요?
대부분의 에이전트 작업은 모델 추론과 도구 호출을 번갈아 수행합니다. 모델은 한 턴에 여러 도구 호출을 할 수 있지만, 그 배치는 생성되는 순간 고정됩니다. 또 다른 모델 턴 없이는 루프, 결과에 대한 분기, 실패 재시도, 한 호출의 출력을 다음 호출로 전달하는 일을 할 수 없으며, 모든 결과는 모델 컨텍스트로 돌아갑니다. 또한 모델이 발행할 호출 수를 결정하므로, 수백 개 항목에 걸쳐 작업을 분배하도록 요청하는 것은 신뢰할 수 없고 모든 항목이 아닌 일부만 처리하는 경향이 있습니다.
인터프리터는 그러한 오케스트레이션을 코드로 옮겨 모델이 무엇을 할지 추론하게 하고, 모든 중간 단계를 추론하지 않게 합니다.
패턴 선택
에이전트 루프 내부의 코드에는 인터프리터를 사용하세요: 도구 구성, 상태 유지, 모델로 돌아갈 내용 제어.
환경에 대한 코드에는 샌드박스를 사용하세요: 셸 명령, 패키지 설치, 테스트, 파일시스템 편집, OS 수준 실행.
| 필요 | 사용 |
|---|---|
| 단순한 외부 호출 하나 또는 둘 | 일반적인 도구 호출 |
| 순수 인메모리 JavaScript: 루프, 분기, 재시도 또는 데이터 변환 (외부 도구 없음) | 인터프리터 |
| 코드에서 오케스트레이션하는 많은 외부 도구 호출 (PTC 필요) | 프로그래매틱 도구 호출(PTC)이 있는 인터프리터 |
| 많은 독립 작업 단위, 여러 관점, 대규모 입력에 대한 재귀 분석 | 동적 서브에이전트가 있는 인터프리터 |
| 셸 명령, 패키지 설치, 테스트 또는 전체 OS 파일시스템 접근 | 샌드박스 |
빠른 시작
QuickJS 미들웨어 패키지를 설치한 다음, createDeepAgent의 middleware 인자를 사용해 인터프리터 미들웨어를 전달하세요.
npm install deepagents @langchain/quickjs
pnpm add deepagents @langchain/quickjs
yarn add deepagents @langchain/quickjs
import { createDeepAgent } from "deepagents";
import { createCodeInterpreterMiddleware } from "@langchain/quickjs";
const agent = createDeepAgent({
model: "google-genai:gemini-3.6-flash",
middleware: [createCodeInterpreterMiddleware()],
});
(다른 모델 예시 생략 - 각 제공자별로 동일한 구조)
인터프리터 작동 방식
미들웨어는 에이전트에 eval 도구를 추가합니다. 유용할 때 에이전트가 JavaScript를 작성하고 eval을 호출합니다; 인터프리터를 직접 호출하지 않습니다. 이 도구는 유지(persistence) mode에 따라 eval 호출 간 변수가 유지될 수 있는 QuickJS 컨텍스트에서 코드를 실행합니다. console.log, console.warn, console.error를 캡처하고 마지막 표현식의 결과를 반환합니다.
에이전트는 다음과 같은 코드를 작성할 수 있습니다:
const rows = [
{ team: "alpha", score: 8 },
{ team: "beta", score: 13 },
{ team: "alpha", score: 21 },
];
const totals = rows.reduce((acc, row) => {
acc[row.team] = (acc[row.team] ?? 0) + row.score;
console.log(`${row.team} score: ${acc[row.team]}`);
return acc;
}, {});
totals;
코드는 가벼운 JavaScript 런타임인 QuickJS를 대상으로 실행됩니다. 기본적으로 인터프리터 코드는 호스트 파일시스템, 네트워크, 셸, 패키지 매니저, 시계에 접근할 수 없습니다. 계산하고, 상태를 보유하고, console.log, console.warn, console.error에 쓸 수 있으며 그 외에는 아무것도 할 수 없습니다.
두 가지 명시적 브리지가 그 범위를 확장합니다:
- 도구 — 프로그래매틱 도구 호출(PTC)을 통해.
tools네임스페이스 아래에 async 함수로 도구의 허용 목록을 제공합니다. 이들은 에이전트 자체의 도구이거나 직접 정의해 전달하는 독립 도구일 수 있습니다. - 서브에이전트 — 동적 서브에이전트를 통해. 에이전트에 서브에이전트가 구성되어 있으면, 인터프리터는 코드에서 이를 파견하기 위한
task()전역을 노출합니다.
프로그래매틱 도구 호출은 활성화하기 전까지 꺼져 있습니다. 에이전트에 서브에이전트가 있을 때 task()를 통한 서브에이전트 파견은 기본적으로 켜져 있고, 끌 수 있습니다. 그 외에는 QuickJS 경계를 넘는 것이 없습니다.
프로그래매틱 도구 호출 (PTC)
프로그래매틱 도구 호출(PTC)은 선택한 에이전트 도구를 tools 전역 네임스페이스 아래 인터프리터 내부에 노출합니다. 모델이 도구 호출을 하나 발행하고, 결과를 기다리고, 다음 호출을 결정하도록 요청하는 대신, 에이전트는 루프, 분기, 재시도, 병렬 배치로 도구를 호출하는 코드를 작성할 수 있습니다.
이것은 중간 결과가 다음 단계의 입력일 뿐일 때 유용합니다: 인터프리터가 모델로 돌아가기 전에 이를 필터링하거나 집계하여 다단계 워크플로를 토큰 효율적으로 유지합니다. 제공자 특화 도구 호출 API가 아닌 미들웨어로 구현되므로 모델에 구애받지 않습니다.
미들웨어는 허용 목록에 있는 각 도구를 tools 아래의 async 함수로 노출합니다. 에이전트는 await로 호출하고 코드에서 결과를 처리하며, 모델은 모든 중간 값을 보지 않고 최종 인터프리터 출력만 봅니다. 도구 이름은 camelCase로 변환되지만 입력 객체는 여전히 도구의 스키마를 따릅니다. 그래서 web_search라는 도구는 tools.webSearch(...)가 됩니다:
const result: string = await tools.webSearch({
query: "deepagents interpreters",
});
PTC 활성화
명시적 허용 목록으로 PTC를 활성화하세요:
import { createDeepAgent } from "deepagents";
import { createCodeInterpreterMiddleware } from "@langchain/quickjs";
const agent = createDeepAgent({
model: "google-genai:gemini-3.6-flash",
middleware: [createCodeInterpreterMiddleware({ ptc: ["web_search"] })],
});
(여러 제공자 예시 생략 - 동일한 ptc 옵션)
PTC가 활성화되면 에이전트는 인터프리터 코드에서 허용 목록 도구를 호출할 수 있습니다. 이 예시는 여러 주제를 병렬로 검색하고 모델로 돌아가기 전에 결과를 결합합니다:
const topics = ["retrieval", "memory", "evaluation"];
const results = await Promise.all(
topics.map((topic) =>
tools.webSearch({ query: `${topic} best practices 2025` }),
),
);
results.join("\n\n");
동적 서브에이전트
아래 개요는 동적 서브에이전트를 언제 사용할지와 최소 task() 패턴을 다룹니다. 구성, 오케스트레이션 예시, 워크플로 트리거, 안전 참고 사항은 동적 서브에이전트를 참고하세요.
동적 서브에이전트는 내장 task() 전역을 사용해 인터프리터가 구성된 서브에이전트를 코드에서 파견할 수 있게 합니다. 디렉터리의 모든 파일 검토, 티켓 배치 트리아지처럼 많은 독립 단위를 아우르는 작업은 작업을 fan-out 하고 결과를 종합하는 루프가 됩니다.
동적 서브에이전트를 사용할 때:
- Fan-out 및 종합: 동일한 종류의 작업을 많은 항목에 걸쳐 병렬로 실행한 다음 결과를 결합합니다.
- 검증: 발견 사항을 독립적인 검증기 서브에이전트에 보내 확인된 결과만 유지합니다.
- 재귀 워크플로: 인터프리터 변수에 작업 세트를 유지하고, 슬라이스를 선택하고, 서브에이전트를 호출하고, 결과를 다듬습니다.
const paths = ["src/auth.ts", "src/routes/api.ts"];
const reviews = await Promise.all(
paths.map((path) =>
task({
description: `Review ${path} for authentication issues`,
subagentType: "reviewer",
}),
),
);
reviews.join("\n\n");
보안
인터프리터는 QuickJS를 사용해 신뢰할 수 없는 JavaScript를 엄격한 기본 격리 상태로 실행합니다. 이를 범위가 제한된 인터프리터 런타임으로 취급하세요. 완전한 프로덕션 샌드박스 백엔드가 아닙니다.
PTC를 통해 노출하는 모든 도구는 인터프리터 코드가 사용할 수 있는 외부 능력입니다. PTC 허용 목록을 권한 경계로 취급하세요: 에이전트가 필요한 도구만 노출하고, 민감한 시스템에 접근하거나 비용을 지출하거나 데이터를 변경하거나 제한 없는 네트워크를 호출할 수 있는 광범위한 도구는 그 동작이 의도적이지 않다면 브리지하지 마세요.
| 능력 | 기본적으로 사용 가능 | 노출 방법 |
|---|---|---|
| JavaScript 실행 | 예 | 인터프리터 미들웨어 추가 |
최상위 await |
예 | 인터프리터 코드에서 프로미스 사용 |
console.log, warn, error 캡처 |
예 | captureConsole: false로 비활성화 |
| 에이전트 도구 | 아니요 | PTC 허용 목록 추가 |
| 파일시스템 접근 | 아니요 | PTC 허용 목록을 통해 내장 파일시스템 도구 추가 |
| 네트워크 접근 | 아니요 | PTC를 통해 특정 네트워크 도구 노출 |
| 시계 또는 날짜시간 접근 | 아니요 | 필요 시 명시적 시간 도구 노출 |
| 셸 명령, 패키지 설치, 테스트, OS 수준 실행 | 아니요 | 샌드박스 백엔드 사용 |
인터프리터 코드는 호스트 Node.js 프로세스가 아닌 QuickJS-Emscripten을 통해 WASM 샌드박스 처리된 QuickJS 런타임에서 실행됩니다. 인터프리터를 능력이 범위가 제한된 실행 계층으로 취급하세요: 에이전트가 필요한 도구와 서브에이전트만 브리지하고 PTC 허용 목록을 좁게 유지하세요.
구성
createCodeInterpreterMiddleware는 다음 옵션을 받아들입니다:
| 옵션 | 기본값 | 목적 |
|---|---|---|
memoryLimitBytes |
64 * 1024 * 1024 (64 MB) |
세션당 QuickJS 힙 메모리 상한. |
maxStackSizeBytes |
320 * 1024 |
세션당 QuickJS 스택 크기 상한. |
executionTimeoutMs |
5000 |
각 eval 호출의 밀리초 단위 타임아웃 한도. 음수 값은 타임아웃을 비활성화합니다. |
toolName |
"eval" |
모델에 노출되는 인터프리터 도구 이름. |
captureConsole |
true |
도구 응답에서 console.log, console.warn, console.error를 캡처. false로 설정하면 콘솔 출력을 버립니다. |
maxResultChars |
4000 |
모델로 반환되는 결과, 오류, 콘솔 출력을 최대 문자 수로 자릅니다. |
systemPrompt |
null |
인터프리터 도구의 커스텀 시스템 프롬프트. null이면 내장 프롬프트 사용. |
ptc |
생략 | 인터프리터 내부에서 tools.*로 노출되는 도구 이름 또는 StructuredToolInterface 인스턴스의 허용 목록. 생략 시 비활성화. PTC 활성화 참고. |
maxPtcCalls |
256 |
eval당 허용되는 최대 tools.* 호출 수. 신뢰하는 환경에서만 null로 설정. PTC 및 보안 참고. |
subagents |
true |
에이전트에 서브에이전트가 있을 때 내장 task() 전역을 노출. false로 설정하면 정상 task 도구를 통한 파견을 요구. 동적 서브에이전트 참고. |
더 알아보기
출처: 문서