콘텐츠로 이동

에이전트 실행

에이전트는 자체적으로 아무 작업도 하지 않습니다. Runner 클래스 또는 run() 유틸리티로 에이전트를 실행해야 합니다.

턴을 실행하거나, 이벤트를 스트리밍하거나, 대화 상태를 관리하려면 에이전트를 읽은 후 이 페이지를 확인하세요. 아직 에이전트를 정의할 방법을 결정하는 중이라면 먼저 에이전트부터 시작하세요.

간단한 실행
import { Agent, run } from '@openai/agents';
const agent = new Agent({
name: 'Assistant',
instructions: 'You are a helpful assistant',
});
const result = await run(
agent,
'Write a haiku about recursion in programming.',
);
console.log(result.finalOutput);
// Code within the code,
// Functions calling themselves,
// Infinite loop's dance.

사용자 지정 러너가 필요하지 않다면 싱글톤 기본 Runner 인스턴스를 실행하는 run() 유틸리티를 사용할 수도 있습니다.

또는 자체 러너 인스턴스를 생성할 수 있습니다.

간단한 실행
import { Agent, Runner } from '@openai/agents';
const agent = new Agent({
name: 'Assistant',
instructions: 'You are a helpful assistant',
});
// You can pass custom configuration to the runner
const runner = new Runner();
const result = await runner.run(
agent,
'Write a haiku about recursion in programming.',
);
console.log(result.finalOutput);
// Code within the code,
// Functions calling themselves,
// Infinite loop's dance.

에이전트를 실행하면 최종 출력과 전체 실행 기록이 포함된 실행 결과 객체를 받습니다.

Runner에서 run 메서드를 사용할 때는 시작 에이전트와 입력을 전달합니다. 입력은 사용자 메시지로 간주되는 문자열이거나 OpenAI Responses API의 항목인 입력 항목 목록일 수 있습니다.

이후 러너는 다음 루프를 실행합니다.

  1. 현재 입력으로 현재 에이전트의 모델을 호출합니다.
  2. LLM 응답을 검사합니다.
    • 최종 출력 → 반환합니다.
    • 핸드오프 → 새 에이전트로 전환하고 누적된 대화 기록을 유지한 다음 1단계로 이동합니다.
    • 도구 호출 → 도구를 실행하고 결과를 대화에 추가한 다음 1단계로 이동합니다.
  3. maxTurnsnull이 아닌 경우 maxTurns에 도달하면 MaxTurnsExceededError를 발생시킵니다.

앱이 시작될 때 Runner를 생성하고 요청 간에 재사용하세요. 인스턴스에는 모델 제공자와 트레이싱 옵션 같은 전역 설정이 저장됩니다. 완전히 다른 설정이 필요한 경우에만 다른 Runner를 생성하세요. 간단한 스크립트에서는 내부적으로 기본 러너를 사용하는 run()을 호출할 수도 있습니다.

run() 메서드에는 실행을 시작할 초기 에이전트, 실행 입력, 옵션 집합을 전달합니다.

입력은 사용자 메시지로 간주되는 문자열, 입력 항목 목록 또는 휴먼 인 더 루프 (HITL) 에이전트를 구축하는 경우 RunState 객체일 수 있습니다.

추가 옵션은 다음과 같습니다.

