콘텐츠로 이동

에이전트

에이전트는 OpenAI Agents SDK의 주요 구성 요소입니다. Agent 는 다음과 같이 구성된 Large Language Model (LLM) 입니다:

  • Instructions – 모델에게 정체응답 방식 을 지시하는 시스템 프롬프트
  • Model – 호출할 OpenAI 모델과 선택적 모델 튜닝 매개변수
  • Tools – LLM 이 작업을 수행하기 위해 호출할 수 있는 함수 또는 API 목록
Basic Agent definition
import { Agent } from '@openai/agents';
const agent = new Agent({
name: 'Haiku Agent',
instructions: 'Always respond in haiku form.',
model: 'gpt-5-nano', // optional – falls back to the default model
});

이 페이지의 나머지 부분에서는 모든 Agent 기능을 자세히 살펴봅니다.


Agent 생성자는 단일 구성 객체를 받습니다. 가장 자주 사용하는 속성은 아래와 같습니다.

PropertyRequiredDescription
nameyes사람이 읽을 수 있는 짧은 식별자
instructionsyes시스템 프롬프트(문자열 또는 함수 – Dynamic instructions 참고)
handoffDescriptionno이 에이전트를 핸드오프 도구로 제공할 때 사용하는 짧은 설명
modelno모델 이름 또는 커스텀 Model 구현
modelSettingsno튜닝 매개변수(temperature, top_p 등). 필요한 속성이 최상위에 없으면 providerData 아래에 포함할 수 있습니다
toolsno모델이 호출할 수 있는 Tool 인스턴스 배열
mcpServersno에이전트에 도구를 제공하는 MCP 서버. 모델 컨텍스트 프로토콜 (MCP) 가이드를 참고하세요
resetToolChoiceno도구 호출 후 기본값으로 tool_choice 를 리셋하여 도구 사용 루프를 방지합니다(기본값: true). Forcing tool use 참고
Agent with tools
import { Agent, tool } from '@openai/agents';
import { z } from 'zod';
const getWeather = tool({
name: 'get_weather',
description: 'Return the weather for a given city.',
parameters: z.object({ city: z.string() }),
async execute({ city }) {
return `The weather in ${city} is sunny.`;
},
});
const agent = new Agent({
name: 'Weather bot',
instructions: 'You are a helpful weather bot.',
model: 'gpt-4.1',
tools: [getWeather],
});

에이전트는 컨텍스트 타입에 대해 제네릭 입니다 – 즉 Agent<TContext, TOutput>. 컨텍스트는 개발자가 생성하여 Runner.run() 에 전달하는 의존성 주입 객체입니다. 모든 도구, 가드레일, 핸드오프 등에 전달되며 상태 저장이나 공유 서비스(데이터베이스 연결, user 메타데이터, 기능 플래그 등)를 제공하는 데 유용합니다.

Agent with context
import { Agent } from '@openai/agents';
interface Purchase {
id: string;
uid: string;
deliveryStatus: string;
}
interface UserContext {
uid: string;
isProUser: boolean;
// this function can be used within tools
fetchPurchases(): Promise<Purchase[]>;
}
const agent = new Agent<UserContext>({
name: 'Personal shopper',
instructions: 'Recommend products the user will love.',
});
// Later
import { run } from '@openai/agents';
const result = await run(agent, 'Find me a new pair of running shoes', {
context: { uid: 'abc', isProUser: true, fetchPurchases: async () => [] },
});

기본적으로 에이전트는 일반 텍스트(string)를 반환합니다. 모델이 구조화된 객체를 반환하도록 하려면 outputType 속성을 지정하세요. SDK 는 다음을 허용합니다:

  1. Zod 스키마(z.object({...}))
  2. JSON‑schema 호환 객체
Structured output with Zod
import { Agent } from '@openai/agents';
import { z } from 'zod';
const CalendarEvent = z.object({
name: z.string(),
date: z.string(),
participants: z.array(z.string()),
});
const extractor = new Agent({
name: 'Calendar extractor',
instructions: 'Extract calendar events from the supplied text.',
outputType: CalendarEvent,
});

outputType 이 제공되면 SDK 는 일반 텍스트 대신 자동으로 structured outputs을 사용합니다.


멀티 에이전트 시스템 설계 패턴

섹션 제목: “멀티 에이전트 시스템 설계 패턴”

에이전트를 함께 구성하는 방법은 다양합니다. 프로덕션 앱에서 자주 보는 두 가지 패턴은 다음과 같습니다:

  1. Manager (Agents as tools) – 중앙 에이전트가 대화를 소유하며 도구로 노출된 특화 에이전트를 호출
  2. 핸드오프 – 초기 에이전트가 사용자의 요청을 파악한 후 전체 대화를 전문가에게 위임

이 접근법은 상호 보완적입니다. Manager 는 가드레일이나 레이트 리밋을 한곳에서 강제할 수 있게 해주고, 핸드오프는 각 에이전트가 대화의 제어를 유지하지 않고 단일 작업에 집중할 수 있게 합니다.

이 패턴에서 매니저는 제어를 넘기지 않습니다—LLM 이 도구를 사용하고 매니저가 최종 답을 요약합니다. 자세한 내용은 도구 가이드를 참고하세요.

