도구
도구는 에이전트가 행동을 수행하도록 합니다. 데이터를 가져오고, 외부 API 를 호출하고, 코드를 실행하거나, 심지어 컴퓨터를 사용할 수 있습니다. JavaScript/TypeScript SDK 는 여섯 가지 카테고리를 지원합니다:
- Hosted OpenAI tools – OpenAI 서버에서 모델과 함께 실행됩니다. (웹 검색, 파일 검색, 코드 인터프리터, 이미지 생성)
- 로컬 내장 도구 – 사용자의 환경에서 실행됩니다. (컴퓨터 사용, shell, apply_patch)
- Function tools – 임의의 로컬 함수를 JSON 스키마로 감싸 LLM 이 호출할 수 있게 합니다.
- Agents as tools – 전체 에이전트를 호출 가능한 도구로 노출합니다.
- MCP 서버 – Model Context Protocol 서버(로컬 또는 원격)를 연결합니다.
- 실험적: Codex 도구 – Codex SDK 를 함수 도구로 감싸 작업공간 인지 작업을 실행합니다.
1. 호스티드 툴 (OpenAI Responses API)
섹션 제목: “1. 호스티드 툴 (OpenAI Responses API)”OpenAIResponsesModel을 사용할 때 다음 내장 도구를 추가할 수 있습니다:
| 도구 | 타입 문자열 | 목적 |
|---|---|---|
| 웹 검색 | ’web_search’ | 인터넷 검색 |
| 파일 / 검색 검색 | ’file_search’ | OpenAI 에 호스팅된 벡터 스토어 쿼리 |
| 코드 인터프리터 | ’code_interpreter’ | 샌드박스 환경에서 코드 실행 |
| 이미지 생성 | ’image_generation’ | 텍스트 기반 이미지 생성 |
import { Agent, webSearchTool, fileSearchTool } from '@openai/agents';
const agent = new Agent({ name: 'Travel assistant', tools: [webSearchTool(), fileSearchTool('VS_ID')],});정확한 매개변수 집합은 OpenAI Responses API 와 일치합니다. rankingOptions나 의미 기반 필터와 같은 고급 옵션은 공식 문서를 참고하세요.
2. 로컬 내장 도구
섹션 제목: “2. 로컬 내장 도구”로컬 내장 도구는 사용자의 환경에서 실행되며 구현이 필요합니다:
- 컴퓨터 사용 –
Computer인터페이스를 구현하고computerTool()에 전달 - Shell –
Shell인터페이스를 구현하고shellTool()에 전달 - 패치 적용 –
Editor인터페이스를 구현하고applyPatchTool()에 전달
이 도구들은 로컬에서 실행되며 OpenAI 가 호스팅하지 않습니다. 런타임에서 파일, 터미널 또는 GUI 자동화에 직접 접근해야 할 때 사용하세요. 도구 호출은 여전히 OpenAI 모델의 응답에 의해 요청되지만, 실제 실행은 애플리케이션이 로컬에서 수행해야 합니다.
import { Agent, applyPatchTool, computerTool, shellTool, Computer, Editor, Shell,} from '@openai/agents';
const computer: Computer = { environment: 'browser', dimensions: [1024, 768], screenshot: async () => '', click: async () => {}, doubleClick: async () => {}, scroll: async () => {}, type: async () => {}, wait: async () => {}, move: async () => {}, keypress: async () => {}, drag: async () => {},};
const shell: Shell = { run: async () => ({ output: [ { stdout: '', stderr: '', outcome: { type: 'exit', exitCode: 0 }, }, ], }),};
const editor: Editor = { createFile: async () => ({ status: 'completed' }), updateFile: async () => ({ status: 'completed' }), deleteFile: async () => ({ status: 'completed' }),};
const agent = new Agent({ name: 'Local tools agent', tools: [ computerTool({ computer }), shellTool({ shell, needsApproval: true }), applyPatchTool({ editor, needsApproval: true }), ],});
void agent;3. Function tools
섹션 제목: “3. Function tools”tool() 헬퍼를 사용해 어떤 함수든 도구로 바꿀 수 있습니다.
import { tool } from '@openai/agents';import { z } from 'zod';
const getWeatherTool = tool({ name: 'get_weather', description: 'Get the weather for a given city', parameters: z.object({ city: z.string() }), async execute({ city }) { return `The weather in ${city} is sunny.`; },});옵션 참조
섹션 제목: “옵션 참조”| 필드 | 필수 | 설명 |
|---|---|---|
name | 아니오 | 기본값은 함수 이름(예: get_weather) |
description | 예 | LLM 에 표시되는 명확하고 사람이 읽기 쉬운 설명 |
parameters | 예 | Zod 스키마 또는 원문 JSON 스키마 객체. Zod parameters 사용 시 자동으로 strict 모드가 활성화됨 |
strict | 아니오 | true(기본값)일 때, 인자가 검증에 실패하면 SDK 가 모델 오류를 반환. 유사 매칭이 필요하면 false로 설정 |
execute | 예 | (args, context) => string | unknown | Promise<...> – 비즈니스 로직. 문자열이 아닌 출력은 모델을 위해 직렬화됨. 두 번째 인자는 선택적 RunContext |
errorFunction | 아니오 | 내부 오류를 사용자 가시 문자열로 변환하는 커스텀 핸들러 (context, error) => string |
needsApproval | 아니오 | 실행 전에 사람 승인 요구. 휴먼 인 더 루프 (HITL) 가이드를 참고 |
isEnabled | 아니오 | 실행별로 조건부 노출. 불리언 또는 프레디케이트 허용 |
inputGuardrails | 아니오 | 도구 실행 전에 실행되는 가드레일. 거부 또는 throw 가능. 가드레일 참고 |
outputGuardrails | 아니오 | 도구 실행 후 실행되는 가드레일. 거부 또는 throw 가능. 가드레일 참고 |
비엄격 JSON 스키마 도구
섹션 제목: “비엄격 JSON 스키마 도구”유효하지 않거나 일부만 제공된 입력을 모델이 추론하도록 하려면 원문 JSON 스키마 사용 시 strict 모드를 비활성화할 수 있습니다:
import { tool } from '@openai/agents';
interface LooseToolInput { text: string;}
const looseTool = tool({ description: 'Echo input; be forgiving about typos', strict: false, parameters: { type: 'object', properties: { text: { type: 'string' } }, required: ['text'], additionalProperties: true, }, execute: async (input) => { // because strict is false we need to do our own verification if (typeof input !== 'object' || input === null || !('text' in input)) { return 'Invalid input. Please try again'; } return (input as LooseToolInput).text; },});4. Agents as tools
섹션 제목: “4. Agents as tools”대화를 완전히 넘기지 않고 한 에이전트가 다른 에이전트를 보조하도록 하고 싶을 때 agent.asTool()을 사용하세요:
import { Agent } from '@openai/agents';
const summarizer = new Agent({ name: 'Summarizer', instructions: 'Generate a concise summary of the supplied text.',});
const summarizerTool = summarizer.asTool({ toolName: 'summarize_text', toolDescription: 'Generate a concise summary of the supplied text.',});
const mainAgent = new Agent({ name: 'Research assistant', tools: [summarizerTool],});내부적으로 SDK 는 다음을 수행합니다:
- 단일
input매개변수를 갖는 function tool 생성 - 도구가 호출되면 그 입력으로 서브 에이전트 실행
- 마지막 메시지 또는
customOutputExtractor가 추출한 출력 반환
에이전트를 도구로 실행하면, Agents SDK 는 기본 설정으로 러너를 생성하고 함수 실행 내에서 해당 에이전트를 실행합니다. runConfig 또는 runOptions의 속성을 제공하려면 asTool() 메서드에 전달하여 러너 동작을 사용자화할 수 있습니다.
또한 asTool() 옵션을 통해 에이전트 도구에 needsApproval과 isEnabled를 설정하여 휴먼 인 더 루프 흐름 및 조건부 도구 가용성과 통합할 수 있습니다.
agent.asTool()의 고급 구조화 입력 옵션:
inputBuilder: 구조화된 도구 인자를 중첩 에이전트 입력 페이로드로 매핑includeInputSchema: 더 강력한 스키마 인지 동작을 위해 중첩 실행에 입력 JSON 스키마 포함resumeState: 중첩 직렬화RunState를 재개할 때의 컨텍스트 정합 전략 제어
에이전트 도구의 스트리밍 이벤트
섹션 제목: “에이전트 도구의 스트리밍 이벤트”에이전트 도구는 모든 중첩 실행 이벤트를 앱으로 스트리밍할 수 있습니다. 도구를 구성하는 방식에 맞는 훅 스타일을 선택하세요:
import { Agent } from '@openai/agents';
const billingAgent = new Agent({ name: 'Billing Agent', instructions: 'Answer billing questions and compute simple charges.',});
const billingTool = billingAgent.asTool({ toolName: 'billing_agent', toolDescription: 'Handles customer billing questions.', // onStream: simplest catch-all when you define the tool inline. onStream: (event) => { console.log(`[onStream] ${event.event.type}`, event); },});
// on(eventName) lets you subscribe selectively (or use '*' for all).billingTool.on('run_item_stream_event', (event) => { console.log('[on run_item_stream_event]', event);});billingTool.on('raw_model_stream_event', (event) => { console.log('[on raw_model_stream_event]', event);});
const orchestrator = new Agent({ name: 'Support Orchestrator', instructions: 'Delegate billing questions to the billing agent tool.', tools: [billingTool],});- 이벤트 타입은
RunStreamEvent['type']와 동일:raw_model_stream_event,run_item_stream_event,agent_updated_stream_event onStream은 가장 단순한 범용 훅으로, 도구를 인라인으로 선언할 때 잘 작동합니다(tools: [agent.asTool({ onStream })]). 이벤트별 라우팅이 필요 없다면 사용하세요on(eventName, handler)는 선택적으로(또는'*'로) 구독할 수 있어 더 세밀한 처리가 필요하거나 생성 후 리스너를 부착하고자 할 때 적합합니다onStream또는 어떤on(...)핸들러라도 제공하면 agent-as-tool 은 자동으로 스트리밍 모드로 실행됩니다. 그렇지 않으면 비스트리밍 경로를 유지합니다- 핸들러는 병렬로 호출되므로 느린
onStream콜백이on(...)핸들러를 차단하지 않습니다(반대의 경우도 동일) toolCallId는 도구가 모델의 도구 호출을 통해 호출된 경우 제공됩니다. 직접적인invoke()호출이나 프로바이더 특성에 따라 생략될 수 있습니다
5. MCP 서버
섹션 제목: “5. MCP 서버”Model Context Protocol (MCP) 서버를 통해 도구를 노출하고 에이전트에 연결할 수 있습니다.
예를 들어, MCPServerStdio를 사용해 stdio MCP 서버를 실행하고 연결할 수 있습니다:
import { Agent, MCPServerStdio } from '@openai/agents';
const server = new MCPServerStdio({ fullCommand: 'npx -y @modelcontextprotocol/server-filesystem ./sample_files',});
await server.connect();
const agent = new Agent({ name: 'Assistant', mcpServers: [server],});완전한 예시는 filesystem-example.ts를 참고하세요. MCP 서버 도구 통합에 대한 종합 가이드를 찾고 있다면 모델 컨텍스트 프로토콜 (MCP) 가이드를 참고하세요.
여러 서버(또는 부분 실패)를 관리할 때는 connectMcpServers와 모델 컨텍스트 프로토콜 (MCP) 가이드의 라이프사이클 지침을 사용하세요.
6. 실험적: Codex 도구
섹션 제목: “6. 실험적: Codex 도구”@openai/agents-extensions/experimental/codex는 codexTool()을 제공합니다. 이 함수 도구는 모델 도구 호출을 Codex SDK 로 라우팅하여 에이전트가 작업공간 범위의 작업(shell, 파일 편집, MCP 도구)을 자율적으로 실행할 수 있게 합니다. 이 인터페이스는 실험적이며 변경될 수 있습니다.
먼저 의존성을 설치하세요:
npm install @openai/agents-extensions @openai/codex-sdk빠른 시작:
import { Agent } from '@openai/agents';import { codexTool } from '@openai/agents-extensions/experimental/codex';
export const codexAgent = new Agent({ name: 'Codex Agent', instructions: 'Use the codex tool to inspect the workspace and answer the question. When skill names, which usually start with `$`, are mentioned, you must rely on the codex tool to use the skill and answer the question.', tools: [ codexTool({ sandboxMode: 'workspace-write', workingDirectory: '/path/to/repo', defaultThreadOptions: { model: 'gpt-5.2-codex', networkAccessEnabled: true, webSearchEnabled: false, }, }), ],});알아둘 점:
- 인증:
CODEX_API_KEY(권장) 또는OPENAI_API_KEY를 제공하거나codexOptions.apiKey전달 - 입력: 엄격한 스키마 —
inputs에는 최소한 하나의{ type: 'text', text }또는{ type: 'local_image', path }가 포함되어야 함 - 안전:
sandboxMode를workingDirectory와 함께 사용. 디렉터리가 Git 저장소가 아니라면skipGitRepoCheck설정 - 스레딩:
useRunContextThreadId: true는runContext.context에 최신 thread id 를 읽고 저장하며, 앱 상태에서 턴 간 재사용에 유용 - Thread ID 우선순위: 도구 호출의
threadId(스키마에 포함된 경우)가 최우선, 다음은 런 컨텍스트 thread id, 다음은codexTool({ threadId }) - 런 컨텍스트 키: 기본은
name: 'codex'에 대해codexThreadId,name: 'engineer'와 같은 경우codexThreadId_<suffix>(정규화 후codex_engineer) - 변경 가능한 컨텍스트 필요:
useRunContextThreadId가 활성화된 경우run(..., { context })에 변경 가능한 객체 또는Map을 전달 - 네이밍: 도구 이름은
codex네임스페이스로 정규화됨(engineer는codex_engineer가 됨). 에이전트 내 Codex 도구 이름 중복은 거부됨 - 스트리밍:
onStream은 Codex 이벤트(추론, 명령 실행, MCP 도구 호출, 파일 변경, 웹 검색)를 반영하므로 진행 상황을 로깅하거나 트레이싱할 수 있음 - 출력: 도구 결과에는
response,usage,threadId가 포함되며 Codex 토큰 사용량은RunContext에 기록됨 - 구조:
outputSchema는 디스크립터, JSON 스키마 객체 또는 Zod 객체가 될 수 있음. JSON 객체 스키마의 경우additionalProperties는false여야 함
런 컨텍스트 스레드 재사용 예시:
import { Agent, run } from '@openai/agents';import { codexTool } from '@openai/agents-extensions/experimental/codex';
// Derived from codexTool({ name: 'engineer' }) when runContextThreadIdKey is omitted.type ExampleContext = { codexThreadId_engineer?: string;};
const agent = new Agent<ExampleContext>({ name: 'Codex assistant', instructions: 'Use the codex tool for workspace tasks.', tools: [ codexTool({ // `name` is optional for a single Codex tool. // We set it so the run-context key is tool-specific and to avoid collisions when adding more Codex tools. name: 'engineer', // Reuse the same Codex thread across runs that share this context object. useRunContextThreadId: true, sandboxMode: 'workspace-write', workingDirectory: '/path/to/repo', defaultThreadOptions: { model: 'gpt-5.2-codex', approvalPolicy: 'never', }, }), ],});
// The default key for useRunContextThreadId with name=engineer is codexThreadId_engineer.const context: ExampleContext = {};
// First turn creates (or resumes) a Codex thread and stores the thread ID in context.await run(agent, 'Inspect src/tool.ts and summarize it.', { context });// Second turn reuses the same thread because it shares the same context object.await run(agent, 'Now list refactoring opportunities.', { context });
const threadId = context.codexThreadId_engineer;
void threadId;도구 사용 동작
섹션 제목: “도구 사용 동작”모델이 언제, 어떻게 도구를 사용해야 하는지 제어하려면 에이전트 가이드를 참고하세요
(modelSettings.toolChoice, toolUseBehavior 등).
모범 사례
섹션 제목: “모범 사례”- 짧고 명확한 설명 – 도구가 무엇을 하고 언제 사용하는지 설명
- 입력 검증 – 가능하면 Zod 스키마로 엄격한 JSON 검증 사용
- 에러 핸들러에서 부작용 회피 –
errorFunction은 유용한 문자열을 반환해야 하며 throw 하지 않아야 함 - 도구당 하나의 책임 – 작고 조합 가능한 도구가 더 나은 모델 추론으로 이어짐