콘텐츠로 이동

실행 결과

에이전트 실행 시 다음 중 하나를 받습니다.

두 결과 타입 모두 finalOutput, newItems, interruptions, state 같은 동일한 핵심 결과 인터페이스를 제공합니다. StreamedRunResult에는 completed, toStream(), toTextStream(), currentAgent 같은 스트리밍 제어 기능이 추가됩니다.

대부분의 애플리케이션에는 몇 가지 속성만 필요합니다.

필요한 항목사용할 속성
사용자에게 표시할 최종 답변finalOutput
전체 로컬 대화 기록을 포함하며 재실행 가능한 다음 턴 입력history
이 실행에서 새로 생성된 모델 형식 항목만 필요한 경우output
에이전트/도구/핸드오프 메타데이터를 포함한 상세 실행 항목newItems
일반적으로 다음 사용자 턴을 처리해야 하는 에이전트lastAgent 또는 activeAgent
previousResponseId를 사용한 OpenAI Responses API 연결lastResponseId
대기 중인 승인과 재개 가능한 스냅샷interruptionsstate
앱 컨텍스트, 승인, 사용량 및 중첩된 에이전트 도구 입력runContext
현재 중첩된 Agent.asTool() 호출에 관한 메타데이터(예: customOutputExtractor 내부)agentToolInvocation
원문 모델 호출 또는 가드레일 진단rawResponses 및 가드레일 결과 배열

finalOutput 속성에는 마지막으로 실행된 에이전트의 최종 출력이 포함됩니다. 이 결과는 다음 중 하나입니다.

  • stringoutputType이 정의되지 않은 모든 에이전트의 기본값
  • unknown — 에이전트의 출력 타입으로 JSON 스키마가 정의된 경우. 이 경우 JSON은 파싱되지만 타입은 직접 검증해야 합니다.
  • z.infer<outputType> — 에이전트의 출력 타입으로 Zod 스키마가 정의된 경우. 출력은 이 스키마에 따라 자동으로 파싱됩니다.
  • 추론된 검증 출력 타입 — 에이전트의 출력 타입으로 지원되는 Standard Schema 값이 정의된 경우. 출력은 이 스키마에 따라 동기적으로 파싱되고 검증됩니다.
  • undefined — 에이전트가 출력을 생성하지 않은 경우(예: 출력을 생성하기 전에 중지된 경우)

스트리밍 실행이 아직 진행 중이거나 최종 출력에 도달하기 전에 승인 인터럽션(중단 처리)으로 실행이 일시 중지된 경우에도 finalOutputundefined입니다.

출력 타입이 서로 다른 핸드오프를 사용하는 경우 new Agent() 생성자 대신 Agent.create() 메서드를 사용하여 에이전트를 생성해야 합니다.

그러면 SDK가 가능한 모든 핸드오프의 출력 타입을 추론하고 finalOutput 속성에 유니언 타입을 제공할 수 있습니다.

예시는 다음과 같습니다.

핸드오프 최종 출력 타입
import { Agent, run } from '@openai/agents';
import { z } from 'zod';
const refundAgent = new Agent({
name: 'Refund Agent',
instructions:
'You are a refund agent. You are responsible for refunding customers.',
outputType: z.object({
refundApproved: z.boolean(),
}),
});
const orderAgent = new Agent({
name: 'Order Agent',
instructions:
'You are an order agent. You are responsible for processing orders.',
outputType: z.object({
orderId: z.string(),
}),
});
const triageAgent = Agent.create({
name: 'Triage Agent',
instructions:
'You are a triage agent. You are responsible for triaging customer issues.',
handoffs: [refundAgent, orderAgent],
});
const result = await run(triageAgent, 'I need to a refund for my order');
const output = result.finalOutput;
// ^? { refundApproved: boolean } | { orderId: string } | string | undefined

각 속성은 서로 다른 용도로 사용됩니다.

속성포함된 내용적합한 용도
input이 실행의 기본 입력입니다. 핸드오프 입력 필터가 기록을 다시 작성한 경우, 실행이 계속 진행될 때 사용한 필터링된 입력을 반영합니다.이 실행에서 실제로 사용한 입력 감사
output에이전트 메타데이터 없이 이 실행에서 생성된 모델 형식 항목만 포함합니다.새 모델 델타만 저장하거나 재실행
newItems에이전트/도구/핸드오프 메타데이터가 포함된 상세 RunItem 래퍼입니다.로그, UI, 감사 및 디버깅
historyinput + newItems로 구성된, 재실행 가능한 다음 턴 입력입니다.수동 채팅 루프 및 클라이언트가 관리하는 대화 상태