옵션기본값설명
streamfalsetrue이면 호출이 StreamedRunResult를 반환하고 모델에서 이벤트가 도착하는 대로 내보냅니다.
context모든 도구 / 가드레일 / 핸드오프에 전달되는 컨텍스트 객체입니다. 자세한 내용은 컨텍스트 관리를 참조하세요.
maxTurns10안전 제한입니다. 제한에 도달하면 MaxTurnsExceededError를 발생시킵니다. 제한을 비활성화하려면 null을 전달하세요.
signal취소를 위한 AbortSignal입니다.
session세션 지속성 구현입니다. 세션을 참조하세요.
sessionInputCallback세션 기록과 새 입력을 병합하는 사용자 지정 로직이며 모델 호출 전에 실행됩니다. 세션을 참조하세요.
callModelInputFilter모델 호출 직전에 모델 입력(항목 + 선택적 instructions)을 편집하는 훅입니다. 모델 호출 입력 필터를 참조하세요.
toolErrorFormatter모델에 반환되는 도구 오류 메시지를 사용자 지정하는 훅입니다. 도구 오류 포매터를 참조하세요.
reasoningItemIdPolicy이전 실행 항목이 다시 모델 입력으로 변환될 때 추론 항목의 id를 보존할지 생략할지 제어합니다. 추론 항목 ID 정책을 참조하세요.
tracing실행별 트레이싱 설정 재정의입니다. 기본 작업/턴 스팬 계층 구조를 생략하려면 includeTaskAndTurnSpans: false로 설정하세요.
sandboxSandboxAgent 실행을 위한 샌드박스 클라이언트, 라이브 세션, 세션 상태, 스냅샷, 매니페스트 재정의 또는 동시 실행 제한입니다. 개념을 참조하세요.
toolExecution로컬 도구 호출을 위한 SDK 측 실행 설정입니다. 동시에 실행되는 함수 도구 수를 제한하려면 toolExecution.maxFunctionToolConcurrency를 사용하고, 대기 중인 승인 요청 전에 함수 도구 입력 가드레일을 실행하려면 toolExecution.preApprovalInputGuardrails를 사용하세요.
toolNotFoundBehavior'raise_error'모델이 내보낸 확인되지 않은 함수 도구 호출을 처리하는 방식을 제어합니다. 모델에 표시되는 도구 오류를 반환하고 실행을 계속하려면 'return_error_to_model'을 사용하세요.
errorHandlers지원되는 런타임 오류의 핸들러입니다. 오류 핸들러를 참조하세요.
conversationId서버 측 대화를 재사용합니다(OpenAI Responses API + Conversations API만 해당).
previousResponseId대화를 생성하지 않고 이전 Responses API 호출부터 계속합니다(OpenAI Responses API만 해당).

스트리밍을 사용하면 LLM이 실행되는 동안 스트리밍 이벤트도 받을 수 있습니다. 스트림이 시작되면 StreamedRunResult에 새로 생성된 모든 출력을 포함한 전체 실행 정보가 담깁니다. for await 루프를 사용해 스트리밍 이벤트를 순회할 수 있습니다. 자세한 내용은 스트리밍을 참조하세요.

자체 Runner 인스턴스를 생성하는 경우 RunConfig 객체를 전달하여 러너를 설정할 수 있습니다.

필드타입목적
modelstring | Model실행에 포함된 모든 에이전트에 특정 모델을 강제로 적용합니다.
modelProviderModelProvider모델 이름을 해석하며 기본값은 OpenAI 제공자입니다.
modelSettingsModelSettings에이전트별 설정을 재정의하는 전역 조정 매개변수입니다. 옵트인 재시도 설정을 포함한 자세한 내용은 모델을 참조하세요.
handoffInputFilterHandoffInputFilter핸드오프를 수행할 때 입력 항목을 변경합니다. 단, 핸드오프 자체에 이미 정의된 필터가 없어야 합니다.
inputGuardrailsInputGuardrail[]초기 사용자 입력에 적용되는 가드레일입니다.
outputGuardrailsOutputGuardrail[]최종 출력에 적용되는 가드레일입니다.
tracingDisabledbooleanOpenAI 트레이싱을 완전히 비활성화합니다.
traceIncludeSensitiveDataboolean스팬은 계속 내보내면서 트레이스에서 LLM/도구 입력 및 출력을 제외합니다.
workflowNamestring트레이스 대시보드에 표시되며 관련 실행을 그룹화하는 데 도움이 됩니다.
traceId / groupIdstringSDK가 생성하도록 두는 대신 트레이스 또는 그룹 ID를 수동으로 지정합니다.
traceMetadataRecord<string, string>모든 스팬에 첨부할 임의의 메타데이터입니다.
tracingTracingConfig내보내기 API 키와 includeTaskAndTurnSpans를 포함한 러너 수준의 기본 트레이싱 설정입니다. 개별 실행 옵션으로 이 값을 재정의할 수 있습니다.
sessionInputCallbackSessionInputCallback이 러너의 모든 실행에 적용되는 기본 기록 병합 전략입니다.
callModelInputFilterCallModelInputFilter각 모델 호출 전에 모델 입력을 편집하는 전역 훅입니다.
toolErrorFormatterToolErrorFormatter모델에 반환되는 도구 오류 메시지를 사용자 지정하는 전역 훅입니다.
reasoningItemIdPolicyReasoningItemIdPolicy생성된 항목을 이후 모델 호출의 입력으로 재생할 때 추론 항목의 id를 보존하거나 생략하는 기본 정책입니다.
sandboxSandboxRunConfigSandboxAgent 실행의 기본 샌드박스 런타임 설정입니다.
toolExecutionToolExecutionConfig로컬 도구 호출을 위한 기본 SDK 측 실행 설정입니다. maxFunctionToolConcurrency는 각 턴에서 로컬 함수 도구의 동시 실행 수를 제한합니다. 설정하지 않거나 null이면 한 턴에 내보낸 모든 함수 도구 호출을 시작합니다. preApprovalInputGuardrails는 대기 중인 승인 요청 전에 함수 도구 입력 가드레일을 실행하도록 옵트인합니다.
toolNotFoundBehaviorToolNotFoundBehavior확인되지 않은 함수 도구 호출의 기본 동작입니다. 'raise_error'ModelBehaviorError를 발생시키고, 'return_error_to_model'은 모델에 표시되는 도구 오류를 반환한 후 실행을 계속합니다.

