ストリーミング
Agents SDK は、モデルおよび他の実行ステップからの出力を段階的に配信できます。ストリーミングにより UI を応答性よく保ち、ユーザーを更新する前に最終結果全体を待つことを避けられます。
ストリーミングの有効化
Section titled “ストリーミングの有効化”Runner.run()
に { stream: true }
オプションを渡すと、完全な実行結果ではなくストリーミングオブジェクトを取得できます。
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,});
ストリーミングが有効な場合、返される stream
は AsyncIterable
インターフェースを実装します。各イテレートで得られるイベントは、実行内で何が起きたかを表すオブジェクトです。ストリームはエージェントの実行の異なる部分を記述する 3 種類のイベントのいずれかを返します。多くのアプリケーションはモデルのテキストだけを必要とするため、ストリームにはそのためのヘルパーが用意されています。
テキスト出力の取得
Section titled “テキスト出力の取得”発生したテキストのストリームを得るには stream.toTextStream()
を呼びます。compatibleWithNodeStreams
が true
のとき、戻り値は通常の Node.js Readable
です。process.stdout
や他の出力先へ直接パイプできます。
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
の Promise は、実行とすべての保留中のコールバックが完了すると解決されます。出力がもうないことを確実にしたい場合は必ず await してください。
すべてのイベントの監視
Section titled “すべてのイベントの監視”for await
ループを使えば、到着した各イベントを検査できます。役立つ情報には、低レベルのモデルイベント、任意のエージェントの切り替え、そして SDK 固有の実行情報が含まれます。
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); }}
ストリーミングされた code examples を参照すると、プレーンテキストストリームと元のイベントストリームの両方を出力する完全なスクリプトが見られます。
イベントタイプ
Section titled “イベントタイプ”ストリームは 3 種類のイベントタイプを返します。
raw_model_stream_event
Section titled “raw_model_stream_event”type RunRawModelStreamEvent = { type: 'raw_model_stream_event'; data: ResponseStreamEvent;};
例:
{ "type": "raw_model_stream_event", "data": { "type": "output_text_delta", "delta": "Hello" }}
run_item_stream_event
Section titled “run_item_stream_event”type RunItemStreamEvent = { type: 'run_item_stream_event'; name: RunItemStreamEventName; item: RunItem;};
ハンドオフのペイロード例:
{ "type": "run_item_stream_event", "name": "handoff_occurred", "item": { "type": "handoff_call", "id": "h1", "status": "completed", "name": "transfer_to_refund_agent" }}
agent_updated_stream_event
Section titled “agent_updated_stream_event”type RunAgentUpdatedStreamEvent = { type: 'agent_updated_stream_event'; agent: Agent<any, any>;};
例:
{ "type": "agent_updated_stream_event", "agent": { "name": "Refund Agent" }}
ストリーミング中の Human in the loop(人間の介入)
Section titled “ストリーミング中の Human in the loop(人間の介入)”ストリーミングは、実行を一時停止するハンドオフ(たとえばツールに承認が必要な場合)と両立します。ストリームオブジェクトの interruption
フィールドは割り込みを公開しており、それぞれに対して state.approve()
または state.reject()
を呼ぶことで実行を継続できます。{ stream: true }
で再実行すると、ストリーミング出力が再開されます。
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.rawItem.name} with "${interruption.rawItem.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()
を優先してください
ストリーミングとイベントシステムにより、エージェントをチャットインターフェース、ターミナルアプリケーション、あるいはユーザーが段階的な更新の恩恵を受けるあらゆる場所に統合できます。