콘텐츠로 이동

스트리밍

Agents SDK는 모델과 기타 실행 단계를 점진적으로 전달할 수 있습니다. 스트리밍은 UI를 반응성 있게 유지하고 전체 최종 결과를 기다리지 않고도 사용자에게 업데이트를 제공합니다.

Runner.run(){ stream: true } 옵션을 전달하여 전체 결과 대신 스트리밍 객체를 얻습니다:

Enabling streaming
import { Agent, run } from '@openai/agents';
const agent = new Agent({
name: 'Storyteller',
instructions:
'You are a storyteller. You will be given a topic and you will tell a story about it.',
});
const result = await run(agent, 'Tell me a story about a cat.', {
stream: true,
});

스트리밍이 활성화되면 반환된 streamAsyncIterable 인터페이스를 구현합니다. 각 항목은 실행 중에 발생한 일을 설명하는 객체입니다. 스트림은 에이전트 실행의 서로 다른 부분을 설명하는 세 가지 이벤트 유형 중 하나를 제공합니다. 대부분의 애플리케이션은 모델의 텍스트만 원하므로, 스트림은 이를 위한 헬퍼를 제공합니다.

stream.toTextStream()을 호출하여 방출된 텍스트의 스트림을 얻습니다. compatibleWithNodeStreamstrue이면 반환값은 일반 Node.js Readable입니다. process.stdout 또는 다른 대상으로 직접 파이프할 수 있습니다.

Logging out the text as it arrives
import { Agent, run } from '@openai/agents';
const agent = new Agent({
name: 'Storyteller',
instructions:
'You are a storyteller. You will be given a topic and you will tell a story about it.',
});
const result = await run(agent, 'Tell me a story about a cat.', {
stream: true,
});
result
.toTextStream({
compatibleWithNodeStreams: true,
})
.pipe(process.stdout);

프로미스 stream.completed는 실행과 모든 보류 중인 콜백이 완료되면 resolve됩니다. 더 이상 출력이 없음을 보장하려면 항상 이를 await하세요.

for await 루프를 사용하여 각 이벤트가 도착할 때 검사할 수 있습니다. 유용한 정보에는 저수준 모델 이벤트, 에이전트 전환 여부, SDK 특정 실행 정보 등이 포함됩니다:

Listening to all events
import { Agent, run } from '@openai/agents';
const agent = new Agent({
name: 'Storyteller',
instructions:
'You are a storyteller. You will be given a topic and you will tell a story about it.',
});
const result = await run(agent, 'Tell me a story about a cat.', {
stream: true,
});
for await (const event of result) {
// these are the raw events from the model
if (event.type === 'raw_model_stream_event') {
console.log(`${event.type} %o`, event.data);
}
// agent updated events
if (event.type === 'agent_updated_stream_event') {
console.log(`${event.type} %s`, event.agent.name);
}
// Agent SDK specific events
if (event.type === 'run_item_stream_event') {
console.log(`${event.type} %o`, event.item);
}
}

전체 텍스트 스트림과 원문 이벤트 스트림을 모두 출력하는 완전한 스크립트는 스트리밍 예제를 참조하세요.

이 페이지의 스트리밍 API는 OpenAI Responses WebSocket 전송과도 함께 작동합니다.

setOpenAIResponsesTransport('websocket')으로 전역 활성화하거나, useResponsesWebSocket: true가 설정된 자체 OpenAIProvider를 사용하세요.

WebSocket으로 스트리밍하기 위해서만 withResponsesWebSocketSession(...) 또는 커스텀 OpenAIProvider가 필요하지는 않습니다. 실행 간 재연결이 허용된다면, 전송 방식을 활성화한 후에도 run() / Runner.run(..., { stream: true })는 계속 동작합니다.

연결 재사용과 더 명시적인 프로바이더 라이프사이클 제어가 필요할 때 withResponsesWebSocketSession(...) 또는 커스텀 OpenAIProvider / Runner를 사용하세요.

프로바이더를 직접 구성했다면 종료 시 await provider.close()를 호출하는 것을 잊지 마세요. WebSocket 기반 모델 래퍼는 기본적으로 재사용을 위해 캐시되며, 프로바이더를 닫으면 해당 연결이 해제됩니다. withResponsesWebSocketSession(...)은 동일한 재사용 이점을 제공하면서 정리를 단일 콜백 범위로 자동 한정합니다.

스트리밍, 도구 호출, 승인, previousResponseId를 포함한 완전한 예제는 examples/basic/stream-ws.ts를 참조하세요.

스트림은 세 가지 서로 다른 이벤트 유형을 제공합니다:

type RunRawModelStreamEvent = {
type: 'raw_model_stream_event';
data: ResponseStreamEvent;
};

예시:

{
"type": "raw_model_stream_event",
"data": {
"type": "output_text_delta",
"delta": "Hello"
}
}
type RunItemStreamEvent = {
type: 'run_item_stream_event';
name: RunItemStreamEventName;
item: RunItem;
};

name은 어떤 종류의 아이템이 생성되었는지 식별합니다:

name의미
message_output_created메시지 출력 아이템이 생성됨
handoff_requested모델이 핸드오프를 요청함
handoff_occurred런타임이 다른 에이전트로의 핸드오프를 완료함
tool_called도구 호출 아이템이 방출됨
tool_output도구 결과 아이템이 방출됨
reasoning_item_createdreasoning 아이템이 방출됨
tool_approval_requested도구 호출이 휴먼 승인 대기로 일시 중지됨

핸드오프 페이로드 예시:

{
"type": "run_item_stream_event",
"name": "handoff_occurred",
"item": {
"type": "handoff_call",
"id": "h1",
"status": "completed",
"name": "transfer_to_refund_agent"
}
}
type RunAgentUpdatedStreamEvent = {
type: 'agent_updated_stream_event';
agent: Agent<any, any>;
};

예시:

{
"type": "agent_updated_stream_event",
"agent": {
"name": "Refund Agent"
}
}

스트리밍 중 휴먼인더루프 (HITL)

섹션 제목: “스트리밍 중 휴먼인더루프 (HITL)”

스트리밍은 실행을 일시 중지하는 핸드오프(예: 도구가 승인을 요구하는 경우)와 호환됩니다. 스트림 객체의 interruption 필드는 인터럽션(중단 처리)을 노출하며, 각 항목에 대해 state.approve() 또는 state.reject()를 호출하여 실행을 계속할 수 있습니다. { stream: true }로 다시 실행하면 스트리밍 출력이 재개됩니다.

Handling human approval while streaming
import { Agent, run } from '@openai/agents';
const agent = new Agent({
name: 'Storyteller',
instructions:
'You are a storyteller. You will be given a topic and you will tell a story about it.',
});
let stream = await run(
agent,
'What is the weather in San Francisco and Oakland?',
{ stream: true },
);
stream.toTextStream({ compatibleWithNodeStreams: true }).pipe(process.stdout);
await stream.completed;
while (stream.interruptions?.length) {
console.log(
'Human-in-the-loop: approval required for the following tool calls:',
);
const state = stream.state;
for (const interruption of stream.interruptions) {
const approved = confirm(
`Agent ${interruption.agent.name} would like to use the tool ${interruption.name} with "${interruption.arguments}". Do you approve?`,
);
if (approved) {
state.approve(interruption);
} else {
state.reject(interruption);
}
}
// Resume execution with streaming output
stream = await run(agent, state, { stream: true });
const textStream = stream.toTextStream({ compatibleWithNodeStreams: true });
textStream.pipe(process.stdout);
await stream.completed;
}

사용자와 상호작용하는 보다 완전한 예제는 human-in-the-loop-stream.ts를 참조하세요.

  • 모든 출력이 플러시되었는지 보장하려면 종료 전에 stream.completed를 기다리세요
  • 초기 { stream: true } 옵션은 제공된 해당 호출에만 적용됩니다. RunState로 다시 실행하는 경우 옵션을 다시 지정해야 합니다
  • 애플리케이션이 텍스트 결과만 중요하다면 개별 이벤트 객체를 처리하지 않도록 toTextStream()을 선호하세요

스트리밍과 이벤트 시스템을 사용하면 채팅 인터페이스, 터미널 애플리케이션 등 점진적 업데이트가 유익한 모든 곳에 에이전트를 통합할 수 있습니다.