コンテンツにスキップ

エージェントの実行

エージェントはそれだけでは何もしません。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. maxTurns に達したら、maxTurnsnull でない限り、MaxTurnsExceededError をスローします。

アプリの起動時に Runner を作成し、リクエスト間で再利用してください。このインスタンスは、モデルプロバイダーやトレーシングオプションなどのグローバル設定を保持します。完全に異なるセットアップが必要な場合にのみ、別の Runner を作成してください。シンプルなスクリプトでは、内部でデフォルトランナーを使用する run() を呼び出すこともできます。

run() メソッドへの入力は、実行を開始する初期エージェント、実行の入力、およびオプションセットです。

入力は、文字列(ユーザーメッセージと見なされます)、入力アイテム のリスト、または 人間の介入(HITL) エージェントを構築している場合は RunState オブジェクトのいずれかです。

追加のオプションは次のとおりです。

オプションデフォルト説明
streamfalsetrue の場合、呼び出しは StreamedRunResult を返し、モデルから届いたイベントを順次発行します。
contextすべてのツール / ガードレール / ハンドオフに転送されるコンテキストオブジェクトです。詳しくは コンテキスト管理 を参照してください。
maxTurns10安全上の制限です。到達すると MaxTurnsExceededError をスローします。制限を無効化するには null を渡します。
signalキャンセル用の AbortSignal
sessionセッション永続化の実装です。セッション を参照してください。
sessionInputCallbackセッション履歴と新しい入力のためのカスタムマージロジックです。モデル呼び出しの前に実行されます。セッション を参照してください。
callModelInputFilterモデルを呼び出す直前に、モデル入力(アイテム + オプションの instructions)を編集するフックです。モデル呼び出し入力フィルター を参照してください。
toolErrorFormatterモデルに返されるツール承認の拒否メッセージをカスタマイズするフックです。ツールエラーフォーマッター を参照してください。
reasoningItemIdPolicyreasoning-item の id を、以前の実行アイテムがモデル入力に戻されるときに保持するか省略するかを制御します。Reasoning item ID ポリシー を参照してください。
tracing実行ごとのトレーシング設定の上書き(例:エクスポート API キー)
sandboxSandboxAgent 実行のサンドボックスクライアント、ライブセッション、セッション状態、スナップショット、マニフェスト上書き、または同時実行数制限です。コンセプト を参照してください。
toolExecutionローカルツール呼び出しの SDK 側実行設定です。toolExecution.maxFunctionToolConcurrency を使用して同時に実行される関数ツールの数を制限し、toolExecution.preApprovalInputGuardrails を使用して保留中の承認リクエストの前に関数ツール入力ガードレールを実行します。
errorHandlersサポートされるランタイムエラー(現在は maxTurns)のハンドラーです。エラーハンドラー を参照してください。
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 / ツールの入力と出力をトレースから除外します。
workflowNamestringTraces ダッシュボードに表示され、関連する実行をグループ化するのに役立ちます。
traceId / groupIdstringSDK に生成させる代わりに、トレース ID またはグループ ID を手動で指定します。
traceMetadataRecord<string, string>すべてのスパンに付与する任意のメタデータです。
tracingTracingConfig実行ごとのトレーシング上書き(例:エクスポート API キー)
sessionInputCallbackSessionInputCallbackこのランナー上のすべての実行に対するデフォルトの履歴マージ戦略です。
callModelInputFilterCallModelInputFilter各モデル呼び出しの前にモデル入力を編集するグローバルフックです。
toolErrorFormatterToolErrorFormatterモデルに返されるツール承認の拒否メッセージをカスタマイズするグローバルフックです。
reasoningItemIdPolicyReasoningItemIdPolicy生成済みアイテムを後続のモデル呼び出しに再生するときに、reasoning item の id を保持するか省略するかのデフォルトポリシーです。
sandboxSandboxRunConfigSandboxAgent 実行用のデフォルトサンドボックスランタイム設定です。
toolExecutionToolExecutionConfigローカルツール呼び出しのデフォルト SDK 側実行設定です。maxFunctionToolConcurrency は各ターンのローカル関数ツールの同時実行数に上限を設けます。未設定または null の場合、1 ターンで発行されたすべての関数ツール呼び出しを開始します。preApprovalInputGuardrails は、保留中の承認リクエストの前に関数ツール入力ガードレールを実行することを有効化します。

toolExecution.maxFunctionToolConcurrency1 以上の整数である必要があります。この設定は、ローカル関数ツールの SDK 側実行のみを制限します。プロバイダー側の modelSettings.parallelToolCalls は変更しません。

toolExecution.preApprovalInputGuardrails はデフォルトで無効です。true に設定すると、承認が必要なローカル関数ツールは、SDK が保留中の承認割り込みを記録する前に入力ガードレールを実行します。ガードレールが rejectContent を返した場合、SDK は承認を求める代わりに、その拒否メッセージをツール出力として送り返します。ガードレールが呼び出しを許可した場合でも、承認リクエストは発生し、承認が解決された後のツール実行直前に同じ入力ガードレールが再度実行されます。

次のターンに状態を持ち越す一般的な方法は 4 つあります。