실제로는 다음과 같이 사용합니다.

  • 애플리케이션에서 전체 대화를 직접 유지하는 경우 history를 사용합니다.
  • 이전 기록을 이미 다른 곳에 저장하고 있으며 이 실행에서 새로 생성된 항목만 필요한 경우 output을 사용합니다.
  • 에이전트 연결 정보, 도구 출력, 핸드오프 경계 또는 승인 항목이 필요한 경우 newItems를 사용합니다.
  • conversationId 또는 previousResponseId를 사용하는 경우 일반적으로 historyrun()에 다시 전달하지 않습니다. 대신 새 사용자 입력만 전달하고 서버에서 관리하는 ID를 재사용합니다. 전체 비교는 에이전트 실행을 참조하세요.

history를 사용하면 채팅과 같은 사용 사례에서 전체 기록을 편리하게 유지할 수 있습니다.

기록 루프
import { Agent, user, run } from '@openai/agents';
import type { AgentInputItem } from '@openai/agents';
const agent = new Agent({
name: 'Assistant',
instructions:
'You are a helpful assistant knowledgeable about recent AGI research.',
});
let history: AgentInputItem[] = [
// initial message
user('Are we there yet?'),
];
for (let i = 0; i < 10; i++) {
// run 10 times
const result = await run(agent, history);
// update the history to the new output
history = result.history;
history.push(user('How about now?'));
}

newItems는 실행 중 발생한 상황을 가장 상세하게 보여 줍니다. 일반적인 항목 타입은 다음과 같습니다.

어떤 에이전트가 항목을 생성했는지 또는 해당 항목이 도구, 도구 검색, 핸드오프, 승인 경계를 나타내는지 알아야 할 때는 output 대신 newItems를 선택하세요. toolSearchTool()을 사용할 때 이러한 도구 검색 항목은 일반적인 도구 호출이 발생하기 전에 어떤 지연 로드 도구 또는 네임스페이스가 로드되었는지 확인하는 가장 쉬운 방법입니다.

로컬 도구 또는 MCP 서버에 customDataExtractor가 정의되어 있으면 해당 RunToolCallOutputItem.customData에 반환된 SDK 전용 메타데이터가 포함됩니다. 이 데이터는 렌더러 힌트나 내부 ID 같은 애플리케이션 UI 상태에 유용합니다. 이 데이터는 RunState 직렬화 후에도 유지되지만 history에서는 제외되며 모델에 다시 전송되지 않습니다.

RunToolCallOutputItem.output은 SDK 측 도구 반환 값입니다. JSON 호환 기본형, 배열 및 일반 객체는 RunState 직렬화 후에도 구조가 유지됩니다. 그 외의 라이브 값에는 기존 문자열 폴백이 적용됩니다. 이 래퍼 값은 rawItem.output과 별도로 유지되며, rawItem.outputhistory 및 재실행에서 사용하는 모델 공개 도구 출력입니다.

lastAgent 속성에는 마지막으로 실행된 에이전트가 포함됩니다. 이는 핸드오프 후 다음 사용자 턴에 재사용하기에 가장 적합한 에이전트인 경우가 많습니다. activeAgent는 동일한 값의 별칭입니다.

스트리밍 모드에서 currentAgent는 실행이 아직 진행되는 동안 현재 어떤 에이전트가 활성 상태인지 알려 줍니다.

인터럽션(중단 처리) 및 재개 가능한 상태

섹션 제목: “인터럽션(중단 처리) 및 재개 가능한 상태”

도구에 승인이 필요하면 실행이 일시 중지되고 interruptions에 대기 중인 RunToolApprovalItem이 포함됩니다. 여기에는 직접 사용된 도구, 핸드오프 후 도달한 도구 또는 중첩된 agent.asTool() 실행에서 발생한 승인이 포함될 수 있습니다.

result.state.approve(...) / result.state.reject(...)를 통해 승인을 처리한 다음 동일한 staterun()에 다시 전달하여 실행을 재개합니다. 모든 인터럽션(중단 처리)을 한 번에 처리할 필요는 없습니다. 일부 항목만 처리한 후 다시 실행하면 처리된 호출은 계속 진행되고, 미처리 항목은 대기 상태로 남아 실행을 다시 일시 중지할 수 있습니다.

state 속성은 결과의 기반이 되는 직렬화 가능한 스냅샷입니다. 휴먼 인 더 루프 (HITL), 재시도 흐름 또는 일시 중지된 실행을 나중에 재개해야 하는 경우에 사용합니다.

lastResponseId는 OpenAI Responses API 연결을 사용할 때 다음 턴의 previousResponseId로 전달할 값입니다.