toolExecution.maxFunctionToolConcurrency1 이상의 정수여야 합니다. 이 설정은 로컬 함수 도구의 SDK 측 실행만 제한합니다. 제공자 측 modelSettings.parallelToolCalls는 변경하지 않습니다.

toolExecution.preApprovalInputGuardrails는 기본적으로 비활성화되어 있습니다. true로 설정하면 승인이 필요한 로컬 함수 도구는 SDK가 대기 중인 승인 인터럽션(중단 처리)을 기록하기 전에 입력 가드레일을 실행합니다. 가드레일이 rejectContent를 반환하면 SDK는 승인을 요청하는 대신 해당 거부 메시지를 도구 출력으로 다시 보냅니다. 가드레일이 호출을 허용하면 승인 요청은 계속 발생하며, 승인이 처리된 후 도구를 실행하기 직전에 동일한 입력 가드레일이 다시 실행됩니다.

다음 턴으로 상태를 전달하는 일반적인 방법은 네 가지입니다.

전략상태가 저장되는 위치적합한 용도다음 턴에 전달할 항목
result.history앱 메모리소규모 채팅 루프, 완전한 수동 제어, 모든 제공자result.history
session스토리지 + SDK지속적인 채팅 상태, 재개 가능한 실행, 사용자 지정 스토어동일한 session 인스턴스(또는 스토어 기반 인스턴스)
conversationIdOpenAI Conversations API여러 워커/서비스 간에 공유하는 서버 측 상태동일한 conversationId와 새 사용자 턴만 전달
previousResponseIdOpenAI Responses API만 해당대화를 생성하지 않는 가장 간단한 서버 관리형 연속 실행result.lastResponseId와 새 사용자 턴만 전달

result.historysession은 클라이언트가 관리합니다. conversationIdpreviousResponseId는 OpenAI가 관리하며 OpenAI Responses API를 사용할 때만 적용됩니다. 대부분의 애플리케이션에서는 대화마다 하나의 지속성 전략을 선택하세요. 두 계층을 의도적으로 조정하는 경우가 아니라면 클라이언트 관리형 기록과 서버 관리형 상태를 혼합할 때 컨텍스트가 중복될 수 있습니다.

샌드박스 에이전트는 라이브 샌드박스 작업 공간이라는 또 다른 상태 계층을 추가합니다. 대화 기록에는 일반 SDK의 session, conversationId 또는 previousResponseId를 사용하고, 샌드박스 파일 시스템 상태에는 sandbox.session, sandbox.sessionState, RunState 또는 스냅샷을 사용하세요. 작업 공간 수명 주기에 관한 자세한 내용은 개념을 참조하세요.

runner.run() 호출(또는 run() 유틸리티 호출)은 애플리케이션 수준 대화에서 하나의 을 나타냅니다. 최종 사용자에게 RunResult를 얼마나 보여줄지는 직접 선택할 수 있습니다. 경우에 따라 finalOutput만 보여주고, 다른 경우에는 생성된 모든 항목을 보여줄 수 있습니다.

