> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/agentclientprotocol/typescript-sdk/llms.txt
> Use this file to discover all available pages before exploring further.

# Session Management

> Learn how to create, load, and manage conversation sessions

## Overview

Sessions represent independent conversation contexts with their own history and state. Each session has a unique ID and maintains its own conversation history, working directory, and MCP server connections.

## Creating Sessions

The `newSession` method creates a new conversation session:

```typescript theme={null}
async newSession(
  params: NewSessionRequest
): Promise<NewSessionResponse>
```

<ParamField path="params.workingDirectory" type="string">
  Optional working directory for the session
</ParamField>

<ParamField path="params.mcpServers" type="MCPServerConfig[]">
  MCP servers to connect to for this session
</ParamField>

<ResponseField name="sessionId" type="string" required>
  A unique identifier for the new session
</ResponseField>

<ResponseField name="availableModes" type="Mode[]">
  Optional list of available modes for this session
</ResponseField>

<ResponseField name="currentMode" type="string">
  The initial mode for this session
</ResponseField>

See protocol docs: [Session Setup](https://agentclientprotocol.com/protocol/session-setup)

### Example

```typescript theme={null}
interface AgentSession {
  workingDirectory?: string;
  history: acp.Message[];
  pendingPrompt: AbortController | null;
  mcpServers: MCPServerConnection[];
}

class MyAgent implements acp.Agent {
  private sessions: Map<string, AgentSession> = new Map();

  async newSession(params: acp.NewSessionRequest): Promise<acp.NewSessionResponse> {
    const sessionId = crypto.randomUUID();
    
    // Create session state
    this.sessions.set(sessionId, {
      workingDirectory: params.workingDirectory,
      history: [],
      pendingPrompt: null,
      mcpServers: await this.connectToMCPServers(params.mcpServers),
    });

    return {
      sessionId,
      currentMode: "code",
    };
  }

  private async connectToMCPServers(
    configs: acp.MCPServerConfig[] = []
  ): Promise<MCPServerConnection[]> {
    // Connect to each MCP server
    return Promise.all(configs.map(config => this.connectMCPServer(config)));
  }
}
```

<Note>
  May throw an `auth_required` error if the agent requires authentication before creating sessions.
</Note>

## Loading Sessions

The optional `loadSession` method loads an existing session to resume a previous conversation:

```typescript theme={null}
loadSession?(
  params: LoadSessionRequest
): Promise<LoadSessionResponse>
```

<ParamField path="params.sessionId" type="string" required>
  The session ID to load
</ParamField>

<ParamField path="params.mcpServers" type="MCPServerConfig[]">
  MCP servers to connect to for this session
</ParamField>

<ResponseField name="availableModes" type="Mode[]">
  Optional list of available modes for this session
</ResponseField>

<ResponseField name="currentMode" type="string">
  The current mode for this session
</ResponseField>

This method is only available if the agent advertises the `loadSession` capability during initialization.

The agent should:

* Restore the session context and conversation history
* Connect to the specified MCP servers
* Stream the entire conversation history back to the client via `sessionUpdate` notifications

See protocol docs: [Loading Sessions](https://agentclientprotocol.com/protocol/session-setup#loading-sessions)

### Example

```typescript theme={null}
async loadSession(params: acp.LoadSessionRequest): Promise<acp.LoadSessionResponse> {
  // Load session from storage
  const sessionData = await this.storage.loadSession(params.sessionId);
  
  if (!sessionData) {
    throw acp.RequestError.resourceNotFound(params.sessionId);
  }

  // Restore session state
  this.sessions.set(params.sessionId, {
    workingDirectory: sessionData.workingDirectory,
    history: sessionData.history,
    pendingPrompt: null,
    mcpServers: await this.connectToMCPServers(params.mcpServers),
  });

  // Stream conversation history to client
  for (const message of sessionData.history) {
    await this.connection.sessionUpdate({
      sessionId: params.sessionId,
      update: {
        sessionUpdate: "agent_message_chunk",
        content: message.content,
      },
    });
  }

  return {
    currentMode: sessionData.mode,
  };
}
```

## Session Modes

Session modes allow switching between different agent behaviors (e.g., "ask", "architect", "code") that affect system prompts, tool availability, and permission behaviors.

```typescript theme={null}
setSessionMode?(
  params: SetSessionModeRequest
): Promise<SetSessionModeResponse | void>
```

<ParamField path="params.sessionId" type="string" required>
  The session ID to update
</ParamField>

<ParamField path="params.mode" type="string" required>
  The mode to switch to (must be one of the advertised modes)
</ParamField>

The mode must be one of the modes advertised in `availableModes` during session creation or loading. Agents may also change modes autonomously and notify the client via `current_mode_update` notifications.

This method can be called at any time during a session, whether the agent is idle or actively generating a turn.

See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)

### Example

```typescript theme={null}
async initialize(params: acp.InitializeRequest): Promise<acp.InitializeResponse> {
  return {
    protocolVersion: acp.PROTOCOL_VERSION,
    agentCapabilities: {
      sessionModes: true,
    },
    availableModes: [
      {
        id: "code",
        name: "Code",
        description: "Full coding capabilities with all tools",
      },
      {
        id: "ask",
        name: "Ask",
        description: "Question answering without code modifications",
      },
      {
        id: "architect",
        name: "Architect",
        description: "High-level design and planning",
      },
    ],
  };
}

async setSessionMode(params: acp.SetSessionModeRequest): Promise<void> {
  const session = this.sessions.get(params.sessionId);
  if (!session) {
    throw new Error(`Session ${params.sessionId} not found`);
  }

  // Validate mode
  if (!this.isValidMode(params.mode)) {
    throw acp.RequestError.invalidParams({ mode: params.mode });
  }

  // Update session mode
  session.mode = params.mode;

  // Update system prompt based on mode
  await this.updateSystemPrompt(session, params.mode);
}
```

## Forking and Resuming Sessions (Unstable)

<Warning>
  These methods are marked as **UNSTABLE** and may be removed or changed at any point.
</Warning>

### Forking Sessions

The `unstable_forkSession` method creates a new session based on an existing one:

```typescript theme={null}
unstable_forkSession?(
  params: ForkSessionRequest
): Promise<ForkSessionResponse>
```

<ParamField path="params.sessionId" type="string" required>
  The session ID to fork from
</ParamField>

<ParamField path="params.mcpServers" type="MCPServerConfig[]">
  MCP servers to connect to for the new session
</ParamField>

<ResponseField name="sessionId" type="string" required>
  The ID of the newly created session
</ResponseField>

This allows operations like generating summaries without affecting the original session's history.

### Example

```typescript theme={null}
async unstable_forkSession(params: acp.ForkSessionRequest): Promise<acp.ForkSessionResponse> {
  const originalSession = this.sessions.get(params.sessionId);
  if (!originalSession) {
    throw new Error(`Session ${params.sessionId} not found`);
  }

  const newSessionId = crypto.randomUUID();
  
  // Create new session with copied state
  this.sessions.set(newSessionId, {
    workingDirectory: originalSession.workingDirectory,
    history: [...originalSession.history], // Copy history
    pendingPrompt: null,
    mcpServers: await this.connectToMCPServers(params.mcpServers),
  });

  return { sessionId: newSessionId };
}
```

### Resuming Sessions

The `unstable_resumeSession` method resumes an existing session without replaying the message history:

```typescript theme={null}
unstable_resumeSession?(
  params: ResumeSessionRequest
): Promise<ResumeSessionResponse>
```

<ParamField path="params.sessionId" type="string" required>
  The session ID to resume
</ParamField>

<ParamField path="params.mcpServers" type="MCPServerConfig[]">
  MCP servers to connect to for this session
</ParamField>

Unlike `loadSession`, this method does not stream the conversation history to the client.

### Example

```typescript theme={null}
async unstable_resumeSession(params: acp.ResumeSessionRequest): Promise<void> {
  const sessionData = await this.storage.loadSession(params.sessionId);
  
  if (!sessionData) {
    throw acp.RequestError.resourceNotFound(params.sessionId);
  }

  // Restore session state WITHOUT streaming history
  this.sessions.set(params.sessionId, {
    workingDirectory: sessionData.workingDirectory,
    history: sessionData.history,
    pendingPrompt: null,
    mcpServers: await this.connectToMCPServers(params.mcpServers),
  });
}
```

## Session Persistence

To support session loading, you'll need to persist session data:

```typescript theme={null}
interface SessionStorage {
  saveSession(sessionId: string, data: SessionData): Promise<void>;
  loadSession(sessionId: string): Promise<SessionData | null>;
  listSessions(): Promise<SessionMetadata[]>;
}

class MyAgent implements acp.Agent {
  constructor(
    private connection: acp.AgentSideConnection,
    private storage: SessionStorage
  ) {}

  async prompt(params: acp.PromptRequest): Promise<acp.PromptResponse> {
    const session = this.sessions.get(params.sessionId);
    if (!session) {
      throw new Error(`Session ${params.sessionId} not found`);
    }

    // Process prompt...
    const response = await this.processPrompt(params, session);

    // Persist updated session
    await this.storage.saveSession(params.sessionId, {
      workingDirectory: session.workingDirectory,
      history: session.history,
      mode: session.mode,
    });

    return response;
  }
}
```

## Best Practices

<CardGroup cols={2}>
  <Card title="Generate Unique IDs" icon="fingerprint">
    Use `crypto.randomUUID()` or similar to generate unique session IDs
  </Card>

  <Card title="Clean Up Resources" icon="broom">
    Disconnect from MCP servers and clean up resources when sessions end
  </Card>

  <Card title="Persist State" icon="database">
    Save session state after each prompt to support session loading
  </Card>

  <Card title="Validate Modes" icon="check">
    Validate that requested modes are in your list of available modes
  </Card>
</CardGroup>
