Skip to main content
会話とセッション

メモリ

ネイティブメモリでターンやセッションをまたいで知識を引き継ぐ、または生成と読み込みをアプリケーション側で制御します。

メモリは、Agent が1つのセッションで得た知識を保持し、後のセッションで再利用できるようにします。プロジェクトのビルドコマンド、テストの構成、コード規約といった情報を、毎回ゼロから調べ直す必要がなくなります。 Qoder Agent SDK のメモリは生成と読み込みの2つの部分で構成され、それぞれ個別に設定できます。
構成要素役割実行タイミング
生成(Generation)Agent が得た知識をメモリファイルに書き込むターン完了後、バックグラウンドのメモリ Agent が実行
読み込み(Consumption)メモリファイルを Agent のコンテキストに読み込むセッション初期化時、および明示的な再読み込み時
対応言語:TypeScript のみ。memory オプションと flushMemory() / refreshMemory() の各メソッドは TypeScript SDK にのみ存在します。Python SDK に相当するオプションはないため、Python アプリケーションから SDK メモリの設定、スコープの選択、生成・読み込み結果の受信はできません。本ページの内容は TypeScript にのみ適用されます。

ネイティブメモリを有効にする

mode: 'native' は、すべての挙動をランタイムの既定動作に委ねます。まずはこの設定から始めることを推奨します。何を記録すべきか、どこに保存するか、いつ読み込むかをランタイムが判断します。
import { query } from '@qoder-ai/qoder-agent-sdk';

for await (const message of query({
  prompt: 'ヘルスチェック用のエンドポイントを追加し、テストを実行してください',
  options: {
    memory: { mode: 'native' },
  },
})) {
  console.log(message);
}
native モードで設定できるのは、2つのスコープスイッチと結果コールバックだけです。保存場所、生成プロンプト、読み込み予算などはランタイムが管理し、リリースごとに改善されます。

メモリのスコープを選ぶ

ネイティブメモリには2つのスコープがあり、既定ではどちらも有効です。
スコープルート id保持する内容
ユーザー単位user利用者に紐づき、プロジェクトをまたいで通用する知識
プロジェクト単位project現在の作業ディレクトリに固有の知識
Query ごとに片方を無効化できます。
// プロジェクト単位の知識のみを使い、ユーザー単位のメモリは読み書きしない
options: {
  memory: { mode: 'native', userScope: false },
}
native モードでは少なくとも1つのスコープが有効である必要があります。両方を無効にすると例外が発生します。
native mode requires at least one enabled scope; use memory: {} to disable SDK memory

メモリを無効にする

空のオブジェクトは明示的な無効化スイッチで、memory を渡さない場合と同じです。メモリ設定はランタイムに送信されません。
options: {
  memory: {},
}

生成と読み込みを上書きする

mode: 'custom' は明示的に指定した部分のみを上書きし、それ以外はランタイムの既定動作を継承します。メモリの保存場所、または何を記録対象とするかをアプリケーション側で決める場合に使用します。

書き込む内容を制御する

options: {
  memory: {
    mode: 'custom',
    generation: {
      roots: [
        { id: 'team', path: '/srv/knowledge/team', access: 'read' },
        { id: 'service', path: '/srv/knowledge/checkout', indexFile: 'INDEX.md' },
      ],
      prompt: 'デプロイ手順と障害の特徴のみを記録してください。',
    },
  },
}
各 root は、メモリ Agent がアクセスできるディレクトリに対応します。
フィールド既定値説明
idstringプロンプト、初期化、生成結果で使われる安定した識別子
pathstringQoder CLI を実行するマシン上のディレクトリパス
access'read' | 'read-write''read-write'メモリ Agent がこの root に書き込めるかどうか
indexFilestringroot 内の相対インデックスパス。すべてが内容ファイルの場合は省略

ターンごとに書き込むかを判断する

生成は既定で各ターンの完了後に実行されます。shouldGenerate により、アプリケーション側で単一の生成を却下できます。価値の低いターンを飛ばす、テナントごとに予算を制御する、読み取り専用のレビュー時には書き込まない、といった用途に使えます。
options: {
  memory: {
    mode: 'custom',
    generation: {
      turnComplete: {
        shouldGenerate: async (input, { signal }) => {
          if (input.prompt.length < 40) {
            return { run: false, reason: 'プロンプトが短く、記録する価値がない' };
          }
          return { run: true };
        },
        timeoutMs: 5_000,
        onGateError: 'skip',
      },
    },
  },
}
コールバックは完了したターンの promptresponse、加えて sessionIdcwd、1 から始まる turnIndex を受け取ります。run: false を返すとバックグラウンド Agent は起動せず、skipped の結果が生成されます。
フィールド既定値説明
enabledbooleantrueターン完了時の生成を有効にするか
shouldGenerateコールバックアプリケーション側のゲート。省略時はランタイム内蔵の保護ルールのみ
timeoutMsnumber10000ゲートコールバックの最大所要時間
onGateError'skip' | 'report_failed''skip'コールバックのエラーやタイムアウトの報告方法