대화 기록을 이어서 전달하는 예시
import { Agent, run } from '@openai/agents';
import type { AgentInputItem } from '@openai/agents';
let thread: AgentInputItem[] = [];
const agent = new Agent({
name: 'Assistant',
});
async function userSays(text: string) {
const result = await run(
agent,
thread.concat({ role: 'user', content: text }),
);
thread = result.history; // Carry over history + newly generated items
return result.finalOutput;
}
await userSays('What city is the Golden Gate Bridge in?');
// -> "San Francisco"
await userSays('What state is it in?');
// -> "California"

대화형 버전은 채팅 예제를 참조하세요.

매 턴마다 전체 로컬 대화 기록을 전송하는 대신 OpenAI Responses API가 대화 기록을 지속하도록 할 수 있습니다. 이는 긴 대화나 여러 서비스를 조율할 때 유용합니다. 아래 서버 관리형 접근 방식 중 어느 것을 사용하든 각 요청에는 새 턴의 입력만 전달하세요. API가 이전 상태를 재사용합니다. 자세한 내용은 대화 상태 가이드를 참조하세요.

OpenAI는 서버 측 상태를 재사용하는 두 가지 방법을 제공합니다.

Conversations API를 사용해 대화를 한 번 생성한 다음 모든 턴에서 해당 ID를 재사용할 수 있습니다. SDK는 새로 생성된 항목만 자동으로 포함합니다.

서버 대화 재사용
import { Agent, run } from '@openai/agents';
import { OpenAI } from 'openai';
const agent = new Agent({
name: 'Assistant',
instructions: 'Reply very concisely.',
});
async function main() {
// Create a server-managed conversation:
const client = new OpenAI();
const { id: conversationId } = await client.conversations.create({});
const first = await run(agent, 'What city is the Golden Gate Bridge in?', {
conversationId,
});
console.log(first.finalOutput);
// -> "San Francisco"
const second = await run(agent, 'What state is it in?', { conversationId });
console.log(second.finalOutput);
// -> "California"
}
main().catch(console.error);
2. 마지막 턴부터 계속하기 위한 previousResponseId
섹션 제목: “2. 마지막 턴부터 계속하기 위한 previousResponseId”

Responses API만으로 시작하려는 경우 이전 응답에서 반환된 ID를 사용해 각 요청을 연결할 수 있습니다. 이렇게 하면 전체 대화 리소스를 생성하지 않고도 여러 턴에 걸쳐 컨텍스트를 유지할 수 있습니다.

previousResponseId를 사용한 연결
import { Agent, run } from '@openai/agents';
const agent = new Agent({
name: 'Assistant',
instructions: 'Reply very concisely.',
});
async function main() {
const first = await run(agent, 'What city is the Golden Gate Bridge in?');
console.log(first.finalOutput);
// -> "San Francisco"
const previousResponseId = first.lastResponseId;
const second = await run(agent, 'What state is it in?', {
previousResponseId,
});
console.log(second.finalOutput);
// -> "California"
}
main().catch(console.error);

conversationIdpreviousResponseId는 함께 사용할 수 없습니다. 여러 시스템에서 공유할 수 있는 이름 있는 대화 리소스가 필요하면 conversationId를 사용하고, 한 응답에서 다음 응답으로 이어지는 비용이 가장 낮은 SDK 수준의 연속 실행 기본 구성 요소만 필요하면 previousResponseId를 사용하세요.

모델이 호출되기 직전에 모델 입력을 편집하려면 callModelInputFilter를 사용하세요. 이 훅은 현재 에이전트, 컨텍스트, 결합된 입력 항목(세션 기록이 있는 경우 해당 기록 포함)을 받습니다. 민감한 데이터를 수정하거나, 오래된 메시지를 제거하거나, 추가 시스템 지침을 삽입하려면 업데이트된 input 배열과 선택적 instructions를 반환하세요.

runner.run(..., { callModelInputFilter })에서 실행별로 설정하거나 Runner 설정에서 기본값으로 설정할 수 있습니다(RunConfigcallModelInputFilter).

