コンテンツにスキップ

エージェントメモリ

メモリを使うと、以後の sandbox-agent の実行で過去の実行から学習できます。これは、メッセージ履歴を保存する SDK の会話用 セッション メモリとは別です。メモリは過去の実行から得た知見をサンドボックスワークスペース内のファイルに要約して保存するため、生成されたメモリアーティファクトは保持データとして扱い、ワークスペースに適用しているものと同じ機密性と保持ポリシーを適用してください。

メモリは、将来の実行における 3 種類のコストを削減できます。

  1. エージェントのコスト: エージェントがワークフローの完了に長い時間を要した場合、次回の実行では探索を減らせるはずです。これにより、トークン使用量と完了までの時間を削減できます。
  2. ユーザーのコスト: ユーザーがエージェントを修正したり好みを伝えたりした場合、将来の実行でそのフィードバックを記憶できます。これにより、人間の介入を減らせます。
  3. コンテキストのコスト: エージェントが以前にタスクを完了していて、ユーザーがそのタスクを土台にしたい場合、ユーザーは以前のスレッドを探したり、すべてのコンテキストを再入力したりする必要がなくなります。これにより、タスク記述を短くできます。

サンドボックスエージェントに、capability として memory() を追加します。

Enable memory
import {
filesystem,
Manifest,
memory,
SandboxAgent,
shell,
} from '@openai/agents/sandbox';
const manifest = new Manifest({
entries: {
'README.md': {
type: 'file',
content: '# Memory demo\n\nA workspace for follow-up runs.\n',
},
},
});
const agent = new SandboxAgent({
name: 'Memory-enabled reviewer',
model: 'gpt-5.5',
instructions:
'Inspect the workspace, verify important claims, and preserve useful lessons for follow-up runs.',
defaultManifest: manifest,
capabilities: [filesystem(), shell(), memory()],
});

読み取りが有効な場合、memory() には shell() が必要です。これにより、注入された要約だけでは不十分なときに、エージェントがメモリファイルを読み取って検索できます。ライブメモリ更新がデフォルトで有効な場合は、filesystem() も必要です。これにより、エージェントが古いメモリを見つけた場合や、ユーザーがメモリの更新を求めた場合に、memories/MEMORY.md を更新できます。

デフォルトでは、メモリアーティファクトはサンドボックスワークスペース内の memories/ に保存されます。後続の実行で再利用するには、同じライブサンドボックスセッションを維持するか、永続化したセッション状態またはスナップショットから再開することで、設定された memories ディレクトリー全体を保持して再利用してください。新しい空のサンドボックスは、空のメモリから開始します。

memory() は、メモリの読み取りと生成の両方を有効にします。メモリは読み取るが新しいメモリは生成すべきでないエージェントには memory({ generate: false }) を使用します。たとえば、内部エージェント、サブエージェント、チェッカー、または実行による有用なシグナルがあまり増えない単発のツールエージェントです。実行で後のためにメモリは生成したいが、既存のメモリの影響は受けたくない場合は、memory({ read: null }) を使用します。

読み取り専用メモリの設定
import { memory } from '@openai/agents/sandbox';
const readOnlyMemory = memory({
read: { liveUpdate: false },
generate: false,
});

メモリの読み取りでは段階的開示を使用します。実行開始時に、SDK は一般的に有用なヒント、ユーザー設定、利用可能なメモリをまとめた小さな要約 (memory_summary.md) を、エージェントの developer prompt に注入します。これにより、過去の作業が関係しそうかどうかを判断するための十分なコンテキストをエージェントに与えます。

過去の作業が関連しそうな場合、エージェントは現在のタスクのキーワードを使って、設定済みのメモリインデックス( memoriesDir 配下の MEMORY.md )を検索します。さらに詳細が必要な場合にのみ、設定された rollout_summaries/ ディレクトリー配下の対応する過去のロールアウト要約を開きます。

メモリは古くなることがあります。エージェントには、メモリはあくまで参考情報として扱い、現在の環境を信頼するよう指示されています。デフォルトでは、メモリ読み取りで liveUpdate が有効になっているため、エージェントが古いメモリを見つけた場合、同じ実行内で設定済みの MEMORY.md を更新できます。たとえば実行がレイテンシーに敏感である場合など、メモリは読み取るが実行中には変更させたくないときは、ライブ更新を無効にします。

実行が終了すると、サンドボックスランタイムはその実行セグメントを会話ファイルに追記します。蓄積された会話ファイルは、サンドボックスセッションが閉じられたときに処理されます。これらの会話ファイルには、ユーザー入力、assistant と tool の項目、中断、最終出力が含まれることがあるため、機密性の高いワークロードには適切なメモリストアと保持ポリシーを使用してください。