読み込む内容を制御する

files を明示的に指定すると、この Query ではネイティブの自動メモリが置き換えられます。静的な指示は引き続き読み込まれます。
options: {
  memory: {
    mode: 'custom',
    consumption: {
      files: [
        { id: 'conventions', path: '/srv/knowledge/CONVENTIONS.md', required: true },
        { id: 'runbook', path: '/srv/knowledge/RUNBOOK.md' },
      ],
      maxTokens: 4_000,
      overflow: 'truncate',
      failureMode: 'fail_query',
    },
  },
}
ファイルは配列の順に注入され、id が注入されるセクション名になります。
フィールド既定値説明
enabledbooleantrueメモリを読み込むか
filesMemoryConsumptionFile[]明示的なファイル一覧。ネイティブの自動メモリを置き換える
maxTokensnumberすべての明示ファイルで共有するトークン予算
overflow'truncate' | 'fail_query''truncate'内容が maxTokens を超えた場合の扱い
failureMode'best_effort' | 'fail_query''best_effort'読み取り失敗時の扱い。required を付けたファイルのみ Query を失敗させる

メモリの実行結果を確認する

メモリはバックグラウンドで動作するため、成功を前提とせず結果を明示的に取得してください。方法は2つあります。 1つはコールバックの登録で、nativecustom の両モードで利用できます。
options: {
  memory: {
    mode: 'native',
    generation: {
      onResult: (result) => {
        console.log(`[memory] ${result.status} / ${result.durationMs}ms`);
        for (const file of result.writtenFiles) {
          console.log(`  書き込み ${file.rootId}:${file.path}`);
        }
      },
    },
    consumption: {
      onResult: (result) => {
        for (const file of result.files) {
          console.log(`  読み込み ${file.id}: ${file.status}`);
        }
      },
    },
  },
}
もう1つはメッセージストリームからの取得で、subtype が memory_generation および memory_consumptionsystem メッセージに同じ内容が含まれます。
for await (const message of q) {
  if (message.type === 'system' && message.subtype === 'memory_generation') {
    console.log(message.result.status);
  }
}
生成は次の5種類のいずれかを報告します。
ステータス意味
saved書き込み対象のすべてのファイルが成功
partial少なくとも1件が成功し1件が失敗。failedFiles を確認
no_change実行されたが、記録すべき新しい内容が見つからなかった
skipped実行されなかった。例:ゲートが run: false を返した
failed実行されたが、書き込みに成功したファイルがない
読み込みは successpartialfailed のいずれかを報告し、ファイルごとに loadedmissingfailedtruncated のステータスを返します。missing はエラーではありません。初回実行時にはメモリファイルがまだ存在しない場合があります。

実行中にメモリを制御する

Query オブジェクトには、バックグラウンド生成に伴うタイミングの問題を扱う2つのメソッドがあります。
const q = query({ prompt: userMessages(), options: { memory: { mode: 'native' } } });

// プロセス終了やファイル内容の検証の前に、未完了のターン生成を待つ
await q.flushMemory();

// 外部プロセスがメモリファイルを変更した後に再読み込みする
await q.refreshMemory();
flushMemory() は CI やテストで特に重要です。最終の result メッセージを受け取った直後にプロセスが終了すると、書き込み中の生成が中断される可能性があります。

実際に適用された設定を確認する

メモリオプションはランタイムとの調整によって決まるため、渡した値ではなく実際に適用された設定を読み戻してください。
const init = await q.initializationResult();
console.log(init.memory);
// {
//   enabled: true,
//   requester: 'sdk',
//   mode: 'native',
//   generationEnabled: true,
//   turnCompleteEnabled: true,
//   consumptionEnabled: true,
//   roots: [{ id: 'user', access: 'read-write' }, { id: 'project', access: 'read-write' }]
// }
memory を省略した場合、または {} を指定した場合、init.memoryundefined になります。

次のステップ