반환 값은 ModelInputData 객체인 { input: AgentInputItem[], instructions? }여야 합니다. input 필드는 필수이며 배열이어야 합니다. 다른 형태를 반환하면 UserError가 발생합니다.

SDK는 필터를 호출하기 전에 준비된 턴 입력을 복제합니다. session도 사용 중이라면 필터링된 복제본이 지속되므로 여기서 적용한 수정이나 잘라내기가 저장된 세션 기록에도 반영됩니다.

conversationId 또는 previousResponseId를 사용하면 훅은 다음 Responses API 호출을 위해 준비된 페이로드에서 실행됩니다. 이전 서버 관리형 컨텍스트는 API가 복구하므로 해당 호출의 필터링된 배열은 이전 기록 전체를 재생하는 대신 이미 새 턴의 변경분만 나타낼 수 있습니다. 이 최종 필터 단계 전에 저장된 기록과 현재 턴을 병합하는 방식을 변경해야 한다면 sessionInputCallback을 사용하세요.

모델로 다시 전송되는 도구 오류 메시지를 사용자 지정하려면 toolErrorFormatter를 사용하세요. 이를 사용하면 SDK 기본 메시지 대신 도메인별 문구(예: 규정 준수 지침)를 반환할 수 있습니다.

포매터는 실행별로 설정하거나(runner.run(..., { toolErrorFormatter })) RunConfig에서 전역으로 설정할 수 있습니다(new Runner(...)toolErrorFormatter).

이 포매터는 승인 거부에 대한 전역 폴백입니다. 특정 인터럽션(중단 처리)을 result.state.reject(interruption, { message: '...' })로 거부하면 해당 호출별 messagetoolErrorFormatter보다 우선합니다. 둘 다 제공되지 않으면 SDK는 기본 거부 텍스트인 Tool execution was not approved.를 사용합니다.

toolNotFoundBehavior: 'return_error_to_model'이 확인되지 않은 함수 도구 호출을 모델에 표시되는 도구 출력으로 변환할 때도 포매터가 실행됩니다. 이 경우 기본 메시지는 Tool '<name>' not found.입니다.

포매터는 다음을 받습니다.

  • kind ('approval_rejected' 또는 'tool_not_found')
  • toolType ('function', 'computer', 'shell' 또는 'apply_patch')
  • toolName
  • callId
  • defaultMessage(현재 오류 종류에 대한 SDK 폴백 메시지)
  • runContext

메시지를 재정의하려면 문자열을 반환하고, SDK 기본값을 유지하려면 undefined를 반환하세요. 포매터에서 오류가 발생하거나 문자열이 아닌 값을 반환하면 SDK는 경고를 기록하고 현재 오류 종류의 기본 메시지를 사용합니다.

SDK가 이전에 생성된 실행 항목을 이후 모델 입력을 위한 AgentInputItem[]로 다시 변환할 때 추론 항목의 id 필드를 유지할지 제어하려면 reasoningItemIdPolicy를 사용하세요.

이는 SDK가 생성된 모델 항목을 입력으로 재생하는 다음과 같은 위치에 영향을 줍니다.

  • 동일한 실행 내의 후속 모델 호출(예: 도구 실행 후)
  • 생성된 항목을 입력/기록으로 재사용하는 이후 턴
  • 저장된 RunState에서 재개한 실행
  • result.history / result.output처럼 결과에서 파생된 뷰(모델 입력 형태의 배열)
  • 'preserve'(기본값)는 추론 항목 ID를 유지합니다.
  • 'omit'은 추론 항목을 다시 입력으로 보내기 전에 id 필드를 제거합니다.
  • 추론 항목이 아닌 항목은 영향을 받지 않습니다.

다음 항목은 변경되지 않습니다.

  • 원문 모델 응답(result.rawResponses)
  • 실행 항목(result.newItems)
  • 제공자가 반환한 모델의 현재 턴 출력

즉, 이 정책은 SDK가 이전에 생성된 항목으로 다음 입력을 구성할 때 적용됩니다.

정책은 실행별로 설정하거나(runner.run(..., { reasoningItemIdPolicy: 'omit' })) 러너 기본값으로 설정할 수 있습니다(new Runner({ reasoningItemIdPolicy: 'omit', ... })). 저장된 RunState에서 재개할 때는 재정의하지 않는 한 이전에 확정된 정책을 재사용합니다.