이미 history, session 또는 conversationId를 사용하여 대화를 계속하고 있다면 일반적으로 lastResponseId가 필요하지 않습니다. 여러 단계로 구성된 실행의 모든 원문 모델 응답이 필요하다면 대신 rawResponses를 확인하세요.

중첩된 에이전트 도구 메타데이터

섹션 제목: “중첩된 에이전트 도구 메타데이터”

agentToolInvocation은 중첩된 Agent.asTool() 결과를 위한 것으로, 특히 customOutputExtractor 내부에서 현재 도구 호출에 관한 메타데이터가 필요한 경우에 사용합니다. 전체 실행이 완료되었음을 요약하는 일반적인 필드가 아닙니다.

이 중첩된 컨텍스트에서 agentToolInvocation은 다음을 제공합니다.

  • toolName
  • toolCallId
  • toolArguments

중첩된 에이전트 도구 실행에 전달된 구조화된 입력도 필요한 경우 result.runContext.toolInput과 함께 사용합니다.

일반적인 최상위 run() 결과에서 이 값은 대개 undefined입니다. 메타데이터는 런타임 전용이며 RunState로 직렬화되지 않습니다. 관련 패턴은 Agents as tools를 참조하세요.

StreamedRunResult는 위와 동일한 결과 인터페이스를 상속하지만 스트리밍 전용 제어 기능도 추가합니다.

  • 어시스턴트 텍스트만 제공하는 toTextStream().
  • 전체 이벤트 스트림을 제공하는 toStream() 또는 for await ... of stream.
  • 실행 및 모든 후처리 콜백이 끝날 때까지 기다리는 completed.
  • 최종 스트리밍 상태를 확인하는 errorcancelled.
  • 실행 중 활성 에이전트를 추적하는 currentAgent.
  • 실제로 요청 경계에 도달한 모델 턴 수를 확인하는 currentTurn.
  • 이 스트리밍 실행에 적용된 제한을 확인하는 maxTurns (null은 제한 없음을 의미).

currentTurn은 모델 요청이 허용될 때만 증가합니다. 최대 턴 검사 또는 요청을 차단하는 입력 가드레일은 이 값을 증가시키지 않으며, 재개된 실행은 해당 RunState에 보존된 횟수부터 시작합니다.

스트리밍 실행의 확정된 최종 상태가 필요한 경우 finalOutput, history, interruptions 또는 기타 요약 속성을 읽기 전에 completed를 기다리세요. 이벤트별 처리 방법은 스트리밍을 참조하세요.

스트리밍 실행이 취소되면 정리 작업 후에도 completed는 정상적으로 완료되고 cancelledtrue가 되지만, 현재 턴이 완료되지 않았으므로 finalOutput 같은 턴 종료 필드는 설정되지 않은 상태로 남을 수 있습니다. 새 사용자 메시지를 추가하는 대신 result.state와 동일한 session을 사용하여 완료되지 않은 턴을 재개하세요(session을 사용하는 경우).

runContext 속성은 결과에서 지원되는 실행 컨텍스트의 공개 인터페이스입니다. result.runContext.context는 앱 컨텍스트이며, 동일한 객체에는 승인, 사용량 및 중첩된 toolInput 같은 SDK 관리형 런타임 메타데이터도 포함됩니다. 전체 구조는 컨텍스트 관리를 참조하세요.

rawResponses에는 실행 중 수집된 원문 모델 응답이 포함됩니다. 여러 단계로 구성된 실행은 핸드오프 또는 반복되는 도구/모델 주기 등에 걸쳐 두 개 이상의 응답을 생성할 수 있습니다.

출력 가드레일이 최종 함수 도구 결과를 거부하면 SDK는 SDK가 관리하는 다른 재실행 인터페이스와 함께 rawResponses의 현재 응답을 정리합니다. 이 속성을 통해 거부된 최종 도구 출력을 계속 확인할 수 있다고 가정하지 마세요. 수정 처리 경계와 제한 사항은 거부된 최종 도구 출력을 참조하세요.

각 응답에는 제공업체의 요청 식별자를 나타내는 requestId도 포함될 수 있습니다. OpenAI Responses 및 Chat Completions 모델은 스트리밍 및 비스트리밍 HTTP 요청에 이 값을 채웁니다. 일부 제공업체와 전송 방식은 이 값을 제공하지 않으므로 선택적 값으로 취급하세요.

Chat Completions 텍스트 출력의 URL 인용을 읽으려면 정규화된 output_text 부분의 providerData.annotations를 확인하세요. 비스트리밍 응답은 제공업체의 메시지 주석을 보존합니다. 스트리밍 응답은 텍스트와 함께 수신된 유효한 url_citation 주석을 유지하고, 반복된 인용은 중복 제거하며, 잘못된 형식이나 지원되지 않는 주석 구조는 무시합니다.

