모델
모든 에이전트는 궁극적으로 LLM을 호출합니다. SDK는 모델을 두 가지 경량 인터페이스로 추상화합니다.
Model– 특정 API에 대해 하나의 요청을 수행하는 방법을 알고 있습니다.ModelProvider– 사람이 읽을 수 있는 모델 이름(예:'gpt‑5.4')을Model인스턴스로 해석합니다.
일상적인 작업에서는 일반적으로 모델 이름과 가끔 ModelSettings만 다룹니다.
import { Agent } from '@openai/agents';
const agent = new Agent({ name: 'Creative writer', model: 'gpt-5.4',});모델 선택
섹션 제목: “모델 선택”기본 모델
섹션 제목: “기본 모델”Agent를 초기화할 때 모델을 지정하지 않으면 기본 모델이 사용됩니다. 현재 기본값은 품질과 지연 시간의 균형을 위해 gpt-5.4-mini에 reasoning.effort: "none" 및 text.verbosity: "low"를 적용한 구성입니다.
gpt-5.5 같은 다른 모델로 전환하려면 에이전트를 구성하는 방법이 두 가지 있습니다.
첫째, 커스텀 모델을 설정하지 않은 모든 에이전트에 특정 모델을 일관되게 사용하려면 에이전트를 실행하기 전에 OPENAI_DEFAULT_MODEL 환경 변수를 설정합니다.
export OPENAI_DEFAULT_MODEL=gpt-5.5node my-awesome-agent.js둘째, Runner 인스턴스에 기본 모델을 설정할 수 있습니다. 에이전트에 모델을 설정하지 않으면 이 Runner의 기본 모델이 사용됩니다.
import { Runner } from '@openai/agents';
const runner = new Runner({ model: 'gpt‑4.1-mini' });GPT-5.x 모델
섹션 제목: “GPT-5.x 모델”이 방식으로 gpt-5.4 같은 GPT-5.x 모델을 사용하면 SDK가 기본 modelSettings를 적용합니다. 대부분의 사용 사례에 가장 적합한 설정을 적용합니다. 기본 모델의 추론 강도를 조정하려면 직접 modelSettings를 전달합니다.
import { Agent } from '@openai/agents';
const myAgent = new Agent({ name: 'My Agent', instructions: "You're a helpful agent.", // If OPENAI_DEFAULT_MODEL=gpt-5.4 is set, passing only modelSettings works. // It's also fine to pass a GPT-5.x model name explicitly: model: 'gpt-5.4', modelSettings: { reasoning: { effort: 'high' }, text: { verbosity: 'low' }, },});지연 시간이 중요하다면 기본 gpt-5.4-mini 구성으로 시작하거나 다른 GPT-5.x 모델에서 reasoning.effort: "none"을 사용한 다음, 작업에 더 신중한 추론이 필요한 경우에만 추론 강도를 높이세요.
비 GPT-5 모델
섹션 제목: “비 GPT-5 모델”커스텀 modelSettings 없이 비 GPT-5 모델 이름을 전달하면 SDK는 모든 모델과 호환되는 일반 modelSettings로 되돌아갑니다.
OpenAI 프로바이더 구성
섹션 제목: “OpenAI 프로바이더 구성”OpenAI 프로바이더
섹션 제목: “OpenAI 프로바이더”기본 ModelProvider는 OpenAI API를 사용해 이름을 해석합니다. 서로 다른 두 엔드포인트를 지원합니다.
| API | 사용 용도 | setOpenAIAPI() 호출 |
|---|---|---|
| Chat Completions | 표준 채팅 및 함수 호출 | setOpenAIAPI('chat_completions') |
| Responses | 새로운 스트리밍 우선 생성 API(도구 호출, 유연한 출력) | setOpenAIAPI('responses') (기본값) |
import { setDefaultOpenAIKey } from '@openai/agents';
setDefaultOpenAIKey(process.env.OPENAI_API_KEY!); // sk-...커스텀 네트워킹 설정이 필요하다면 setDefaultOpenAIClient(client)를 통해 직접 만든 OpenAI 클라이언트를 연결할 수도 있습니다.
Responses WebSocket 전송 방식
섹션 제목: “Responses WebSocket 전송 방식”Responses API와 함께 OpenAI 프로바이더를 사용하면 기본 HTTP 전송 방식 대신 WebSocket 전송 방식으로 요청을 보낼 수 있습니다.
전역으로 활성화하려면 setOpenAIResponsesTransport('websocket')을 사용하고, 프로바이더별로 활성화하려면 new OpenAIProvider({ useResponses: true, useResponsesWebSocket: true })를 사용합니다.
WebSocket 전송 방식만 사용하려는 경우에는 withResponsesWebSocketSession(...) 또는 커스텀 OpenAIProvider가 필요하지 않습니다. 각 실행/요청마다 재연결해도 괜찮다면 setOpenAIResponsesTransport('websocket')을 활성화한 후에도 기존 run() / Runner.run() 사용 방식은 계속 동작합니다.
전송 방식 선택은 모델 해석을 따릅니다.
setOpenAIResponsesTransport('websocket')은 Responses API를 사용하는 동안 나중에 OpenAI 프로바이더를 통해 해석되는 문자열 모델 이름에만 영향을 줍니다.- 구체적인
Model인스턴스를Agent또는Runner에 전달하면 해당 인스턴스가 그대로 사용됩니다.OpenAIResponsesWSModel은 WebSocket에 남고,OpenAIResponsesModel은 HTTP에 남으며,OpenAIChatCompletionsModel은 Chat Completions에 남습니다. - 자체
modelProvider를 제공하는 경우 해당 프로바이더가 모델 해석을 제어합니다. 전역 setter에 의존하지 말고 해당 프로바이더에서 WebSocket을 활성화하세요. - 프록시, 게이트웨이 또는 기타 OpenAI 호환 엔드포인트를 통해 라우팅하는 경우 대상이 WebSocket
/responses엔드포인트를 지원해야 합니다.websocketBaseURL을 명시적으로 설정해야 할 수도 있습니다.
연결 재사용을 최적화하고 websocket 프로바이더 수명 주기를 더 명시적으로 관리하려는 경우에만 withResponsesWebSocketSession(...) 또는 커스텀 OpenAIProvider / Runner를 사용하세요.
withResponsesWebSocketSession(...): 콜백 이후 자동 정리를 제공하는 편리한 범위 지정 수명 주기- 커스텀
OpenAIProvider/Runner: 자체 앱 아키텍처에서 명시적인 수명 주기 제어(종료 정리 포함)
이름과 달리 withResponsesWebSocketSession(...)은 전송 방식 수명 주기 헬퍼이며, 세션에 설명된 메모리 Session 인터페이스와는 관련이 없습니다.
websocket 프록시 또는 게이트웨이를 사용하는 경우 OpenAIProvider에서 websocketBaseURL을 구성하거나 OPENAI_WEBSOCKET_BASE_URL을 설정하세요.
OpenAIProvider를 직접 인스턴스화하는 경우 websocket 기반 Responses 모델 래퍼는 연결 재사용을 위해 기본적으로 캐시된다는 점을 기억하세요. 종료 시 캐시된 연결을 해제하려면 await provider.close()를 호출하세요. withResponsesWebSocketSession(...)은 주로 이 수명 주기를 대신 관리하기 위해 존재합니다. websocket이 활성화된 프로바이더와 runner를 만들고, 이를 콜백에 전달하며, 이후 항상 프로바이더를 닫습니다. 임시 프로바이더에는 providerOptions를 사용하고, 콜백 범위 runner 기본값에는 runnerConfig를 사용하세요.
Responses WebSocket 전송 방식을 사용하는 전체 스트리밍 + HITL 예제는 examples/basic/stream-ws.ts를 참고하세요.
Responses 전용 지연 도구 로딩
섹션 제목: “Responses 전용 지연 도구 로딩”deferLoading: true가 설정된 toolSearchTool(), toolNamespace(), 함수 도구 또는 호스티드 MCP 도구에는 OpenAI Responses API가 필요합니다. Chat Completions 프로바이더는 네임스페이스가 지정되었거나 지연된 함수 도구를 거부하며, AI SDK 어댑터는 지연 Responses 도구 로딩 흐름을 지원하지 않습니다. 도구 검색이 필요하다면 Responses 모델을 직접 사용하세요.
도구 검색은 Responses API에서 이를 지원하는 GPT-5.4 및 더 최신 모델 릴리스에서만 지원됩니다.
실행에 지연 도구가 포함된 경우 동일한 에이전트에 toolSearchTool()을 추가하고 modelSettings.toolChoice를 'auto'로 유지하세요. 모델이 해당 정의를 언제 로드할지 결정해야 하므로, SDK는 내장 tool_search 도구나 지연 함수 도구를 이름으로 강제하도록 허용하지 않습니다. 전체 설정은 도구 및 공식 OpenAI 도구 검색 가이드를 참고하세요.
모델 동작과 프롬프트
섹션 제목: “모델 동작과 프롬프트”ModelSettings
섹션 제목: “ModelSettings”ModelSettings는 OpenAI 매개변수를 반영하지만 프로바이더에 종속되지 않습니다.
| Field | Type | Notes |
|---|---|---|
temperature | number | 창의성과 결정성 간의 균형입니다. |
topP | number | 뉴클리어스 샘플링입니다. |
frequencyPenalty | number | 반복 토큰에 페널티를 부여합니다. |
presencePenalty | number | 새 토큰을 유도합니다. |
toolChoice | 'auto' | 'required' | 'none' | string | 도구 사용 강제를 참고하세요. OpenAI Responses에서는 사용 가능한 경우 toolChoice: 'computer'가 GA 내장 컴퓨터 도구를 강제합니다. |
parallelToolCalls | boolean | 지원되는 경우 병렬 함수 호출을 허용합니다. |
truncation | 'auto' | 'disabled' | 토큰 잘림 전략입니다. |
maxTokens | number | 응답의 최대 토큰 수입니다. |
store | boolean | 검색 / RAG 워크플로를 위해 응답을 유지합니다. |
promptCacheRetention | 'in-memory' | '24h' | null | 지원되는 경우 프로바이더 프롬프트 캐시 보존을 제어합니다. |
contextManagement | ModelSettingsContextManagement | 서버 측 압축 같은 프로바이더 컨텍스트 관리를 제어합니다. |
reasoning.effort | 'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | gpt-5.x 모델의 추론 강도입니다. |
reasoning.summary | 'auto' | 'concise' | 'detailed' | 모델이 반환하는 추론 요약의 양을 제어합니다. |
text.verbosity | 'low' | 'medium' | 'high' | gpt-5.x 등의 텍스트 상세도입니다. |
providerData | Record<string, any> | 기반 모델로 전달되는 프로바이더별 패스스루 옵션입니다. |
retry | ModelRetrySettings | 런타임 전용 옵트인 재시도 구성입니다. 모델 재시도를 참고하세요. |
설정은 두 수준 중 어디에든 적용할 수 있습니다.
import { Runner, Agent } from '@openai/agents';
const agent = new Agent({ name: 'Creative writer', // ... modelSettings: { temperature: 0.7, toolChoice: 'auto' },});
// or globallynew Runner({ modelSettings: { temperature: 0.3 } });Runner 수준 설정은 충돌하는 에이전트별 설정을 재정의합니다. retry는 중요한 예외입니다. 상속된 값을 undefined로 명시적으로 지우지 않는 한, 중첩 필드가 runner와 에이전트 설정 간에 병합됩니다.
모델 재시도
섹션 제목: “모델 재시도”재시도는 런타임 전용이며 옵트인 방식입니다. modelSettings.retry를 구성하고 정책이 재시도 결정을 반환하지 않는 한 SDK는 모델 요청을 재시도하지 않습니다.
import { Agent, Runner, retryPolicies } from '@openai/agents';
const sharedRetry = { maxRetries: 4, backoff: { initialDelayMs: 500, maxDelayMs: 5_000, multiplier: 2, jitter: true, }, policy: retryPolicies.any( retryPolicies.providerSuggested(), retryPolicies.retryAfter(), retryPolicies.networkError(), retryPolicies.httpStatus([408, 409, 429, 500, 502, 503, 504]), ),};
const runner = new Runner({ modelSettings: { retry: sharedRetry, },});
const agent = new Agent({ name: 'Assistant', instructions: 'You are a concise assistant.', modelSettings: { retry: { maxRetries: 2, backoff: { maxDelayMs: 2_000, }, }, },});
await runner.run(agent, 'Summarize exponential backoff in plain English.');ModelRetrySettings에는 세 가지 필드가 있습니다.
| Field | Type | Notes |
|---|---|---|
maxRetries | number | 최초 요청 이후 허용되는 재시도 횟수입니다. |
backoff | { initialDelayMs?, maxDelayMs?, multiplier?, jitter? } | 정책이 delayMs를 반환하지 않고 재시도할 때의 기본 지연 전략입니다. backoff.maxDelayMs는 계산된 이 backoff 지연에만 상한을 적용하며, 정책이 반환한 명시적 delayMs 값이나 retry-after 힌트에는 상한을 적용하지 않습니다. |
policy | RetryPolicy | 재시도 여부를 결정하는 콜백입니다. 이 함수는 런타임 전용이며 영구 저장된 실행 상태로 직렬화되지 않습니다. |
재시도 정책은 다음을 포함하는 RetryPolicyContext를 받습니다.
attempt와maxRetries: 시도 횟수를 고려한 결정을 내릴 수 있습니다.stream: 스트리밍 및 비스트리밍 동작을 분기할 수 있습니다.error: 원문 검사를 위한 값입니다.normalized:statusCode,retryAfterMs,errorCode,isNetworkError,isAbort같은 정규화된 정보입니다.providerAdvice: 기반 모델/프로바이더가 재시도 지침을 제공할 수 있는 경우의 값입니다.
정책은 다음 중 하나를 반환할 수 있습니다.
- 간단한 재시도 결정을 위한
true/false - 지연을 재정의하거나 로깅을 위한 진단 이유를 첨부하려는 경우
{ retry, delayMs?, reason? }
SDK는 retryPolicies에서 즉시 사용할 수 있는 헬퍼를 내보냅니다.
| Helper | Behavior |
|---|---|
retryPolicies.never() | 항상 옵트아웃합니다. |
retryPolicies.providerSuggested() | 가능한 경우 프로바이더의 재시도 권고를 따릅니다. |
retryPolicies.networkError() | 일시적인 전송/연결 실패에 매칭됩니다. |
retryPolicies.httpStatus([..]) | 선택한 HTTP 상태 코드에 매칭됩니다. |
retryPolicies.retryAfter() | retry-after 힌트가 있는 경우에만 재시도하며, 해당 힌트를 backoff.maxDelayMs의 상한을 받지 않는 명시적 지연으로 사용합니다. |
retryPolicies.any(...) | 중첩 정책 중 하나라도 옵트인하면 재시도합니다. |
retryPolicies.all(...) | 모든 중첩 정책이 옵트인하는 경우에만 재시도합니다. |
정책을 조합할 때는 providerSuggested()가 가장 안전한 첫 구성 요소입니다. 프로바이더가 구분할 수 있는 경우 프로바이더의 거부와 재실행 안전 승인 모두를 보존하기 때문입니다.
안전 경계
섹션 제목: “안전 경계”일부 실패는 절대 자동으로 재시도되지 않습니다.
- 중단 오류
- 어떤 가시적 이벤트나 원문 모델 이벤트가 이미 방출된 후의 스트리밍 실행
- 재실행이 안전하지 않다고 표시하는 프로바이더 권고
previousResponseId 또는 conversationId를 사용하는 상태 유지 후속 요청도 더 보수적으로 처리됩니다. 이러한 요청의 경우 networkError() 또는 httpStatus([500]) 같은 비프로바이더 조건자만으로는 충분하지 않습니다. 재시도 정책에는 일반적으로 retryPolicies.providerSuggested()를 통한 프로바이더의 재실행 안전 승인이 포함되어야 합니다.
Runner와 에이전트 병합 동작
섹션 제목: “Runner와 에이전트 병합 동작”retry는 runner 수준 및 에이전트 수준 modelSettings 간에 깊게 병합됩니다.
- 에이전트는
retry.maxRetries만 재정의하고 runner의policy를 계속 상속할 수 있습니다. - 에이전트는
retry.backoff의 일부만 재정의하고 runner의 형제 backoff 필드를 유지할 수 있습니다. - 상속된
policy또는backoff를 제거해야 하는 경우 해당 필드를 명시적으로undefined로 설정하세요.
로깅을 포함한 더 완전한 예제는 examples/basic/retry.ts 및 examples/ai-sdk/retry.ts를 참고하세요.
프롬프트
섹션 제목: “프롬프트”에이전트는 prompt 매개변수로 구성할 수 있으며, 이는 에이전트의 동작을 제어하는 데 사용해야 하는 서버 저장 프롬프트 구성을 나타냅니다. 현재 이 옵션은 OpenAI Responses API를 사용할 때만 지원됩니다.
prompt는 정적 객체이거나 런타임에 객체를 반환하는 함수일 수 있습니다. 콜백 형태는 동적 프롬프트를 참고하세요.
| Field | Type | Notes |
|---|---|---|
promptId | string | 프롬프트의 고유 식별자입니다. |
version | string | 사용하려는 프롬프트 버전입니다. |
variables | object | 프롬프트에 대체할 변수의 키/값 쌍입니다. 값은 문자열이거나 텍스트, 이미지, 파일 같은 콘텐츠 입력 타입일 수 있습니다. |
import { parseArgs } from 'node:util';import { Agent, run } from '@openai/agents';
/*NOTE: This example will not work out of the box, because the default prompt ID will notbe available in your project.
To use it, please:1. Go to https://platform.openai.com/chat/edit2. Create a new prompt variable, `poem_style`.3. Create a system prompt with the content: Write a poem in {{poem_style}}4. Run the example with the `--prompt-id` flag.*/
const DEFAULT_PROMPT_ID = 'pmpt_6965a984c7ac8194a8f4e79b00f838840118c1e58beb3332';const POEM_STYLES = ['limerick', 'haiku', 'ballad'];
function pickPoemStyle(): string { return POEM_STYLES[Math.floor(Math.random() * POEM_STYLES.length)];}
async function runDynamic(promptId: string) { const poemStyle = pickPoemStyle(); console.log(`[debug] Dynamic poem_style: ${poemStyle}`);
const agent = new Agent({ name: 'Assistant', prompt: { promptId, version: '1', variables: { poem_style: poemStyle }, }, });
const result = await run(agent, 'Tell me about recursion in programming.'); console.log(result.finalOutput);}
async function runStatic(promptId: string) { const agent = new Agent({ name: 'Assistant', prompt: { promptId, version: '1', variables: { poem_style: 'limerick' }, }, });
const result = await run(agent, 'Tell me about recursion in programming.'); console.log(result.finalOutput);}
async function main() { const args = parseArgs({ options: { dynamic: { type: 'boolean', default: false }, 'prompt-id': { type: 'string', default: DEFAULT_PROMPT_ID }, }, });
const promptId = args.values['prompt-id']; if (!promptId) { console.error('Please provide a prompt ID via --prompt-id.'); process.exit(1); }
if (args.values.dynamic) { await runDynamic(promptId); } else { await runStatic(promptId); }}
main().catch((error) => { console.error(error); process.exit(1);});tools나 instructions 같은 추가 에이전트 구성은 저장된 프롬프트에 구성했을 수 있는 값을 재정의합니다.
저장된 프롬프트가 이미 모델을 정의하는 경우, 명시적으로 재정의하지 않는 한 SDK는 에이전트의 기본 모델을 보내지 않습니다. 이는 computerTool()에 중요합니다. 호환성을 위해 프롬프트 관리 실행은 기본적으로 레거시 프리뷰 wire 형식을 유지합니다. 프롬프트 관리 실행에서 GA Responses 컴퓨터 도구를 사용하도록 옵트인하려면 modelSettings.toolChoice: 'computer'를 명시적으로 설정하거나 gpt-5.4 같은 명시적 모델을 보내세요. 관련 컴퓨터 사용 세부 사항은 도구를 참고하세요.
고급 프로바이더와 관측성
섹션 제목: “고급 프로바이더와 관측성”커스텀 모델 프로바이더
섹션 제목: “커스텀 모델 프로바이더”자체 프로바이더 구현은 간단합니다. ModelProvider와 Model을 구현하고 해당 프로바이더를 Runner 생성자에 전달하면 됩니다.
import { ModelProvider, Model, ModelRequest, ModelResponse, ResponseStreamEvent,} from '@openai/agents-core';
import { Agent, Runner } from '@openai/agents';
class EchoModel implements Model { name: string; constructor() { this.name = 'Echo'; } async getResponse(request: ModelRequest): Promise<ModelResponse> { return { usage: {}, output: [{ role: 'assistant', content: request.input as string }], } as any; } async *getStreamedResponse( _request: ModelRequest, ): AsyncIterable<ResponseStreamEvent> { yield { type: 'response.completed', response: { output: [], usage: {} }, } as any; }}
class EchoProvider implements ModelProvider { getModel(_modelName?: string): Promise<Model> | Model { return new EchoModel(); }}
const runner = new Runner({ modelProvider: new EchoProvider() });console.log(runner.config.modelProvider.getModel());const agent = new Agent({ name: 'Test Agent', instructions: 'You are a helpful assistant.', model: new EchoModel(), modelSettings: { temperature: 0.7, toolChoice: 'auto' },});console.log(agent.model);모든 run() 호출과 새로 생성되는 모든 Runner가 기본적으로 동일한 프로바이더를 사용하도록 하려면 앱 시작 시 한 번 설정하세요.
import { setDefaultModelProvider } from '@openai/agents';
setDefaultModelProvider({ async getModel() { // Return any Model implementation here. throw new Error('Provide your own model implementation.'); },});앱이 비 OpenAI 프로바이더를 표준으로 사용하며 커스텀 Runner를 곳곳에 전달하고 싶지 않을 때 유용합니다.
AI SDK 연동
섹션 제목: “AI SDK 연동”ModelProvider를 직접 구현하지 않고 비 OpenAI 모델을 사용하려면 AI SDK 연동을 참고하세요. 해당 어댑터를 사용하면 AI SDK 모델을 Agents 런타임에 직접 연결할 수 있으며, 앱이 이미 AI SDK 프로바이더를 표준으로 사용하거나 더 넓은 프로바이더 생태계에 접근하려는 경우 유용합니다. 또한 Agents SDK providerData가 AI SDK providerMetadata에 어떻게 매핑되는지와 AI SDK UI 라우트에서 사용할 수 있는 스트림 헬퍼도 문서화합니다.
트레이싱 자격 증명
섹션 제목: “트레이싱 자격 증명”지원되는 서버 런타임에서는 트레이싱이 이미 기본적으로 활성화되어 있습니다. 트레이스 내보내기가 기본 OpenAI API 키와 다른 자격 증명을 사용해야 하는 경우에만 setTracingExportApiKey()를 사용하세요.
import { setTracingExportApiKey } from '@openai/agents';
setTracingExportApiKey('sk-...');이는 해당 자격 증명을 사용해 트레이스를 OpenAI 대시보드로 보냅니다. 커스텀 수집 엔드포인트나 재시도 튜닝 같은 exporter 커스터마이즈는 트레이싱을 참고하세요.