Agents as tools
import { Agent } from '@openai/agents';
const bookingAgent = new Agent({
name: 'Booking expert',
instructions: 'Answer booking questions and modify reservations.',
});
const refundAgent = new Agent({
name: 'Refund expert',
instructions: 'Help customers process refunds and credits.',
});
const customerFacingAgent = new Agent({
name: 'Customer-facing agent',
instructions:
'Talk to the user directly. When they need booking or refund help, call the matching tool.',
tools: [
bookingAgent.asTool({
toolName: 'booking_expert',
toolDescription: 'Handles booking questions and requests.',
}),
refundAgent.asTool({
toolName: 'refund_expert',
toolDescription: 'Handles refund questions and requests.',
}),
],
});

핸드오프에서는 분류 에이전트가 요청을 라우팅하지만, 핸드오프가 발생하면 전문가 에이전트가 최종 출력을 생성할 때까지 대화를 소유합니다. 이는 프롬프트를 짧게 유지하고 각 에이전트를 독립적으로 사고할 수 있게 해줍니다. 자세한 내용은 핸드오프 가이드를 참고하세요.

Agent with handoffs
import { Agent } from '@openai/agents';
const bookingAgent = new Agent({
name: 'Booking Agent',
instructions: 'Help users with booking requests.',
});
const refundAgent = new Agent({
name: 'Refund Agent',
instructions: 'Process refund requests politely and efficiently.',
});
// Use Agent.create method to ensure the finalOutput type considers handoffs
const triageAgent = Agent.create({
name: 'Triage Agent',
instructions: `Help the user with their questions.
If the user asks about booking, hand off to the booking agent.
If the user asks about refunds, hand off to the refund agent.`.trimStart(),
handoffs: [bookingAgent, refundAgent],
});

instructions 는 문자열 대신 함수 가 될 수 있습니다. 이 함수는 현재 RunContext 와 Agent 인스턴스를 받고, 문자열 또는 Promise<string> 을 반환할 수 있습니다.

Agent with dynamic instructions
import { Agent, RunContext } from '@openai/agents';
interface UserContext {
name: string;
}
function buildInstructions(runContext: RunContext<UserContext>) {
return `The user's name is ${runContext.context.name}. Be extra friendly!`;
}
const agent = new Agent<UserContext>({
name: 'Personalized helper',
instructions: buildInstructions,
});

동기 및 async 함수 모두 지원합니다.


고급 사용 사례에서는 이벤트를 수신하여 Agent 라이프사이클을 관찰할 수 있습니다. 사용 가능한 항목은 여기에 나열된 에이전트 훅 이벤트 이름을 참조하세요.

Agent with lifecycle hooks
import { Agent } from '@openai/agents';
const agent = new Agent({
name: 'Verbose agent',
instructions: 'Explain things thoroughly.',
});
agent.on('agent_start', (ctx, agent) => {
console.log(`[${agent.name}] started`);
});
agent.on('agent_end', (ctx, output) => {
console.log(`[agent] produced:`, output);
});

가드레일을 사용하면 user 입력과 에이전트 출력을 검증하거나 변환할 수 있습니다. inputGuardrailsoutputGuardrails 배열을 통해 구성합니다. 자세한 내용은 가드레일 가이드를 참고하세요.


기존 에이전트의 약간 수정된 버전이 필요하신가요? 완전히 새로운 Agent 인스턴스를 반환하는 clone() 메서드를 사용하세요.

Cloning Agents
import { Agent } from '@openai/agents';
const pirateAgent = new Agent({
name: 'Pirate',
instructions: 'Respond like a pirate – lots of “Arrr!”',
model: 'gpt-5-mini',
});
const robotAgent = pirateAgent.clone({
name: 'Robot',
instructions: 'Respond like a robot – be precise and factual.',
});

도구를 제공해도 LLM 이 반드시 호출하는 것은 아닙니다. modelSettings.tool_choice 로 도구 사용을 강제 할 수 있습니다:

  1. 'auto' (기본값) – LLM 이 도구 사용 여부를 결정
  2. 'required' – LLM 은 반드시 도구를 호출해야 함(어떤 도구인지는 선택 가능)
  3. 'none' – LLM 은 도구를 호출하면 안 됨
  4. 특정 도구 이름, 예: 'calculator' – 해당 도구를 반드시 호출해야 함
Forcing tool use
import { Agent, tool } from '@openai/agents';
import { z } from 'zod';
const calculatorTool = tool({
name: 'Calculator',
description: 'Use this tool to answer questions about math problems.',
parameters: z.object({ question: z.string() }),
execute: async (input) => {
throw new Error('TODO: implement this');
},
});
const agent = new Agent({
name: 'Strict tool user',
instructions: 'Always answer using the calculator tool.',
tools: [calculatorTool],
modelSettings: { toolChoice: 'auto' },
});

도구 호출 후 SDK 는 자동으로 tool_choice'auto' 로 리셋합니다. 이는 모델이 도구를 반복 호출하는 무한 루프에 빠지는 것을 방지합니다. 이 동작은 resetToolChoice 플래그 또는 toolUseBehavior 구성으로 재정의할 수 있습니다:

  • 'run_llm_again' (기본값) – 도구 결과로 LLM 을 다시 실행
  • 'stop_on_first_tool' – 첫 도구 결과를 최종 답으로 처리
  • { stopAtToolNames: ['my_tool'] } – 나열된 도구 중 하나가 호출되면 중지
  • (context, toolResults) => ... – 실행을 종료할지 여부를 반환하는 커스텀 함수
const agent = new Agent({
...,
toolUseBehavior: 'stop_on_first_tool',
});

참고: toolUseBehaviorfunction tools 에만 적용됩니다. Hosted tools 는 항상 처리를 위해 모델로 되돌아갑니다.