Chat Completions 오디오에서 정규화된 모델 응답은 audio 콘텐츠 부분이 포함된 오디오 전용 어시스턴트 메시지를 나타냅니다. 이 메시지가 실행 항목이 되면 동일한 부분을 RunMessageOutputItem.rawItem에서 확인하세요. 비스트리밍 응답에 오디오와 함께 텍스트 또는 거부가 포함된 경우 정규화된 어시스턴트 메시지는 텍스트 또는 거부를 유지하며, 전체 제공업체 응답은 rawResponses[].providerData에서 확인할 수 있습니다. 스트리밍 혼합 출력에서 제공업체 오디오 청크를 도착하는 즉시 확인해야 한다면 원문 모델 스트림 이벤트를 확인하세요. 완료된 rawResponses 항목에는 정규화된 텍스트 또는 거부가 포함되지만 재구성된 오디오는 포함되지 않습니다. 스트리밍 toTextStream() 도우미는 텍스트만 내보냅니다.

modelSettings.preserveRawUsagetrue이면 완료된 각 응답에 SDK 정규화 전에 캡처된 분리된 JSON 호환 스냅샷인 rawUsage가 포함될 수도 있습니다. 정규화된 Usage는 계속 response.usage에서 사용할 수 있으며, rawUsage는 제공된 경우 제공업체별 필드 이름과 생략된 값 및 명시된 값의 차이를 보존합니다. 제공업체가 사용량을 생략하거나 페이로드를 안전하게 복사할 수 없는 경우 undefined일 수 있습니다. rawUsage는 런타임 전용이며 직렬화된 RunState에서 의도적으로 제외되므로, 실행을 저장하고 재개하기 전에 필요한 필드를 복사하세요.

inputGuardrailResultsoutputGuardrailResults 속성에는 에이전트 수준 가드레일 결과가 포함됩니다. 도구 가드레일 결과는 toolInputGuardrailResultstoolOutputGuardrailResults를 통해 별도로 제공됩니다.

가드레일 결정을 기록하거나, 가드레일 함수가 반환한 추가 메타데이터를 확인하거나, 실행이 차단된 이유를 디버깅하려는 경우 이러한 배열을 사용합니다.

거부된 최종 함수 도구 결과에 대해 SDK는 현재 응답의 가드레일 메타데이터를 의도적으로 정리합니다. outputGuardrailResults에서 agentOutputOutput withheld by an output guardrail.이 되고 outputInfo는 제거됩니다. 현재 toolOutputGuardrailResults는 판정을 유지하지만 outputInfo는 생략하며, rejectContent 결과는 메시지에 동일한 자리표시자를 사용합니다. 이전에 승인된 과거 결과는 변경되지 않습니다.

하나의 가드레일 실행이 실패하더라도 성공적으로 완료된 다른 가드레일의 결과는 실행 상태에 유지됩니다. 스트리밍 실행에서는 completed가 거부된 후 결과 배열을 확인하세요. 비스트리밍 실행에서는 GuardrailExecutionError에 동일하게 확정된 state가 포함됩니다.

토큰 사용량은 result.state.usage에 집계되며, 실행의 요청 횟수와 토큰 합계를 추적합니다. 동일한 사용량 객체는 result.runContext.usage에서도 사용할 수 있습니다. 스트리밍 실행에서는 응답이 도착할 때마다 이 데이터가 업데이트됩니다.

완료된 스트리밍 또는 비스트리밍 Chat Completions 호출은 제공업체가 사용량 객체를 생략하더라도 하나의 요청으로 계산됩니다. 이 경우 제공업체가 토큰 수를 보고하지 않았으므로 토큰 합계는 0으로 유지됩니다.

RunState에서 사용량 읽기
import { Agent, run } from '@openai/agents';
const agent = new Agent({
name: 'Usage Tracker',
instructions: 'Summarize the latest project update in one sentence.',
});
const result = await run(
agent,
'Summarize this: key customer feedback themes and the next product iteration.',
);
const usage = result.state.usage;
console.log({
requests: usage.requests,
inputTokens: usage.inputTokens,
outputTokens: usage.outputTokens,
totalTokens: usage.totalTokens,
});
if (usage.requestUsageEntries) {
for (const entry of usage.requestUsageEntries) {
console.log('request', {
endpoint: entry.endpoint,
inputTokens: entry.inputTokens,
outputTokens: entry.outputTokens,
totalTokens: entry.totalTokens,
});
}
}