reasoningItemIdPolicycallModelInputFilter보다 먼저 적용됩니다. 사용자 지정 동작이 필요한 경우 callModelInputFilter에서 준비된 입력을 검사하고 모델 호출 전에 추론 ID를 수동으로 다시 추가하거나 제거할 수 있습니다.

재생되는 추론 항목을 ID 없이 정규화하려는 경우(예: 전달되거나 재생되는 모델 입력을 더 간단하게 유지하거나 앱 파이프라인의 연동 요구 사항에 맞추려는 경우) 'omit'을 사용하세요.

백엔드/제공자가 재생된 추론 항목을 요청 검증 오류로 거부하는 경우에도 유용한 문제 해결 옵션입니다. 예를 들어 후속 입력의 추론 항목 ID와 관련된 HTTP 400 오류가 발생할 수 있습니다. 이 경우 'omit'으로 재생된 추론 ID를 제거하면 백엔드가 새 요청에 유효하지 않은 것으로 처리하는 ID의 전송을 피할 수 있습니다.

SDK가 재생된 입력을 통해 추론 항목 ID를 전달하도록 하고 연동 환경에서 이를 허용하는 경우 'preserve'를 유지하세요.

지원되는 런타임 오류를 발생시키는 대신 최종 출력으로 변환하려면 errorHandlers를 사용하세요. 지원되는 키는 maxTurns, modelRefusal, invalidFinalOutput입니다.

  • errorHandlers.maxTurns는 최대 턴 오류만 처리합니다.
  • errorHandlers.modelRefusalModelRefusalError로 노출되는 모델 거부를 처리합니다.
  • errorHandlers.invalidFinalOutput은 구조화된 최종 출력이 없거나 출력 스키마 검증에 실패할 때 발생하는 ModelBehaviorError 인스턴스를 처리합니다. 핸들러는 모델을 재시도하거나 도구의 부수 효과를 재생하지 않고 검증된 폴백을 반환합니다.
  • errorHandlers.default는 지원되는 오류 종류의 폴백으로 사용됩니다.
  • 핸들러는 { error, context, runData }를 받고 { finalOutput, includeInHistory? }를 반환할 수 있습니다. 반환되는 finalOutput은 현재 에이전트의 outputType과 일치해야 합니다. 구조화된 출력의 경우 SDK는 실행을 완료하기 전에 폴백을 검증합니다. 해당 오류에 대해 undefined를 반환하면 기본 동작을 유지합니다.

SDK는 포착할 수 있는 소수의 오류를 발생시킵니다.

모두 기본 AgentsError 클래스를 확장하며, 이 클래스는 현재 실행 상태에 액세스할 수 있는 state 속성을 제공할 수 있습니다.

다음은 GuardrailExecutionError를 처리하는 코드 예제입니다. 입력 가드레일은 첫 번째 사용자 입력에서만 실행되므로 이 예제는 원래 입력과 컨텍스트로 실행을 다시 시작합니다. 또한 저장된 상태를 재사용하여 모델을 다시 호출하지 않고 출력 가드레일을 재시도하는 방법도 보여줍니다.

