Session persistence¶
The assistant automatically saves the session state on exit and offers to resume on next launch. This enables continuity across sessions—the assistant knows what files existed and if they changed, allowing it to pick up where the previous session left off.
Agent Assist memory¶
The LLM itself does not remember the conversation. There is no server-side chat or conversation ID to preserve. The architecture is stateless from the LLM's perspective:
-
pydantic-ai + OpenAI-compatible API: The agent uses
OpenAIChatModelwhich communicates with the OpenAI Chat Completions API through the DataRobot LLM Gateway. This API is stateless—there is no server-side conversation thread. Every request sends the full message history in the request body, and the server has no memory of prior turns. -
message_history: This is alist[ModelMessage]maintained entirely on the client side. Each call toagent.iter(user_input, message_history=message_history)sends the full history to the LLM. When the response arrives,agent_run.all_messages()returns the updated list, including the new turn. The server doesn't track or account for a "chat or conversation ID" during this process.
This means:
- When the process exits, the
message_historylist ceases to exist and the LLM doesn't remember the conversation. - Replaying the full raw history when the conversation resumes would be expensive and fragile due to token limits, stale tool results, etc.
- Session continuity is achieved through compressed context injection—a summary of the conversation's actions and decisions is injected into the system prompt when the conversation resumes.
Session persistence details¶
Session persistence saves conversation history in compacted form: a recent-messages tail plus a summary of older turns, alongside lightweight metadata. On resume, the assistant reconstructs a trimmed message_history from this (via reconstruct_history()) and also injects a resume-context block into the system prompt. The lightweight metadata it tracks:
| アーティファクト | 目的 |
|---|---|
| Session ID and timestamps | Identity and recency—"when did we last talk?". |
agent_spec.md path |
Whether the user was designing an agent. |
| File manifest (SHA256 hashes) | Detect if files changed while the assistant was offline. Files not in the manifest are not detected (that would require a full workspace scan). |
_session_deleted |
Whether the session was deleted by the user. |
Context injection¶
When the agent conversation resumes, build_resume_context() constructs a text block from the previously saved session state and injects it into the agent's system prompt using pydantic-ai's @agent.system_prompt(dynamic=True) decorator. This decorator re-evaluates on every agent run, so:
- On resume: the agent sees session context (ID, timestamps, file changes, summary, decisions).
- After
/reset: the dynamic prompt returns""and the agent sees nothing. - During normal operation: the prompt returns whatever was set at launch.
This block serves as invisible system prompt content that gives the agent awareness of prior sessions.
Session lifecycle details¶
When an exited session resumes, a block similar to the following is injected into the system prompt (invisible to the user):
# 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.
After running /reset (/new), this block disappears—the dynamic prompt returns an empty string.
Fresh launch (no prior session)¶
The first time the agent launches, when there is no prior session:
- On launch,
SessionState()creates a new session with a random 12-character hex ID. - The user interacts with the agent.
- On exit,
SessionLifecycle.snapshot_and_save()captures the current file manifest, thenSessionManager.save()writes the session file andactive_{pid}.jsonpointer
Resume (existing session)¶
When the agent resumes a previous session:
- On launch,
SessionManager.load()readsactive_{pid}.jsonand loads the indicated session file. -
The user is prompted to resume the previous session:
Previous session found (last active: 2026-03-31 14:22 UTC) Resume previous session? [Y/n] -
Yes: The existing
SessionStateis carried forward (same ID, same file on disk).build_resume_context()constructs the system prompt block with session info and drift detection results. - No: A new
SessionState()is created. The old session file remains on disk as an orphan (small, <1KB). The new session's autosave on exit updatesactive_{pid}.jsonto point to the new ID. - The constructed system prompt is injected into the agent using pydantic-ai's
@agent.system_prompt(dynamic=True).
Session reset¶
When the user runs /reset (/new):
- If
agent_spec.mdor template directory exist, the user is prompted for confirmation before deletion. - Even if no files exist,
/resetalways: - Clears in-memory conversation history (
message_history = None). - Creates a fresh
SessionState()with a new ID. - Deletes the persisted session file and
active_{pid}.jsonpointer. - Clears the dynamic resume context from the system prompt.
- Sets
_session_deleted = Trueto prevent autosave resurrection on exit. - If the user continues interacting after
/reset, the first successful agent response re-enables autosave (_session_deleted = False) so the new session is preserved.
Session save¶
When the user runs /save:
SessionLifecycle.explicit_save()updatesagent_spec_pathand rebuildsfile_manifestfrom current workspaceSessionManager.save()writes the session file and updatesactive_{pid}.json- Re-enables autosave if it was disabled by a prior
/reset
Session exit (autosave)¶
When the agent exits due to normal shutdown, Ctrl+C, or crash:
- The
finallyblock inchat()runs on quit, Ctrl+C, or crash. - If
_session_deletedisTrue(set by/resetwith no subsequent interaction), autosave is skipped - Otherwise, snapshots workspace state and persists.
Session slash commands¶
The assistant supports the following slash commands for session management:
| Command | 説明 |
|---|---|
/save |
Checkpoint the session immediately. Snapshots the current agent_spec.md state and file manifest before writing. |
/reset (/new) |
Always clears conversation history, deletes the saved session, and removes resume context from the system prompt. If agent_spec.md or the template directory exist, prompts for confirmation before deleting them. The next agent turn starts completely clean. |
/checkpoint |
List session checkpoints, or restore one by number (/checkpoint [number]). |
/compact |
会話履歴を圧縮してトークンの使用量を減らします。 |
/resume |
Show the resume context currently injected into the session's system prompt. |
File drift detection¶
On resume, the assistant compares SHA256 hashes of tracked files against the saved manifest. This detects three cases:
- Unchanged: The hash matches; reported as a count ("1 tracked file(s) unchanged").
- Modified: The file exists but the hash differs; listed as
<file>: modified. - Deleted: The file was in manifest but no longer exists; listed as
<file>: deleted.
File drift detection
New files not in the manifest are not detected (that would require a full workspace scan).
This allows the assistant to alert the user (or adjust its own behavior) when workspace files were changed outside the assistant between sessions.
Component map¶
The following components are responsible for session management:
| コンポーネント | 位置 | Responsibility |
|---|---|---|
SessionState |
session/models.py |
Pydantic model—schema for persisted state. |
SessionManager |
session/manager.py |
CRUD operations on session JSON files. |
SessionLifecycle |
session/lifecycle.py |
Owns session state, message history, resume context, and deletion flag; enforces state transition invariants; builds resume context for system prompt injection. |
| Filesystem helpers | helpers/filesystem.py |
SHA256 hashing, path validation, manifest building, drift detection. |
| Path helpers | helpers/paths.py |
Path-to-directory-name resolution for project settings. |
| Confirmation UI | ui/confirm.py |
Destructive action confirmation dialog (isolated to break circular import). |
| Main loop | main.py |
Lifecycle orchestration (resume prompt, delegates to SessionLifecycle). |
| Command handlers | commands/handlers.py |
/save and /reset session operations. |
CommandContext |
commands/base.py |
Carries session references to command handlers. |
Storage layout¶
The session state is stored in the project configuration directory at ~/.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)
Each session file contains the following fields:
| フィールド | 説明 |
|---|---|
schema_version |
Schema version for forward compatibility (currently 3). |
session_id |
12-character hex identifier. |
created_at |
UTC timestamp of session creation. |
updated_at |
UTC timestamp of last save. |
agent_spec_path |
Relative path to agent spec, or null. |
file_manifest |
{relative_path: sha256_hex} for tracked files. |
summary |
LLM-extracted narrative summary of the prior session, or null. |
decisions |
Key decisions extracted from the prior session. |
recent_messages |
Serialized recent conversation messages (the compaction tail) reconstructed on resume. |
compacted_history_summary |
Summary of older messages compacted away, or null. |
checkpoint_count |
Most recent checkpoint number written for the session (informational, not a live file count). |
phase |
Current conversation phase (design / code / deploy), or null. |
セキュリティ¶
- Path traversal protection: All manifest paths are validated via
is_safe_relative_path()(inhelpers/filesystem.py) to resolve within the workspace directory before any file I/O. Tampered manifests containing../sequences are silently skipped. - Symlink rejection:
build_file_manifest()anddetect_file_drift()skip symlinks as defense-in-depth against time-of-check-to-time-of-use (TOCTOU) symlink attacks. A file replaced by a symlink between sessions is reported as deleted. - Session ID validation: Session IDs are validated against a strict
^[a-f0-9]{12}$regex before constructing file paths, preventing path injection via crafted pointer files. - No secrets in session files: Session state contains only metadata (timestamps, hashes, paths). API keys, conversation content, and user input are not persisted.