# セッションの永続化

> セッションの永続化 - セッションの永続化の詳細、コンテキストの注入、セッションのライフサイクルの詳細、ファイルのドリフト検出、セッションのリセット、セッションの保存、セッションの終了（自動保存）、セ
> ッションのスラッシュコマンド。

This Markdown file sits beside the HTML page at the same path (with a `.md` suffix). It summarizes the topic and lists links for tools and LLM context.

Companion generated at `2026-07-27T18:44:30.173081+00:00` (UTC).

## Primary page

- [セッションの永続化](https://docs.datarobot.com/ja/docs/agentic-ai/agent-assist/session-management.html.md): Full documentation for this topic (Markdown sidecar).

## Sections on this page

- [Agent Assistのメモリー](https://docs.datarobot.com/ja/docs/agentic-ai/agent-assist/session-management.html.md#agent-assist-memory): In-page section heading.
- [セッションの永続化の詳細](https://docs.datarobot.com/ja/docs/agentic-ai/agent-assist/session-management.html.md#session-persistence-details): In-page section heading.
- [コンテキストの注入](https://docs.datarobot.com/ja/docs/agentic-ai/agent-assist/session-management.html.md#context-injection): In-page section heading.
- [セッションライフサイクルの詳細](https://docs.datarobot.com/ja/docs/agentic-ai/agent-assist/session-management.html.md#session-lifecycle-details): In-page section heading.
- [新規起動（以前のセッションなし）](https://docs.datarobot.com/ja/docs/agentic-ai/agent-assist/session-management.html.md#fresh-launch-no-prior-session): In-page section heading.
- [再開（既存のセッション）](https://docs.datarobot.com/ja/docs/agentic-ai/agent-assist/session-management.html.md#resume-existing-session): In-page section heading.
- [セッションのリセット](https://docs.datarobot.com/ja/docs/agentic-ai/agent-assist/session-management.html.md#session-reset): In-page section heading.
- [セッションの保存](https://docs.datarobot.com/ja/docs/agentic-ai/agent-assist/session-management.html.md#session-save): In-page section heading.
- [セッション終了（自動保存）](https://docs.datarobot.com/ja/docs/agentic-ai/agent-assist/session-management.html.md#session-exit-autosave): In-page section heading.
- [セッションのスラッシュコマンド](https://docs.datarobot.com/ja/docs/agentic-ai/agent-assist/session-management.html.md#session-slash-commands): In-page section heading.
- [ファイルドリフト検出](https://docs.datarobot.com/ja/docs/agentic-ai/agent-assist/session-management.html.md#file-drift-detection): In-page section heading.
- [コンポーネントマップ](https://docs.datarobot.com/ja/docs/agentic-ai/agent-assist/session-management.html.md#component-map): In-page section heading.
- [ストレージレイアウト](https://docs.datarobot.com/ja/docs/agentic-ai/agent-assist/session-management.html.md#storage-layout): In-page section heading.
- [セキュリティ](https://docs.datarobot.com/ja/docs/agentic-ai/agent-assist/session-management.html.md#security): In-page section heading.

## Documentation content

アシスタントは終了時にセッションの状態を自動的に保存し、次回の起動時に再開するかどうかを尋ねます。 これにより、セッション間の連続性が確保されます。アシスタントは、どのファイルが存在していたか、またそれらが変更されたかどうかを把握しているため、前回のセッションの続きから再開できます。

## Agent Assistのメモリー

LLM自体は会話を 記憶しません 。 保存すべきサーバー側のチャットや会話IDはありません。 LLMの観点から見ると、アーキテクチャはステートレスです。

- pydantic-ai + OpenAI互換API：エージェントは、DataRobot LLM Gatewayを介してOpenAI Chat Completions APIと通信するOpenAIChatModelを使用します。 このAPIはステートレスです。サーバー側の会話スレッドはありません。 すべてのリクエストでは、リクエスト本文にメッセージの全履歴が送信され、サーバーはそれ以前のやり取りを一切記憶していません。
- message_history：これは、完全にクライアント側で管理されるlist[ModelMessage]です。agent.iter(user_input, message_history=message_history)を呼び出すたびに、完全な履歴がLLMに送信されます。 応答が届くと、agent_run.all_messages()は新しいやり取りも含めた更新後のリストを返します。 このプロセスにおいて、サーバーは「チャットID」や「会話ID」を追跡したり、考慮したりすることはありません。

つまり、次のようになります。

- プロセスが終了すると、 message_history リストは消滅し、LLMは会話を記憶しません。
- 会話が再開された際に、生の履歴をすべて再生し直すことは、トークンの制限やツールの結果が古くなっていることなどの理由から、高コストで脆弱になります。
- セッションの継続性は、 圧縮コンテキストの注入 によって実現されます。つまり、会話が再開される際、その会話における行動や決定事項の要約が、システムのプロンプトに注入されます。

## セッションの永続化の詳細

セッションの永続化により、会話履歴は 圧縮 された形式で保存されます。具体的には、最近のメッセージの末尾部分と、それ以前のやり取りの要約、および軽量なメタデータが含まれます。 再開時、アシスタントはこのデータから（ `reconstruct_history()` を通じて）トリミングされた `message_history` を再構築し、システムプロンプトに再開コンテキストブロックを注入します。 追跡される軽量なメタデータは以下のとおりです。

| アーティファクト | 目的 |
| --- | --- |
| セッションIDとタイムスタンプ | 識別情報と最新性 - 「最後に会話したのはいつですか？」 |
| agent_spec.mdのパス | ユーザーがエージェントを設計していたかどうか。 |
| ファイルマニフェスト（SHA256ハッシュ） | アシスタントがオフラインの間にファイルが変更されたかどうかを検出します。 マニフェストに含まれていないファイルは検出されません（検出するにはワークスペース全体のスキャンが必要となります）。 |
| _session_deleted | セッションがユーザーによって削除されたかどうか。 |

## コンテキストの注入

エージェントの会話が再開されると、 `build_resume_context()` は以前に保存されたセッション状態からテキストブロックを構築し、pydantic-aiの `@agent.system_prompt(dynamic=True)` デコレーターを使用して、それをエージェントのシステムプロンプトに注入します。 このデコレーターはエージェントの実行ごとに再評価されるため、以下のようになります。

- 再開時：エージェントはセッションのコンテキスト（ID、タイムスタンプ、ファイルの変更、要約、決定事項）を確認できます。
- /reset の後：動的プロンプトは "" を返し、エージェントは何も認識しません。
- 通常の操作中：プロンプトは起動時に設定された内容を返します。

このブロックは、エージェントに過去のセッションに関する情報を認識させるための、ユーザーには見えないシステムプロンプトの内容として機能します。

## セッションライフサイクルの詳細

終了したセッションが再開されると、次のようなブロックがシステムプロンプトに注入されます（ユーザーには見えません）。

```
# Resumed Session Context
This is a resumed session (ID: a1b2c3d4e5f6).
Originally started: 2026-03-30 10:15 UTC
Last active: 2026-03-31 14:22 UTC

Agent specification file: agent_spec.md

## Previous Session Summary
User designed a customer support agent with three tools. Model selection
was GPT-5 via the DataRobot model catalog. Spec was saved but not yet
implemented in code.

## Key Decisions Made
- Selected GPT-5 as the agent model for strong reasoning capability
- Chose REST API tools over SDK wrappers for portability
- Deferred authentication configuration to implementation phase

## File Changes Since Last Session
- agent_spec.md: modified

IMPORTANT: You are resuming a previous session. Review the context above
before proceeding. If the user's request seems to continue prior work,
use this context. If they start a new topic, proceed normally. 
```

`/reset` （ `/new` ）を実行すると、このブロックは消え、動的プロンプトは空の文字列を返します。

### 新規起動（以前のセッションなし）

以前のセッションが存在しない場合、エージェントが初めて起動するとき

1. 起動時に、 SessionState() はランダムな12文字の16進数IDを持つ新しいセッションを作成します。
2. ユーザーはエージェントとやり取りします。
3. 終了時、 SessionLifecycle.snapshot_and_save() は現在のファイルマニフェストを取得し、その後、 SessionManager.save() がセッションファイルと active_{pid}.json ポインターを書き込みます。

### 再開（既存のセッション）

エージェントが以前のセッションを再開する場合

1. 起動時、 SessionManager.load() は active_{pid}.json を読み取り、指定されたセッションファイルをロードします。
2. ユーザーには、前回のセッションを再開するかどうかを尋ねるプロンプトが表示されます。 Previous session found (last active: 2026-03-31 14:22 UTC)
Resume previous session? [Y/n]
3. はい：既存のSessionStateが引き継がれます（同じID、ディスク上の同じファイル）。build_resume_context()は、セッション情報とドリフト検出結果を使用してシステムプロンプトブロックを構築します。
4. いいえ ：新しい SessionState() が作成されます。 古いセッションファイルは孤立したファイル（小、<1KB）としてディスクに残ります。 新しいセッションの終了時の自動保存により、 active_{pid}.json が新しいIDを指すように更新されます。
5. 構築されたシステムプロンプトは、pydantic-aiの @agent.system_prompt(dynamic=True) を使用してエージェントに注入されます。

### セッションのリセット

ユーザーが `/reset` （ `/new` ）を実行した場合

1. agent_spec.md またはテンプレートディレクトリが存在する場合、削除前にユーザーに確認が求められます。
2. ファイルが存在しない場合でも、 /reset は常に次の処理を行います。
3. メモリー内の会話履歴（ message_history = None ）をクリアします。
4. 新しいIDを持つ新規の SessionState() を作成します。
5. 永続化されたセッションファイルと active_{pid}.json ポインターを削除します。
6. システムプロンプトから動的再開コンテキストをクリアします。
7. 終了時の自動保存による復活を防ぐために、 _session_deleted = True を設定します。
8. /reset の後にユーザーが対話を続けた場合、エージェントの最初の応答が成功すると、自動保存が再び有効になり（ _session_deleted = False ）、新しいセッションが保持されます。

### セッションの保存

ユーザーが `/save` を実行した場合

1. SessionLifecycle.explicit_save() は agent_spec_path を更新し、現在のワークスペースから file_manifest を再構築します
2. SessionManager.save() writes the session file and updates active_{pid}.json
3. 以前の /reset によって無効になっていた場合、自動保存を再度有効にします

### セッション終了（自動保存）

通常のシャットダウン、Ctrl+C、またはクラッシュによりエージェントが終了した場合

1. chat() 内の finally ブロックは、終了、Ctrl+C、またはクラッシュ時に実行されます。
2. _session_deleted が True の場合（その後の対話なしで /reset によって設定された場合）、自動保存はスキップされます
3. それ以外の場合は、ワークスペースの状態のスナップショットを作成して永続化します。

## セッションのスラッシュコマンド

アシスタントは、セッション管理用の次のスラッシュコマンドをサポートしています。

| Command | 説明 |
| --- | --- |
| /save | セッションのチェックポイントをただちに作成します。 書き込む前に、現在のagent_spec.md状態とファイルマニフェストのスナップショットを作成します。 |
| /reset (/new) | 常に会話履歴をクリアし、保存されたセッションを削除し、システムプロンプトから再開コンテキストを削除します。 agent_spec.mdまたはテンプレートディレクトリが存在する場合は、削除する前に確認を求めます。 次のエージェントターンは完全にクリーンな状態で開始されます。 |
| /checkpoint | セッションのチェックポイントを一覧表示するか、番号を指定して復元します（/checkpoint [number]）。 |
| /compact | 会話履歴を圧縮してトークンの使用量を減らします。 |
| /resume | セッションのシステムプロンプトに現在注入されている再開コンテキストを表示します。 |

## ファイルドリフト検出

再開時に、アシスタントは追跡対象ファイルのSHA256ハッシュを保存されたマニフェストと比較します。 これにより、次の3つのケースが検出されます。

- 変更なし ：ハッシュが一致します。カウント（「1つの追跡対象ファイルが変更されていません」）として報告されます。
- 変更あり ：ファイルは存在しますがハッシュが異なります。 <file>: modified としてリストされます。
- 削除済み ：ファイルはマニフェストにありましたが、現在は存在しません。 <file>: deleted としてリストされます。

> [!NOTE] ファイルドリフト検出
> マニフェストにない新しいファイルは検出されません（それには完全なワークスペーススキャンが必要になります）。

これにより、セッション間でアシスタントの外部でワークスペースファイルが変更されたときに、アシスタントがユーザーに警告する（または自身の動作を調整する）ことができます。

## コンポーネントマップ

次のコンポーネントはセッション管理を担います。

| コンポーネント | 位置 | 役割 |
| --- | --- | --- |
| SessionState | session/models.py | Pydanticモデル—永続化された状態のスキーマ。 |
| SessionManager | session/manager.py | セッションJSONファイルのCRUD操作。 |
| SessionLifecycle | session/lifecycle.py | セッション状態、メッセージ履歴、再開コンテキスト、および削除フラグを保持します。状態遷移の不変条件を強制します。システムプロンプト注入用の再開コンテキストを構築します。 |
| ファイルシステムヘルパー | helpers/filesystem.py | SHA256ハッシュ、パス検証、マニフェスト構築、ドリフト検出。 |
| パスヘルパー | helpers/paths.py | プロジェクト設定のパスからディレクトリ名への解決。 |
| 確認UI | ui/confirm.py | 破壊的アクションの確認ダイアログ（循環インポートを断ち切るために分離されています）。 |
| メインループ | main.py | ライフサイクルオーケストレーション（再開プロンプト、SessionLifecycleへの委譲）。 |
| コマンドハンドラー | commands/handlers.py | /saveおよび/resetセッション操作。 |
| CommandContext | commands/base.py | セッション参照をコマンドハンドラーに伝達します。 |

## ストレージレイアウト

セッション状態は、プロジェクト設定ディレクトリの `~/.config/datarobot/agent_assist/projects/<name>_<hash>/sessions/` に保存されます。

```
~/.config/datarobot/agent_assist/projects/
  my-project_a1b2c3d4/
    sessions/
      a1b2c3d4e5f6.json   # per-session state file
      active_<pid>.json    # pointer to current session (one per terminal PID) 
```

各セッションファイルには次のフィールドが含まれています。

| フィールド | 説明 |
| --- | --- |
| schema_version | 前方互換性のためのスキーマバージョン（現在は3）。 |
| session_id | 12文字の16進数識別子。 |
| created_at | セッション作成のUTCタイムスタンプ。 |
| updated_at | 最終保存のUTCタイムスタンプ。 |
| agent_spec_path | エージェント仕様への相対パス、またはnull。 |
| file_manifest | 追跡対象ファイルの{relative_path: sha256_hex}。 |
| summary | LLMが抽出した以前のセッションのナラティブサマリー、またはnull。 |
| decisions | 以前のセッションから抽出された主な決定事項。 |
| recent_messages | 再開時に再構築された、シリアル化された最近の会話メッセージ（圧縮の末尾）。 |
| compacted_history_summary | 圧縮された古いメッセージのサマリー、またはnull。 |
| checkpoint_count | セッションに書き込まれた最新のチェックポイント番号（情報提供のみ。ライブファイルカウントではありません）。 |
| phase | 現在の会話フェーズ（設計 / コード / デプロイ）、またはnull。 |

## セキュリティ

- パストラバーサル保護 ：すべてのマニフェストパスは、ファイルI/Oの前にワークスペースディレクトリ内で解決されるように、（ helpers/filesystem.py の） is_safe_relative_path() を介して検証されます。 ../ シーケンスを含む改ざんされたマニフェストは、暗黙のうちにスキップされます。
- シンボリックリンクの拒否 ： build_file_manifest() および detect_file_drift() は、TOCTOU（time-of-check-to-time-of-use）シンボリックリンク攻撃に対する多層防御としてシンボリックリンクをスキップします。 セッション間にシンボリックリンクに置き換えられたファイルは、削除済みとして報告されます。
- セッションIDの検証 ：セッションIDは、ファイルパスを構築する前に厳密な ^[a-f0-9]{12}$ 正規表現に対して検証され、巧妙に作られたポインターファイルによるパスインジェクションを防ぎます。
- セッションファイルにシークレットが含まれない ：セッション状態にはメタデータ（タイムスタンプ、ハッシュ、パス）のみが含まれます。 APIキー、会話のコンテンツ、およびユーザー入力は永続化されません。
