セッション
セッションは Agents SDK による永続的なメモリ層です。Session インターフェースを実装した任意のオブジェクトを Runner.run に渡すだけで、残りは SDK が処理します。セッションがある場合、ランナーは自動的に以下を行います。
- 以前に保存された会話アイテムを取得し、次のターンの先頭に付与
- 各実行完了後に、新しい user 入力と assistant 出力を永続化
- 新しい user テキストでランナーを呼び出す場合も、中断された
RunStateから再開する場合も、将来のターンに備えてセッションを利用可能な状態に保持
これにより、手動で toInputList() を呼び出したり、ターン間で履歴をつなぎ合わせる必要がなくなります。TypeScript SDK には 2 つの実装が同梱されています。Conversations API 用の OpenAIConversationsSession と、ローカル開発向けの MemorySession です。どちらも Session インターフェースを共有しているため、独自のストレージバックエンドを差し替えられます。Conversations API 以外の例としては、examples/memory/ 配下のサンプルセッションバックエンド(Prisma、ファイルバックなど)をご覧ください。OpenAI Responses モデルを使う場合は、任意のセッションを OpenAIResponsesCompactionSession でラップし、responses.compact によって保存済みのトランスクリプトを自動的に縮小できます。
ヒント: このページの
OpenAIConversationsSessionの例を実行するには、OPENAI_API_KEY環境変数を設定する(またはセッションの構築時にapiKeyを指定する)ことで、SDK が Conversations API を呼び出せるようにしてください。
クイックスタート
Section titled “クイックスタート”OpenAIConversationsSession を使って Conversations API とメモリを同期するか、他の任意の Session 実装に差し替えます。
import { Agent, OpenAIConversationsSession, run } from '@openai/agents';
const agent = new Agent({ name: 'TourGuide', instructions: 'Answer with compact travel facts.',});
// Any object that implements the Session interface works here. This example uses// the built-in OpenAIConversationsSession, but you can swap in a custom Session.const session = new OpenAIConversationsSession();
const firstTurn = await run(agent, 'What city is the Golden Gate Bridge in?', { session,});console.log(firstTurn.finalOutput); // "San Francisco"
const secondTurn = await run(agent, 'What state is it in?', { session });console.log(secondTurn.finalOutput); // "California"同じセッションインスタンスを再利用すると、各ターンの前にエージェントが完全な会話履歴を受け取り、新しいアイテムも自動で永続化されます。別の Session 実装へ切り替えても、他のコード変更は不要です。
Runner によるセッションの利用
Section titled “Runner によるセッションの利用”- 各実行の前 にセッション履歴を取得し、新しいターンの入力とマージして、結合済みリストをエージェントに渡します
- 非ストリーミング実行の後 は、1 回の
session.addItems()呼び出しで、直近ターンの元の user 入力とモデル出力の両方を永続化します - ストリーミング実行の場合 は、まず user 入力を書き込み、ターン完了後にストリーム出力を追記します
RunResult.stateから再開する場合(承認などで中断されたケース)も、同じsessionを渡し続けます。再開したターンは入力を再準備せずにメモリへ追加されます
履歴の確認と編集
Section titled “履歴の確認と編集”セッションはシンプルな CRUD ヘルパーを公開しているため、「取り消し」「チャットのクリア」や監査機能を実装できます。
import { OpenAIConversationsSession } from '@openai/agents';import type { AgentInputItem } from '@openai/agents-core';
// Replace OpenAIConversationsSession with any other Session implementation that// supports get/add/pop/clear if you store history elsewhere.const session = new OpenAIConversationsSession({ conversationId: 'conv_123', // Resume an existing conversation if you have one.});
const history = await session.getItems();console.log(`Loaded ${history.length} prior items.`);
const followUp: AgentInputItem[] = [ { type: 'message', role: 'user', content: [{ type: 'input_text', text: 'Let’s continue later.' }], },];await session.addItems(followUp);
const undone = await session.popItem();
if (undone?.type === 'message') { console.log(undone.role); // "user"}
await session.clearSession();session.getItems() は保存された AgentInputItem[] を返します。popItem() を呼ぶと最後のエントリを削除できます。エージェントを再実行する前の user の修正に便利です。
独自ストレージの利用
Section titled “独自ストレージの利用”Session インターフェースを実装して、Redis、DynamoDB、SQLite、その他のデータストアでメモリを裏付けます。必要なのは 5 つの非同期メソッドだけです。
import { Agent, run } from '@openai/agents';import { randomUUID } from '@openai/agents-core/_shims';import { logger, Logger } from '@openai/agents-core/dist/logger';import type { AgentInputItem, Session } from '@openai/agents-core';
/** * Minimal example of a Session implementation; swap this class for any storage-backed version. */export class CustomMemorySession implements Session { private readonly sessionId: string; private readonly logger: Logger;
private items: AgentInputItem[];
constructor( options: { sessionId?: string; initialItems?: AgentInputItem[]; logger?: Logger; } = {}, ) { this.sessionId = options.sessionId ?? randomUUID(); this.items = options.initialItems ? options.initialItems.map(cloneAgentItem) : []; this.logger = options.logger ?? logger; }
async getSessionId(): Promise<string> { return this.sessionId; }
async getItems(limit?: number): Promise<AgentInputItem[]> { if (limit === undefined) { const cloned = this.items.map(cloneAgentItem); this.logger.debug( `Getting items from memory session (${this.sessionId}): ${JSON.stringify(cloned)}`, ); return cloned; } if (limit <= 0) { return []; } const start = Math.max(this.items.length - limit, 0); const items = this.items.slice(start).map(cloneAgentItem); this.logger.debug( `Getting items from memory session (${this.sessionId}): ${JSON.stringify(items)}`, ); return items; }
async addItems(items: AgentInputItem[]): Promise<void> { if (items.length === 0) { return; } const cloned = items.map(cloneAgentItem); this.logger.debug( `Adding items to memory session (${this.sessionId}): ${JSON.stringify(cloned)}`, ); this.items = [...this.items, ...cloned]; }
async popItem(): Promise<AgentInputItem | undefined> { if (this.items.length === 0) { return undefined; } const item = this.items[this.items.length - 1]; const cloned = cloneAgentItem(item); this.logger.debug( `Popping item from memory session (${this.sessionId}): ${JSON.stringify(cloned)}`, ); this.items = this.items.slice(0, -1); return cloned; }
async clearSession(): Promise<void> { this.logger.debug(`Clearing memory session (${this.sessionId})`); this.items = []; }}
function cloneAgentItem<T extends AgentInputItem>(item: T): T { return structuredClone(item);}
const agent = new Agent({ name: 'MemoryDemo', instructions: 'Remember the running total.',});
// Using the above custom memory session implementation hereconst session = new CustomMemorySession({ sessionId: 'session-123-4567',});
const first = await run(agent, 'Add 3 to the total.', { session });console.log(first.finalOutput);
const second = await run(agent, 'Add 4 more.', { session });console.log(second.finalOutput);カスタムセッションにより、保持ポリシーの適用、暗号化の追加、または永続化前に各会話ターンへメタデータを付与できます。
履歴と新規アイテムの結合方法の制御
Section titled “履歴と新規アイテムの結合方法の制御”実行入力として AgentInputItem の配列を渡す場合、sessionInputCallback を指定して、保存済み履歴とのマージを決定的に制御します。ランナーは既存の履歴をロードし、モデル呼び出しの前に コールバックを呼び出し、返された配列をターンの完全な入力としてモデルに渡します。このフックは、古いアイテムの削除、ツール結果の重複排除、モデルに見せたいコンテキストだけを強調するのに最適です。
import { Agent, OpenAIConversationsSession, run } from '@openai/agents';import type { AgentInputItem } from '@openai/agents-core';
const agent = new Agent({ name: 'Planner', instructions: 'Track outstanding tasks before responding.',});
// Any Session implementation can be passed here; customize storage as needed.const session = new OpenAIConversationsSession();
const todoUpdate: AgentInputItem[] = [ { type: 'message', role: 'user', content: [ { type: 'input_text', text: 'Add booking a hotel to my todo list.' }, ], },];
await run(agent, todoUpdate, { session, // function that combines session history with new input items before the model call sessionInputCallback: (history, newItems) => { const recentHistory = history.slice(-8); return [...recentHistory, ...newItems]; },});文字列入力の場合はランナーが自動で履歴をマージするため、コールバックは任意です。
承認と再開可能な実行の取り扱い
Section titled “承認と再開可能な実行の取り扱い”Human in the loop(人間の介入)のフローでは、承認待ちで実行が一時停止することがあります。
const result = await runner.run(agent, 'Search the itinerary', { session, stream: true,});
if (result.requiresApproval) { // ... collect user feedback, then resume the agent in a later turn const continuation = await runner.run(agent, result.state, { session }); console.log(continuation.finalOutput);}以前の RunState から再開すると、新しいターンは同じメモリレコードに追記され、単一の会話履歴が保たれます。Human-in-the-loop (HITL) フローとの互換性は完全に維持され、承認チェックポイントは引き続き RunState を介して往復しつつ、セッションはトランスクリプトを完全な状態で保持します。
OpenAI Responses の履歴の自動圧縮
Section titled “OpenAI Responses の履歴の自動圧縮”OpenAIResponsesCompactionSession は任意の Session をデコレートし、OpenAI Responses API に依存してトランスクリプトを短く保ちます。各ターンの永続化後に、ランナーは最新の responseId を runCompaction に渡し、判断フックが true を返したときに responses.compact を呼び出します。デフォルトのトリガーは、少なくとも 10 個の user 以外のアイテムが蓄積された時点で圧縮します。shouldTriggerCompaction をオーバーライドして、トークン数や独自のヒューリスティクスに基づいて判断できます。デコレータは圧縮結果で基盤となるセッションをクリアして書き直すため、別の server 管理の履歴フローを使う OpenAIConversationsSession との併用は避けてください。
import { Agent, MemorySession, OpenAIResponsesCompactionSession, run,} from '@openai/agents';
const agent = new Agent({ name: 'Support', instructions: 'Answer briefly and keep track of prior context.', model: 'gpt-5.2',});
// Wrap any Session to trigger responses.compact once history grows beyond your threshold.const session = new OpenAIResponsesCompactionSession({ // You can pass any Session implementation except OpenAIConversationsSession underlyingSession: new MemorySession(), // (optional) The model used for calling responses.compact API model: 'gpt-5.2', // (optional) your custom logic here shouldTriggerCompaction: ({ compactionCandidateItems }) => { return compactionCandidateItems.length >= 12; },});
await run(agent, 'Summarize order #8472 in one sentence.', { session });await run(agent, 'Remind me of the shipping address.', { session });
// Compaction runs automatically after each persisted turn. You can also force it manually.await session.runCompaction({ force: true });アーカイブやハンドオフの前に履歴を縮小したいときは、いつでも runCompaction({ force: true }) を呼び出せます。圧縮の判断を追跡するには、DEBUG=openai-agents:openai:compaction を有効にしてください。