戦略状態の保存場所最適な用途次のターンで渡すもの
result.historyアプリのメモリ小規模なチャットループ、完全な手動制御、任意のプロバイダーresult.history
sessionストレージ + SDK永続的なチャット状態、再開可能な実行、カスタムストア同じ session インスタンス(またはストアに裏付けられたもの)
conversationIdOpenAI Conversations APIワーカー / サービス間で共有されるサーバー側状態同じ conversationId と、新しいユーザーターンのみ
previousResponseIdOpenAI Responses API のみ会話を作成せずに行う最もシンプルなサーバー管理の継続result.lastResponseId と、新しいユーザーターンのみ

result.historysession はクライアント管理です。conversationIdpreviousResponseId は OpenAI 管理であり、OpenAI Responses API を使用している場合にのみ適用されます。ほとんどのアプリケーションでは、会話ごとに 1 つの永続化戦略を選びます。両方のレイヤーを意図的に照合している場合を除き、クライアント管理の履歴とサーバー管理の状態を混在させると、コンテキストが重複する可能性があります。

サンドボックスエージェントは、別の状態レイヤーであるライブサンドボックスワークスペースを追加します。会話履歴には通常の SDK sessionconversationId、または previousResponseId を使用し、サンドボックスのファイルシステム状態には sandbox.sessionsandbox.sessionStateRunState、またはスナップショットを使用します。ワークスペースのライフサイクルについては コンセプト を参照してください。

runner.run()(または run() ユーティリティ)の各呼び出しは、アプリケーションレベルの会話における 1 つの ターン を表します。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 はサーバー側状態を再利用する 2 つの方法を提供しています。

1. 会話全体に対する conversationId
Section titled “1. 会話全体に対する conversationId”

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
Section titled “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 を使用します。

モデル呼び出し入力フィルター

Section titled “モデル呼び出し入力フィルター”

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. にフォールバックします。

現在、フォーマッターは approval_rejected イベントで実行され、次を受け取ります。

  • kind(現在は常に 'approval_rejected'
  • toolType'function''computer''shell'、または 'apply_patch'
  • toolName
  • callId
  • defaultMessage(SDK のフォールバックメッセージ。現在は Tool execution was not approved.
  • runContext

メッセージを上書きするには文字列を返し、SDK デフォルトを維持するには undefined を返します。フォーマッターが例外をスローした場合(または文字列以外の値を返した場合)、SDK は警告をログに記録し、デフォルトの承認拒否メッセージにフォールバックします。

reasoningItemIdPolicy を使用して、SDK が以前に生成された実行アイテムを後続のモデル入力用の AgentInputItem[] に変換するとき、reasoning items が id フィールドを保持するかどうかを制御します。

これは、SDK が生成済みモデルアイテムを入力として再生する箇所に影響します。例:

  • 同じ実行内の後続モデル呼び出し(例:ツール実行後)
  • 生成済みアイテムを入力 / 履歴として再利用する後続ターン
  • 保存済みの RunState から再開された実行
  • result.history / result.output のような派生結果ビュー(モデル入力の形をした配列)
  • 'preserve'(デフォルト)は reasoning-item ID を保持します。
  • 'omit' は reasoning items から id フィールドを削除してから入力として送り返します。
  • reasoning 以外のアイテムには影響しません。

これによって 変更されない もの:

  • 元のモデルレスポンス(result.rawResponses
  • 実行アイテム(result.newItems
  • プロバイダーから返されるモデルの現在のターンの出力

つまり、このポリシーは SDK が以前に生成されたアイテムから 次の入力 を構築するときに適用されます。

ポリシーは、実行ごと(runner.run(..., { reasoningItemIdPolicy: 'omit' }))またはランナーのデフォルト(new Runner({ reasoningItemIdPolicy: 'omit', ... }))として設定できます。保存済みの RunState から再開する場合、上書きしない限り、以前に解決されたポリシーが再利用されます。

reasoningItemIdPolicycallModelInputFilter の前に適用されます。カスタム動作が必要な場合でも、callModelInputFilter で準備済み入力を調べ、モデル呼び出しの前に reasoning ID を手動で再導入または削除できます。

'omit' は、再生される reasoning items を ID なしで正規化したい場合(例:転送 / 再生されるモデル入力をよりシンプルに保つ、またはアプリのパイプラインの統合要件に合わせる場合)に使用します。

バックエンド / プロバイダーが、リクエスト検証エラー(例:後続入力の reasoning item ID に関連する HTTP 400 エラー)で再生された reasoning items を拒否する場合のトラブルシューティングオプションとしても有用です。そのような場合、'omit' で再生された reasoning ID を削除すると、新しいリクエストに対してバックエンドが無効と見なす ID の送信を避けられます。

SDK に再生入力を通じて reasoning-item ID を持ち越してほしく、かつ統合先がそれを受け付ける場合は、'preserve' のままにします。

errorHandlers を使用すると、サポートされるランタイムエラーをスローする代わりに最終出力に変換できます。サポートされるキーは maxTurnsmodelRefusal です。

  • errorHandlers.maxTurns は最大ターンエラーのみを処理します。
  • errorHandlers.modelRefusalModelRefusalError として表面化したモデル拒否を処理します。
  • errorHandlers.default はサポートされる種類のフォールバックとして使用されます。
  • ハンドラーは { error, context, runData } を受け取り、{ finalOutput, includeInHistory? } を返せます。

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