メモリ生成には 2 つのフェーズがあります。

  1. フェーズ 1: 会話抽出。メモリ生成モデルが 1 つの蓄積された会話ファイルを処理し、会話要約を生成します。system、developer、reasoning の内容は除外されます。会話が長すぎる場合は、先頭と末尾を保持したまま、コンテキストウィンドウに収まるよう切り詰められます。また、フェーズ 2 で統合できるよう、会話からの簡潔なメモである元のメモリ抽出も生成します。
  2. フェーズ 2: レイアウト統合。統合エージェントが、ある 1 つのメモリレイアウトに対する元のメモリを読み取り、より多くの根拠が必要な場合に会話要約を開き、MEMORY.mdmemory_summary.md にパターンを抽出します。

デフォルトのワークスペースレイアウトは次のとおりです。

workspace/
├── sessions/
│ └── <rollout-id>.jsonl
└── memories/
├── memory_summary.md
├── MEMORY.md
├── raw_memories.md
├── raw_memories/
└── rollout_summaries/

memory({ generate: ... }) を使ってメモリ生成を設定できます。

メモリ生成の設定
import { memory } from '@openai/agents/sandbox';
const memoryCapability = memory({
generate: {
maxRawMemoriesForConsolidation: 128,
phaseOneModel: 'gpt-5.4-mini',
phaseTwoModel: 'gpt-5.4',
extraPrompt:
'Prioritize workflow corrections, verification commands, and user preferences.',
},
});

extraPrompt を使うと、たとえば GTM エージェント向けの顧客情報や企業情報など、ユースケースでどのシグナルを最も重視すべきかをメモリ生成器に伝えられます。

最近の元のメモリが maxRawMemoriesForConsolidation を超える場合、フェーズ 2 は新しい会話のメモリだけを残し、古いものを削除します。新しさは、その会話が最後に更新された時点に基づきます。この忘却メカニズムにより、メモリを最新の環境に即した状態に保てます。

複数ターンのサンドボックスチャットでは、同じライブサンドボックスセッションと一緒に通常の SDK Session を使用します。

1 つの SDK セッションと 1 つのサンドボックスセッションを使用
import { MemorySession, run } from '@openai/agents';
import {
filesystem,
Manifest,
memory,
SandboxAgent,
shell,
} from '@openai/agents/sandbox';
import { UnixLocalSandboxClient } from '@openai/agents/sandbox/local';
const manifest = new Manifest();
const agent = new SandboxAgent({
name: 'Memory-enabled reviewer',
model: 'gpt-5.5',
instructions: 'Inspect the workspace before answering.',
capabilities: [filesystem(), shell(), memory()],
});
const conversation = new MemorySession({ sessionId: 'workspace-review' });
const sandbox = await new UnixLocalSandboxClient().create({ manifest });
try {
await run(agent, 'Analyze data/leads.csv.', {
session: conversation,
sandbox: { session: sandbox },
});
await run(agent, 'Write a follow-up recommendation.', {
session: conversation,
sandbox: { session: sandbox },
});
} finally {
await sandbox.close?.();
}

どちらの実行も 1 つのメモリ会話ファイルに追記されます。これは、同じ SDK 会話セッションを渡しており、同じセッション ID を共有するためです。これはサンドボックスとは異なります。サンドボックスはライブワークスペースを識別しますが、メモリ会話 ID としては使われません。フェーズ 1 はサンドボックスセッションが閉じられたときに蓄積された会話を参照するため、分離された 2 つのターンではなく、やり取り全体からメモリを抽出できます。

複数の run(...) 呼び出しを 1 つのメモリ会話にしたい場合は、それらの呼び出しにまたがって安定した識別子を渡してください。メモリが実行を会話に関連付ける際の解決順は次のとおりです。

  1. run(...) に渡した conversationId
  2. SDK Session を渡した場合の SDK session ID
  3. 上記のどちらもない場合の groupId
  4. 安定した識別子が存在しない場合の、実行ごとに生成される ID

異なるエージェントのメモリを分離するための別レイアウトの使用

Section titled “異なるエージェントのメモリを分離するための別レイアウトの使用”

メモリの分離は、エージェント名ではなく MemoryLayoutConfig に基づきます。同じレイアウトと同じメモリ会話 ID を持つエージェントは、1 つのメモリ会話と 1 つの統合メモリを共有します。異なるレイアウトを持つエージェントは、同じサンドボックスワークスペースを共有していても、別々のロールアウトファイル、元のメモリ、MEMORY.mdmemory_summary.md を保持します。

複数のエージェントが 1 つのサンドボックスを共有していても、メモリを共有すべきでない場合は、別々のレイアウトを使用します。

別々のメモリレイアウトを使用
import { memory } from '@openai/agents/sandbox';
const engineeringMemory = memory({
layout: {
memoriesDir: 'memories/engineering',
sessionsDir: 'sessions/engineering',
},
});
const financeMemory = memory({
layout: {
memoriesDir: 'memories/finance',
sessionsDir: 'sessions/finance',
},
});

これにより、あるドメインの分析結果が別のドメインのメモリに統合されること、またその逆を防げます。