Sessions are independent conversation contexts in ACP. Each session maintains its own history, state, and configuration, allowing multiple parallel conversations with an agent.
What are Sessions?
A session represents a distinct conversation between a user and an agent. Sessions provide:
Independent Context - Each session has its own conversation history
Isolated State - Configuration and mode changes don’t affect other sessions
Persistent Identity - Sessions can be saved, loaded, and resumed
MCP Connections - Each session connects to its own set of MCP servers
Think of sessions like browser tabs - each is independent but part of the same application.
Session Lifecycle
Sessions progress through several states:
Creating Sessions
New Sessions
Create a new session with session/new:
const session = await agent . newSession ({
cwd: "/path/to/project" ,
mcpServers: [
{
type: "stdio" ,
command: "npx" ,
args: [ "-y" , "@modelcontextprotocol/server-filesystem" , "/tmp" ]
}
]
});
console . log ( session . sessionId ); // "session-abc123"
console . log ( session . availableModes ); // [{ id: "code", name: "Code" }, ...]
The agent returns a unique sessionId that must be included in all subsequent requests for this session.
export type SessionId = string ;
Session IDs are opaque strings generated by the agent. Clients should treat them as opaque identifiers.
Loading Sessions
Load an existing session to restore conversation history:
await agent . loadSession ({
sessionId: "session-abc123" ,
mcpServers: [
// MCP servers to connect
]
});
// Agent streams the entire conversation history via session/update notifications
// Client receives each message and tool call in order
Loading sessions requires the agent to advertise loadSession: true in its capabilities.
How Loading Works
Client sends session/load request with existing session ID
Agent restores session state from storage
Agent streams conversation history via session/update notifications
Client rebuilds UI state from the streamed messages
Agent responds when streaming is complete
Session ready for new prompts
Resuming Sessions (Unstable)
Resume a session without replaying history:
await agent . unstable_resumeSession ({
sessionId: "session-abc123" ,
mcpServers: []
});
// Agent restores context but doesn't stream history
// Useful when client already has the history
This is an unstable feature (unstable_resumeSession) and may change in future versions.
Forking Sessions (Unstable)
Create a new session based on an existing one:
const fork = await agent . unstable_forkSession ({
sessionId: "session-abc123" ,
mcpServers: []
});
console . log ( fork . sessionId ); // "session-xyz789" (new ID)
// Fork has same history as original but is now independent
// Changes to fork don't affect original session
Use Cases for Forking
Generate Summaries - Fork to create a summary without affecting main conversation
Try Alternatives - Fork to explore different approaches in parallel
Experimentation - Test agent behavior without modifying original session
Listing Sessions (Unstable)
Query available sessions:
const response = await agent . unstable_listSessions ({
cwd: "/path/to/project" , // Optional: filter by directory
cursor: null // Optional: for pagination
});
for ( const session of response . sessions ) {
console . log ( session . sessionId );
console . log ( session . title );
console . log ( session . lastUpdateTime );
console . log ( session . cwd );
}
// Handle pagination
if ( response . cursor ) {
const nextPage = await agent . unstable_listSessions ({
cursor: response . cursor
});
}
Session State Management
Session Modes
Agents can support different operational modes that affect behavior:
// Set the mode for a session
await agent . setSessionMode ({
sessionId: "session-abc123" ,
mode: "code" // or "ask", "architect", etc.
});
Modes typically affect:
System prompts - Different instructions for the LLM
Tool availability - Which tools are accessible
Permission behavior - Automatic vs. manual approval
Available modes are returned in NewSessionResponse.availableModes and LoadSessionResponse.availableModes.
Session Configuration
Set configuration options for a session:
const response = await agent . setSessionConfigOption ({
sessionId: "session-abc123" ,
optionId: "temperature" ,
valueId: "high"
});
// Response contains all current configuration
console . log ( response . configOptions );
Session Model (Unstable)
Select which LLM to use for a session:
await agent . unstable_setSessionModel ({
sessionId: "session-abc123" ,
modelId: "claude-opus-4"
});
Processing Prompts
Once a session is created, send prompts to the agent:
const response = await agent . prompt ({
sessionId: "session-abc123" ,
messages: [
{
role: "user" ,
content: {
type: "text" ,
text: "Help me fix the bug in utils.ts"
}
}
]
});
console . log ( response . stopReason ); // "endTurn", "cancelled", etc.
Prompt Lifecycle
Receiving Updates
Clients receive real-time updates via notifications:
class MyClient implements Client {
async sessionUpdate ( params : SessionNotification ) {
console . log ( "Session ID:" , params . sessionId );
if ( params . content ) {
// Message chunk
console . log ( "Content:" , params . content );
}
if ( params . toolCallUpdate ) {
// Tool call progress
console . log ( "Tool call:" , params . toolCallUpdate );
}
if ( params . currentModeUpdate ) {
// Mode changed
console . log ( "New mode:" , params . currentModeUpdate );
}
}
}
Cancelling Operations
Cancel an ongoing prompt:
await agent . cancel ({
sessionId: "session-abc123"
});
// Agent should:
// 1. Stop all LLM requests
// 2. Abort tool call invocations
// 3. Send any pending updates
// 4. Respond with stopReason: "cancelled"
The agent may send additional session/update notifications before responding with the cancelled status.
Session Persistence
Agents are responsible for persisting session state:
class MyAgent implements Agent {
private sessions = new Map < string , SessionState >();
async newSession ( params ) {
const sessionId = crypto . randomUUID ();
const state = {
id: sessionId ,
cwd: params . cwd ,
messages: [],
mode: "code"
};
this . sessions . set ( sessionId , state );
await this . saveToDatabase ( state );
return { sessionId , availableModes: [ ... ] };
}
async loadSession ( params ) {
const state = await this . loadFromDatabase ( params . sessionId );
this . sessions . set ( params . sessionId , state );
// Stream history to client
for ( const message of state . messages ) {
await this . connection . sessionUpdate ({
sessionId: params . sessionId ,
content: message . content
});
}
return { availableModes: [ ... ] };
}
}
Best Practices
Always validate that session IDs exist and are accessible: async prompt ( params : PromptRequest ) {
if ( ! this . sessions . has ( params . sessionId )) {
throw RequestError . invalidParams (
{ sessionId: params . sessionId },
"Session not found"
);
}
// Process prompt
}
Include Session ID in All Requests
Every session-related operation requires the session ID: // ✅ Correct
await agent . prompt ({ sessionId , messages: [ ... ] });
await connection . sessionUpdate ({ sessionId , content: { ... } });
// ❌ Wrong - missing sessionId
await agent . prompt ({ messages: [ ... ] });
Stream History Efficiently
When loading sessions, batch updates to avoid overwhelming the client: // Send updates in chunks
const CHUNK_SIZE = 10 ;
for ( let i = 0 ; i < messages . length ; i += CHUNK_SIZE ) {
const chunk = messages . slice ( i , i + CHUNK_SIZE );
for ( const msg of chunk ) {
await connection . sessionUpdate ({ ... });
}
// Small delay between chunks
await new Promise ( resolve => setTimeout ( resolve , 10 ));
}
Clean up resources when sessions end: connection . signal . addEventListener ( 'abort' , () => {
// Clean up all active sessions
for ( const [ id , session ] of this . sessions ) {
session . mcpConnections . forEach ( conn => conn . close ());
this . sessions . delete ( id );
}
});
Sessions include metadata for organization:
interface SessionInfo {
sessionId : string ;
title : string | null ;
lastUpdateTime : string ; // ISO 8601
cwd : string ;
}
MCP Server Connections
Each session can connect to MCP servers for additional tools:
const session = await agent . newSession ({
cwd: "/project" ,
mcpServers: [
{
type: "stdio" ,
command: "npx" ,
args: [ "-y" , "@modelcontextprotocol/server-filesystem" , "/tmp" ]
},
{
type: "sse" ,
url: "https://api.example.com/mcp"
}
]
});
MCP servers are connected at session creation/load and provide tools and resources to the agent.
Learn More
Protocol Overview Understanding the ACP specification
Connections Establishing agent-client connections
Session Setup Full specification for session operations
Prompt Turn How prompts are processed in sessions