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:
async newSession (
params : NewSessionRequest
): Promise < NewSessionResponse >
Optional working directory for the session
MCP servers to connect to for this session
A unique identifier for the new session
Optional list of available modes for this session
The initial mode for this session
See protocol docs: Session Setup
Example
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 )));
}
}
May throw an auth_required error if the agent requires authentication before creating sessions.
Loading Sessions
The optional loadSession method loads an existing session to resume a previous conversation:
loadSession ? (
params : LoadSessionRequest
) : Promise < LoadSessionResponse >
MCP servers to connect to for this session
Optional list of available modes for this session
The current mode for this session
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
Example
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.
setSessionMode ? (
params : SetSessionModeRequest
) : Promise < SetSessionModeResponse | void >
The mode to switch to (must be one of the advertised modes)
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
Example
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)
These methods are marked as UNSTABLE and may be removed or changed at any point.
Forking Sessions
The unstable_forkSession method creates a new session based on an existing one:
unstable_forkSession ? (
params : ForkSessionRequest
) : Promise < ForkSessionResponse >
The session ID to fork from
MCP servers to connect to for the new session
The ID of the newly created session
This allows operations like generating summaries without affecting the original session’s history.
Example
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:
unstable_resumeSession ? (
params : ResumeSessionRequest
) : Promise < ResumeSessionResponse >
MCP servers to connect to for this session
Unlike loadSession, this method does not stream the conversation history to the client.
Example
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:
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
Generate Unique IDs Use crypto.randomUUID() or similar to generate unique session IDs
Clean Up Resources Disconnect from MCP servers and clean up resources when sessions end
Persist State Save session state after each prompt to support session loading
Validate Modes Validate that requested modes are in your list of available modes