コンテンツにスキップ

セッション

セッションは Agents SDK による永続メモリ層です。Session インターフェースを実装した任意のオブジェクトを Runner.run に渡すだけで、残りは SDK が処理します。セッションがある場合、ランナーは自動的に次を行います。

  1. 以前に保存された会話アイテムを取得し、次のターンの先頭に付与
  2. 各実行完了後に新しい ユーザー入力とアシスタント出力を永続化
  3. 新しい ユーザー テキストでランナーを呼び出す場合も、中断された RunState から再開する場合も、将来のターンのためにセッションを維持

これにより、手動で toInputList() を呼び出したり、ターン間で履歴をつなぎ合わせる必要がなくなります。TypeScript SDK には 2 つの実装が付属します。Conversations API 用の OpenAIConversationsSession と、ローカル開発向けの MemorySession です。両者は Session インターフェースを共有しているため、独自のストレージ バックエンドを差し替えられます。Conversations API 以外の発想が必要な場合は、examples/memory/ 配下のサンプル セッション バックエンド(Prisma、ファイル バックエンドなど)を参照してください。

ヒント: このページの OpenAIConversationsSession の例を実行するには、OPENAI_API_KEY 環境変数を設定する(またはセッション構築時に apiKey を指定する)ことで、SDK が Conversations API を呼び出せるようにしてください。


OpenAIConversationsSession を使って Conversations API とメモリを同期するか、他の任意の Session 実装に差し替えます。

Conversations API をセッションメモリとして利用
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 実装への切り替えでも、その他のコード変更は不要です。


ランナーによるセッションの使用

Section titled “ランナーによるセッションの使用”
  • 各実行前 にセッションの履歴を取得し、新しいターンの入力とマージして、結合したリストをエージェントに渡します
  • 非ストリーミング実行後 は、1 回の session.addItems() 呼び出しで、直近のターンにおける元の ユーザー入力とモデル出力の両方を永続化します
  • ストリーミング実行の場合 は、まず ユーザー入力を書き込み、ターン完了時にストリーミング出力を追記します
  • RunResult.state からの再開時(承認やその他の中断)も、同じ session を渡し続けます。再開したターンは入力の再準備なくメモリに追加されます

セッションはシンプルな 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() を呼ぶと最後のエントリを削除できます。エージェントを再実行する前の ユーザー修正に便利です。


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 here
const 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 を指定して保存済み履歴とのマージを決定的に制御します。ランナーは既存履歴を読み込み、モデル呼び出し前に コールバックを呼び、返された配列をそのターンの完全な入力としてモデルに渡します。このフックは、古いアイテムのトリミング、ツール結果の重複排除、モデルに見せたいコンテキストのみを強調するのに最適です。

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 を往復しつつ、セッションが書き起こし全体を保持します。