Copilot SDK Session Persistence and Resumption Strategies: A Technical Deep Dive

The Copilot SDK persists sessions by storing state in a developer-configured directory through a pluggable SessionFsProvider interface, enabling exact resumption after restarts by reloading state.json and SQLite databases from the persistence path.

The GitHub Copilot SDK enables long-running conversational agents to survive process restarts and crashes through a robust persistence layer. According to the github/copilot-sdk source code, the SDK delegates all storage operations to an abstract file-system provider, allowing developers to choose between local disk, remote storage, or in-memory implementations while maintaining exact session state across lifecycles.

How the Copilot SDK Persists Session State

The SessionFsProvider Interface and Adapter

In sessionFsProvider.ts, the SDK defines the SessionFsProvider interface that abstracts all storage operations. The createSessionFsAdapter function wraps this provider, translating thrown errors into the JSON-RPC-compatible SessionFsError format. This adapter exposes methods for file operations and SQLite queries, forwarding them directly to the underlying provider implementation without imposing filesystem-specific logic.

Directory Structure and Incremental Updates

When a Session is instantiated via session.ts, the SDK creates a unique directory under the configured persistence root. The path follows the pattern <sessionPersistencePath>/<session-id>/, containing:

  • state.json – Stores serialized session state and conversation history
  • tool-outputs/ – Directory for tool execution artifacts
  • *.sqlite files – Optional SQLite databases for structured conversational data

During normal operation, the SDK writes incremental updates to these locations through the adapter, treating the persisted files as the single source of truth for session recovery.

Resuming Sessions After Process Restarts

Detecting and Loading Existing Sessions

The session.ts implementation checks for existing session directories when startSession is called with a sessionId parameter. If the directory exists, the SDK:

  1. Loads state.json through SessionFsProvider.readFile
  2. Reopens SQLite databases via sqliteQuery or sqliteTransaction methods
  3. Reconstructs the internal Session object with the restored context

This process enables exact session resumption even after host process crashes, container restarts, or application upgrades.

Pluggable Storage Backends

Because the persistence layer relies on the abstract SessionFsProvider interface, developers can substitute the default Node.js file system with custom implementations. The SDK treats the provider's responses as authoritative, enabling resumption from in-memory mocks, cloud object storage, or distributed file systems without modifying core session logic in client.ts.

Practical Implementation Example

import { createCopilotClient } from '@github/copilot-sdk';

// --------------------------------------------------------------------
// 1️⃣  Create a client that persists sessions to a local directory.
// --------------------------------------------------------------------
const client = createCopilotClient({
  // The SDK will create `<persistRoot>/<sessionId>/` for each session.
  sessionPersistencePath: '/tmp/copilot-sessions',
});

// --------------------------------------------------------------------
// 2️⃣  Start a new session (or resume an existing one by ID).
// --------------------------------------------------------------------
async function startOrResume(sessionId?: string) {
  const session = await client.startSession({ sessionId });
  console.log('Session ID:', session.id);

  // ----------------------------------------------------------------
  // 3️⃣  Use the session – file writes, SQLite queries, etc.
  // ----------------------------------------------------------------
  await session.fs.writeFile('notes.txt', 'Initial note');
  const content = await session.fs.readFile('notes.txt');
  console.log('File content:', content);

  // If the provider implements SQLite:
  await session.fs.sqliteQuery({
    queryType: 'run',
    query: 'CREATE TABLE IF NOT EXISTS notes (id INTEGER PRIMARY KEY, text TEXT);',
  });
  await session.fs.sqliteQuery({
    queryType: 'run',
    query: 'INSERT INTO notes (text) VALUES (?);',
    params: { 1: 'Persisted note' },
  });

  // ----------------------------------------------------------------
  // 4️⃣  The session state is automatically persisted to the directory.
  //    Restart the process and call `startOrResume(session.id)` to
  //    continue where you left off.
  // ----------------------------------------------------------------
}

// Example usage:
startOrResume();               // Starts a fresh session
// startOrResume('abc123');    // Resumes an existing session

Summary

  • The Copilot SDK uses a SessionFsAdapter in sessionFsProvider.ts to abstract storage operations into a JSON-RPC-compatible interface that handles errors via SessionFsError.
  • Session data persists to <sessionPersistencePath>/<session-id>/, including state.json and optional SQLite databases, with incremental updates written during normal operation.
  • Developers resume sessions by providing the same sessionPersistencePath and sessionId to createCopilotClient, which reloads state from existing directories through the Session class in session.ts.
  • The pluggable SessionFsProvider interface supports custom backends, including remote storage and in-memory implementations, without requiring changes to core session logic.

Frequently Asked Questions

Where does the Copilot SDK store session data?

The SDK stores session data in a developer-configured directory specified by the sessionPersistencePath option passed to createCopilotClient in client.ts. Each session receives a subdirectory named after its sessionId, containing files like state.json and any SQLite databases used during the conversation.

How do I resume a Copilot SDK session after a process crash?

To resume a session, instantiate a new client with the same sessionPersistencePath and call startSession with the previous sessionId. The SDK automatically detects the existing directory in session.ts, loads the saved state.json, and reopens SQLite connections through the provider interface.

Can I use a custom database or remote storage instead of the local file system?

Yes. The SDK exports the SessionFsProvider interface from sessionFsProvider.ts, allowing you to implement custom readFile, writeFile, and sqliteQuery methods. Pass your custom provider to the session configuration to redirect persistence to cloud storage, distributed databases, or in-memory mocks.

What files are created in the persistence directory?

The SDK creates state.json for serialized session state, a tool-outputs/ subdirectory for artifacts, and any *.sqlite files for structured data. These files serve as the single source of truth for session resumption strategies.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →