エージェントの実行結果
エージェントの実行を行うと、次のいずれかを受け取ります。
stream: trueを指定せずにrunを呼び出した場合は、RunResultstream: trueを指定してrunを呼び出した場合は、StreamedRunResult。ストリーミングの詳細については、ストリーミングも参照してください
どちらの実行結果型も、finalOutput、newItems、interruptions、state など、共通の主要な実行結果サーフェスを公開します。StreamedRunResult には、completed、toStream()、toTextStream()、currentAgent など、ストリーミング用の制御機能も追加されています。
適切な実行結果サーフェスの選択
Section titled “適切な実行結果サーフェスの選択”ほとんどのアプリケーションで必要になるプロパティは、ごくわずかです。
| 必要なもの | 使用するプロパティ |
|---|---|
| ユーザーに表示する最終回答 | finalOutput |
| ローカルの全会話履歴を含む、再生可能な次ターンの入力 | history |
| この実行で新しく生成されたモデル形式の項目のみ | output |
| エージェント、ツール、ハンドオフのメタデータを含む詳細な実行項目 | newItems |
| 通常、次のユーザーターンを処理するエージェント | lastAgent または activeAgent |
previousResponseId を使用した OpenAI Responses API の連結 | lastResponseId |
| 保留中の承認と再開可能なスナップショット | interruptions と state |
| アプリケーションコンテキスト、承認、使用量、ネストされたエージェントツールの入力 | runContext |
現在のネストされた Agent.asTool() 呼び出しに関するメタデータ(customOutputExtractor 内など) | agentToolInvocation |
| 元のモデル呼び出しまたはガードレールの診断情報 | rawResponses とガードレール実行結果の配列 |
finalOutput プロパティには、最後に実行されたエージェントの最終出力が格納されます。この実行結果は、次のいずれかです。
string—outputTypeが定義されていないエージェントのデフォルトunknown— エージェントの出力型として JSON スキーマが定義されている場合。この場合、JSON は解析されていますが、型は手動で検証する必要がありますz.infer<outputType>— エージェントの出力型として Zod スキーマが定義されている場合。出力は、このスキーマに対して自動的に解析されます- 推論された検証済み出力型 — エージェントの出力型として、サポートされている Standard Schema 値が定義されている場合。出力は、このスキーマに対して同期的に解析および検証されます
undefined— エージェントが出力を生成しなかった場合(出力を生成する前に停止した場合など)
ストリーミング実行が進行中の場合や、最終出力に到達する前に承認割り込みによって実行が一時停止した場合も、finalOutput は undefined になります。
異なる出力型を持つハンドオフを使用する場合は、エージェントの作成に 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入出力サーフェス
Section titled “入出力サーフェス”これらのプロパティは、それぞれ異なる目的に対応します。
| プロパティ | 格納される内容 | 最適な用途 |
|---|---|---|
input | この実行のベース入力。ハンドオフ入力フィルターによって履歴が書き換えられた場合、実行の継続に使用されたフィルター済みの入力が反映されます。 | この実行で実際に使用された入力の監査 |
output | この実行で生成されたモデル形式の項目のみ。エージェントのメタデータは含まれません。 | 新しいモデル差分のみの保存または再生 |
newItems | エージェント、ツール、ハンドオフのメタデータを含む、詳細な RunItem ラッパー。 | ログ、UI、監査、デバッグ |
history | input + newItems から構築された、再生可能な次ターンの入力。 | 手動のチャットループとクライアント管理の会話状態 |
実際には、次のように使い分けます。
- アプリケーション内で会話全体を手動で保持する場合は、
historyを使用します。 - 以前の履歴を別の場所に保存しており、この実行で新しく生成された項目のみが必要な場合は、
outputを使用します。 - エージェントとの関連付け、ツール出力、ハンドオフ境界、承認項目が必要な場合は、
newItemsを使用します。 conversationIdまたはpreviousResponseIdを使用している場合、通常はhistoryをrun()に戻して渡しません。代わりに、新しいユーザー入力のみを渡し、サーバー管理の 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 を使用すると、実行中に起きたことを最も詳細に確認できます。一般的な項目型は次のとおりです。
- アシスタントメッセージを表す
RunMessageOutputItem - 実行の再開時に
RunState.pendingInputから取り込まれた入力を表すRunInputItem - 推論項目を表す
RunReasoningItem - Responses のツール検索リクエストと、それによって返された読み込み済みのツール定義を表す
RunToolSearchCallItemおよびRunToolSearchOutputItem - ツール呼び出しとその実行結果を表す
RunToolCallItemおよびRunToolCallOutputItem - 承認待ちで一時停止したツール呼び出しを表す
RunToolApprovalItem - ハンドオフリクエストと完了した移管を表す
RunHandoffCallItemおよびRunHandoffOutputItem
項目を生成したエージェントを把握する必要がある場合や、その項目がツール、ツール検索、ハンドオフ、承認の境界を示すかどうかを確認する必要がある場合は、output ではなく newItems を使用してください。toolSearchTool() を使用する場合、通常のツール呼び出しが行われる前に、どの遅延読み込みツールや名前空間が読み込まれたかを確認するには、これらのツール検索項目が最も簡単な方法です。
ローカルツールまたは MCP サーバーで customDataExtractor が定義されている場合、対応する RunToolCallOutputItem.customData には、返された SDK 専用のメタデータが格納されます。このデータは、レンダラーのヒントや内部 ID など、アプリケーションの UI 状態に役立ちます。このデータは RunState のシリアライズ後も保持されますが、history からは除外され、モデルには返送されません。
RunToolCallOutputItem.output は、SDK 側のツール戻り値です。JSON 互換のプリミティブ値、配列、プレーンオブジェクトは、RunState のシリアライズ後も構造が維持されます。その他の実行時値では、既存の文字列フォールバックが維持されます。このラッパー値は、history と再生で使用されるモデル可視のツール出力である rawItem.output とは分離されたままです。
会話の継続と再開
Section titled “会話の継続と再開”アクティブなエージェント
Section titled “アクティブなエージェント”lastAgent プロパティには、最後に実行されたエージェントが格納されます。多くの場合、ハンドオフ後の次のユーザーターンで再利用するエージェントとして最適です。activeAgent は同じ値のエイリアスです。
ストリーミングモードでは、実行が進行中の間、currentAgent によって現在アクティブなエージェントを確認できます。
割り込みと再開可能な状態
Section titled “割り込みと再開可能な状態”ツールで承認が必要になると、実行が一時停止し、interruptions に保留中の RunToolApprovalItem が格納されます。ここには、直接使用されたツール、ハンドオフ後に到達したツール、またはネストされた agent.asTool() の実行によって発生した承認を含めることができます。
result.state.approve(...) / result.state.reject(...) を通じて承認を処理し、同じ state を run() に戻して渡すことで再開します。すべての割り込みを一度に処理する必要はありません。一部の項目のみを処理して再実行した場合、処理済みの呼び出しは継続できますが、未処理の呼び出しは保留状態のままとなり、実行が再び一時停止します。
state プロパティは、実行結果の基盤となるシリアライズ可能なスナップショットです。人間の介入(HITL)、再試行フロー、または一時停止した実行を後で再開する必要がある場合に使用します。
サーバー管理による継続
Section titled “サーバー管理による継続”lastResponseId は、OpenAI Responses API の連結を使用する場合に、次のターンで previousResponseId として渡す値です。
すでに history、session、または conversationId を使用して会話を継続している場合、通常は lastResponseId は必要ありません。複数ステップの実行に含まれるすべての元のモデルレスポンスが必要な場合は、代わりに rawResponses を確認してください。
ネストされたエージェントツールのメタデータ
Section titled “ネストされたエージェントツールのメタデータ”agentToolInvocation は、ネストされた Agent.asTool() の実行結果向けです。特に、customOutputExtractor 内で現在のツール呼び出しに関するメタデータが必要な場合に使用します。実行全体が完了したことを示す一般的なサマリーフィールドではありません。
このネストされたコンテキストでは、agentToolInvocation から次の情報を取得できます。
toolNametoolCallIdtoolArguments
ネストされたエージェントツールの実行に渡された構造化入力も必要な場合は、result.runContext.toolInput と組み合わせて使用します。
通常のトップレベルの run() の実行結果では、通常これは undefined です。このメタデータは実行時専用であり、RunState にはシリアライズされません。関連するパターンについては、Agents as toolsを参照してください。
ストリーミング実行結果
Section titled “ストリーミング実行結果”StreamedRunResult は上記と同じ実行結果サーフェスを継承し、さらにストリーミング固有の制御機能を追加します。
- アシスタントのテキストのみを取得する
toTextStream() - 完全なイベントストリームを取得する
toStream()またはfor await ... of stream - 実行とすべての後処理コールバックが完了するまで待機する
completed - ストリーミングの終端状態を確認する
errorとcancelled - 実行中のアクティブなエージェントを追跡する
currentAgent - 実際にリクエスト境界へ到達したモデルターン数を確認する
currentTurn - このストリーミング実行に適用された上限を確認する
maxTurns(nullは上限なしを意味します)
currentTurn は、モデルリクエストが受け付けられた場合にのみ増加します。リクエストを阻止する最大ターン数チェックやブロッキング入力ガードレールでは増加せず、再開された実行は RunState に保持されているカウントから開始します。
ストリーミング実行の確定した最終状態が必要な場合は、finalOutput、history、interruptions、その他のサマリープロパティを読み取る前に completed を待機してください。イベント単位の処理については、ストリーミングを参照してください。
ストリーミング実行がキャンセルされた場合でも、クリーンアップ後に completed は解決され、cancelled は true になります。ただし、現在のターンが完了していないため、finalOutput などのターン終了時フィールドは未設定のままになることがあります。新しいユーザーメッセージを追加するのではなく、result.state(session を使用している場合は同じ session も)を使って未完了のターンを再開してください。
診断と高度なフィールド
Section titled “診断と高度なフィールド”実行コンテキスト
Section titled “実行コンテキスト”runContext プロパティは、実行結果に含まれる実行コンテキストについて、サポートされている公開ビューです。result.runContext.context はアプリケーションコンテキストであり、同じオブジェクトには、承認、使用量、ネストされた toolInput など、SDK が管理する実行時メタデータも格納されます。完全な構造については、コンテキスト管理を参照してください。
元のレスポンス
Section titled “元のレスポンス”rawResponses には、実行中に収集された元のモデルレスポンスが格納されます。複数ステップの実行では、ハンドオフやツールとモデルの反復サイクルなどにより、複数のレスポンスが生成されることがあります。
出力ガードレールが終端関数ツールの実行結果を拒否した場合、SDK は rawResponses 内の現在のレスポンスを、SDK が管理するほかの再生用サーフェスとともにサニタイズします。このプロパティを通じて、拒否された終端ツール出力を引き続き確認できるとは限りません。秘匿化の境界と制限については、拒否された終端ツール出力を参照してください。
各レスポンスには、利用可能な場合、プロバイダーのリクエスト識別子である requestId が含まれることもあります。OpenAI Responses および Chat Completions モデルでは、ストリーミングと非ストリーミングの HTTP リクエストの両方にこの値が設定されます。一部のプロバイダーやトランスポートでは公開されないため、オプションとして扱ってください。
Chat Completions のテキスト出力では、正規化された output_text パートの providerData.annotations を確認して URL 引用を読み取ります。非ストリーミングレスポンスでは、プロバイダーのメッセージ注釈が保持されます。ストリーミングレスポンスでは、テキストとともに受信した有効な url_citation 注釈が保持され、重複する引用は除去され、不正な形式やサポートされていない形式の注釈は無視されます。
Chat Completions の音声では、正規化されたモデルレスポンスは、audio コンテンツパートを持つ音声のみのアシスタントメッセージとして表現されます。そのメッセージが実行項目になると、RunMessageOutputItem.rawItem で同じパートを確認できます。非ストリーミングレスポンスに音声とともにテキストまたは拒否が含まれる場合、正規化されたアシスタントメッセージではテキストまたは拒否が保持され、完全なプロバイダーレスポンスは引き続き rawResponses[].providerData で確認できます。ストリーミングの混合出力で、受信時のプロバイダー音声チャンクが必要な場合は、元のモデルストリームイベントを確認してください。完了した rawResponses エントリーには正規化されたテキストまたは拒否が含まれますが、再構築された音声は含まれません。ストリーミングの toTextStream() ヘルパーはテキストのみを出力します。
modelSettings.preserveRawUsage が true の場合、完了した各レスポンスで rawUsage も公開できます。これは、SDK による正規化の前に取得された、分離された JSON 互換のスナップショットです。正規化された Usage は引き続き response.usage で利用できます。rawUsage では、プロバイダー固有のフィールド名と、提供されている場合は値が省略された場合と明示された場合の違いが保持されます。プロバイダーが使用量を省略した場合や、ペイロードを安全にコピーできない場合は、undefined になることがあります。rawUsage は実行時専用であり、シリアライズされた RunState から意図的に除外されます。そのため、実行を永続化して再開する前に、必要なフィールドをコピーしてください。
ガードレールの実行結果
Section titled “ガードレールの実行結果”inputGuardrailResults プロパティと outputGuardrailResults プロパティには、エージェントレベルのガードレール実行結果が格納されます。ツールのガードレール実行結果は、toolInputGuardrailResults と toolOutputGuardrailResults を通じて個別に公開されます。
ガードレールの判定をログに記録する場合、ガードレール関数から返された追加のメタデータを確認する場合、または実行がブロックされた理由をデバッグする場合に、これらの配列を使用します。
終端関数ツールの実行結果が拒否された場合、SDK は現在のレスポンスに含まれるガードレールのメタデータを意図的にサニタイズします。outputGuardrailResults では、agentOutput が Output withheld by an output guardrail. になり、outputInfo は削除されます。現在の toolOutputGuardrailResults では判定結果は保持されますが、outputInfo は省略されます。また、rejectContent の実行結果では、メッセージとして同じプレースホルダーが使用されます。以前に受け入れられた過去の実行結果は変更されません。
あるガードレールの実行に失敗しても、正常に完了したほかのガードレールの実行結果は実行状態に保持されます。ストリーミング実行では、completed が reject された後に実行結果の配列を確認してください。非ストリーミング実行では、GuardrailExecutionError に同じ確定済みの state が含まれます。
トークン使用量は result.state.usage に集約され、実行のリクエスト数とトークン合計が追跡されます。同じ使用量オブジェクトは result.runContext.usage からも利用できます。ストリーミング実行では、レスポンスの到着に応じてこのデータが更新されます。
完了したストリーミングまたは非ストリーミングの Chat Completions 呼び出しは、プロバイダーが使用量オブジェクトを省略した場合でも、1 件のリクエストとしてカウントされます。その場合、プロバイダーから報告されていないため、トークン合計は 0 のままです。
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, }); }}