가드레일 실행 오류
import {
Agent,
GuardrailExecutionError,
InputGuardrail,
InputGuardrailTripwireTriggered,
OutputGuardrail,
OutputGuardrailTripwireTriggered,
run,
} from '@openai/agents';
import { z } from 'zod';
// Shared guardrail agent to avoid re-creating it on every fallback run.
const guardrailAgent = new Agent({
name: 'Guardrail check',
instructions: 'Check if the user is asking you to do their math homework.',
outputType: z.object({
isMathHomework: z.boolean(),
reasoning: z.string(),
}),
});
async function main() {
const input = 'Hello, can you help me solve for x: 2x + 3 = 11?';
const context = { customerId: '12345' };
// Input guardrail example
const unstableInputGuardrail: InputGuardrail = {
name: 'Math Homework Guardrail (unstable)',
execute: async () => {
throw new Error('Something is wrong!');
},
};
const fallbackInputGuardrail: InputGuardrail = {
name: 'Math Homework Guardrail (fallback)',
execute: async ({ input, context }) => {
const result = await run(guardrailAgent, input, { context });
const isMathHomework =
result.finalOutput?.isMathHomework ??
/solve for x|math homework/i.test(JSON.stringify(input));
return {
outputInfo: result.finalOutput,
tripwireTriggered: isMathHomework,
};
},
};
const agent = new Agent({
name: 'Customer support agent',
instructions:
'You are a customer support agent. You help customers with their questions.',
inputGuardrails: [unstableInputGuardrail],
});
try {
// Input guardrails only run on the first turn of a run, so retries must start a fresh run.
await run(agent, input, { context });
} catch (e) {
if (e instanceof GuardrailExecutionError) {
console.error(`Guardrail execution failed (input): ${e}`);
try {
agent.inputGuardrails = [fallbackInputGuardrail];
// Retry from scratch with the original input and context.
await run(agent, input, { context });
} catch (ee) {
if (ee instanceof InputGuardrailTripwireTriggered) {
console.log('Math homework input guardrail tripped on retry');
} else {
throw ee;
}
}
} else {
throw e;
}
}
// Output guardrail example
const replyOutputSchema = z.object({ reply: z.string() });
const unstableOutputGuardrail: OutputGuardrail<typeof replyOutputSchema> = {
name: 'Answer review (unstable)',
execute: async () => {
throw new Error('Output guardrail crashed.');
},
};
const fallbackOutputGuardrail: OutputGuardrail<typeof replyOutputSchema> = {
name: 'Answer review (fallback)',
execute: async ({ agentOutput }) => {
const outputText =
typeof agentOutput === 'string'
? agentOutput
: (agentOutput?.reply ?? JSON.stringify(agentOutput));
const flagged = /math homework|solve for x|x =/i.test(outputText);
return {
outputInfo: { flaggedOutput: outputText },
tripwireTriggered: flagged,
};
},
};
const agent2 = new Agent<unknown, typeof replyOutputSchema>({
name: 'Customer support agent (output check)',
instructions: 'You are a customer support agent. Answer briefly.',
outputType: replyOutputSchema,
outputGuardrails: [unstableOutputGuardrail],
});
try {
await run(agent2, input, { context });
} catch (e) {
if (e instanceof GuardrailExecutionError && e.state) {
console.error(`Guardrail execution failed (output): ${e}`);
try {
agent2.outputGuardrails = [fallbackOutputGuardrail];
// Output guardrails can be retried using the saved state without another model call.
await run(agent2, e.state);
} catch (ee) {
if (ee instanceof OutputGuardrailTripwireTriggered) {
console.log('Output guardrail tripped after retry with saved state');
} else {
throw ee;
}
}
} else {
throw e;
}
}
}
main().catch(console.error);

입력 및 출력 재시도의 차이는 다음과 같습니다.

  • 입력 가드레일은 실행의 맨 처음 사용자 입력에서만 실행되므로 같은 입력/컨텍스트로 새 실행을 시작해야 재시도할 수 있습니다. 저장된 state를 전달해도 입력 가드레일이 다시 실행되지 않습니다.
  • 출력 가드레일은 모델 응답 후 실행되므로 GuardrailExecutionError에 저장된 state를 재사용하여 모델을 다시 호출하지 않고 출력 가드레일을 재실행할 수 있습니다.

위 예제를 실행하면 다음과 같은 출력이 표시됩니다.

Guardrail execution failed (input): Error: Input guardrail failed to complete: Error: Something is wrong!
Math homework input guardrail tripped on retry
Guardrail execution failed (output): Error: Output guardrail failed to complete: Error: Output guardrail crashed.
Output guardrail tripped after retry with saved state

  • 에이전트를 실행하기 전에 정의하는 방법은 에이전트를 참조하세요.
  • finalOutput, 실행 항목, 인터럽션(중단 처리), 재개 상태에 관한 내용은 실행 결과를 참조하세요.
  • SDK가 관리하는 지속성 메모리에 관한 내용은 세션을 참조하세요.
  • 실행 루프에서 사용하는 기능에 관한 내용은 도구를 참조하세요.
  • 제공자 설정과 Responses 전송에 관한 내용은 모델을 참조하세요.
  • 프로덕션 준비를 위해 가드레일 또는 트레이싱을 추가하세요.