Overview
The Agent interface defines the methods that all ACP-compliant agents must implement. These methods handle the lifecycle of the connection, session management, prompt processing, and cancellation.
export interface Agent {
// Required methods
initialize(params: InitializeRequest): Promise<InitializeResponse>;
newSession(params: NewSessionRequest): Promise<NewSessionResponse>;
authenticate(params: AuthenticateRequest): Promise<AuthenticateResponse | void>;
prompt(params: PromptRequest): Promise<PromptResponse>;
cancel(params: CancelNotification): Promise<void>;
// Optional methods
loadSession?(params: LoadSessionRequest): Promise<LoadSessionResponse>;
setSessionMode?(params: SetSessionModeRequest): Promise<SetSessionModeResponse | void>;
setSessionConfigOption?(params: SetSessionConfigOptionRequest): Promise<SetSessionConfigOptionResponse>;
unstable_forkSession?(params: ForkSessionRequest): Promise<ForkSessionResponse>;
unstable_listSessions?(params: ListSessionsRequest): Promise<ListSessionsResponse>;
unstable_resumeSession?(params: ResumeSessionRequest): Promise<ResumeSessionResponse>;
unstable_setSessionModel?(params: SetSessionModelRequest): Promise<SetSessionModelResponse | void>;
extMethod?(method: string, params: Record<string, unknown>): Promise<Record<string, unknown>>;
extNotification?(method: string, params: Record<string, unknown>): Promise<void>;
}
Required Methods
initialize
Establishes the connection with a client and negotiates protocol capabilities.
async initialize(
params: InitializeRequest
): Promise<InitializeResponse>
The protocol version requested by the client
params.clientCapabilities
Capabilities advertised by the client (file system access, terminal support, etc.)
The protocol version the agent will use (should match the client’s version)
Capabilities advertised by the agent (session loading, modes, etc.)
This method is called once at the beginning of the connection to:
- Negotiate the protocol version to use
- Exchange capability information between client and agent
- Determine available authentication methods
See protocol docs: Initialization
Example
async initialize(params: acp.InitializeRequest): Promise<acp.InitializeResponse> {
return {
protocolVersion: acp.PROTOCOL_VERSION,
agentCapabilities: {
loadSession: true,
sessionModes: true,
},
availableModes: [
{ id: "code", name: "Code", description: "Full coding capabilities" },
{ id: "ask", name: "Ask", description: "Question answering only" },
],
};
}
newSession
Creates a new conversation session with the agent.
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
Sessions represent independent conversation contexts with their own history and state.
The agent should:
- Create a new session context
- Connect to any specified MCP servers
- Return a unique session ID for future requests
May throw an auth_required error if the agent requires authentication.
See protocol docs: Session Setup
Example
async newSession(params: acp.NewSessionRequest): Promise<acp.NewSessionResponse> {
const sessionId = crypto.randomUUID();
this.sessions.set(sessionId, {
workingDirectory: params.workingDirectory,
history: [],
pendingPrompt: null,
});
return {
sessionId,
currentMode: "code",
};
}
authenticate
Authenticates the client using the specified authentication method.
async authenticate(
params: AuthenticateRequest
): Promise<AuthenticateResponse | void>
The authentication method ID that was advertised during initialization
Optional credentials provided by the client
Called when the agent requires authentication before allowing session creation. After successful authentication, the client can proceed to create sessions with newSession without receiving an auth_required error.
See protocol docs: Initialization
Example
async authenticate(params: acp.AuthenticateRequest): Promise<void> {
// No authentication needed in this example
return;
}
prompt
Processes a user prompt within a session.
async prompt(
params: PromptRequest
): Promise<PromptResponse>
The session ID to process the prompt in
The user messages with optional context (files, images, etc.)
The reason the prompt turn ended: “end_turn”, “cancelled”, or “error”
This method handles the whole lifecycle of a prompt:
- Receives user messages with optional context
- Processes the prompt using language models
- Reports language model content and tool calls to the client
- Requests permission to run tools
- Executes any requested tool calls
- Returns when the turn is complete with a stop reason
See the Handling Prompts guide for detailed information.
See protocol docs: Prompt Turn
Example
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`);
}
session.pendingPrompt = new AbortController();
try {
// Process the prompt with your LLM
await this.processPrompt(params, session);
return { stopReason: "end_turn" };
} catch (err) {
if (session.pendingPrompt.signal.aborted) {
return { stopReason: "cancelled" };
}
throw err;
} finally {
session.pendingPrompt = null;
}
}
cancel
Cancels ongoing operations for a session.
async cancel(
params: CancelNotification
): Promise<void>
The session ID to cancel operations for
This is a notification sent by the client to cancel an ongoing prompt turn.
Upon receiving this notification, the agent SHOULD:
- Stop all language model requests as soon as possible
- Abort all tool call invocations in progress
- Send any pending
session/update notifications
- Respond to the original
session/prompt request with StopReason::Cancelled
See protocol docs: Cancellation
Example
async cancel(params: acp.CancelNotification): Promise<void> {
const session = this.sessions.get(params.sessionId);
session?.pendingPrompt?.abort();
}
Optional Methods
loadSession
Loads an existing session to resume a previous conversation.
loadSession?(
params: LoadSessionRequest
): Promise<LoadSessionResponse>
MCP servers to connect to for this session
This method is only available if the agent advertises the loadSession capability.
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 notifications
See protocol docs: Loading Sessions
setSessionMode
Sets the operational mode for a session.
setSessionMode?(
params: SetSessionModeRequest
): Promise<SetSessionModeResponse | void>
The mode to switch to (must be one of the advertised modes)
Allows switching between different agent modes (e.g., “ask”, “architect”, “code”) that affect system prompts, tool availability, and permission behaviors.
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
Unstable Methods
The following methods are marked as UNSTABLE and may be removed or changed at any point:
unstable_forkSession: Forks an existing session to create a new independent session
unstable_listSessions: Lists existing sessions from the agent
unstable_resumeSession: Resumes an existing session without returning previous messages
unstable_setSessionModel: Selects a model for a given session
These are experimental features not yet part of the official ACP specification.
Extension Methods
extMethod: Allows custom request handlers not part of the ACP specification
extNotification: Allows custom notification handlers not part of the ACP specification
Complete Example
import * as acp from "@agentprotocol/acp";
interface AgentSession {
workingDirectory?: string;
history: acp.Message[];
pendingPrompt: AbortController | null;
}
class MyAgent implements acp.Agent {
private connection: acp.AgentSideConnection;
private sessions: Map<string, AgentSession>;
constructor(connection: acp.AgentSideConnection) {
this.connection = connection;
this.sessions = new Map();
}
async initialize(params: acp.InitializeRequest): Promise<acp.InitializeResponse> {
return {
protocolVersion: acp.PROTOCOL_VERSION,
agentCapabilities: {
loadSession: false,
},
};
}
async newSession(params: acp.NewSessionRequest): Promise<acp.NewSessionResponse> {
const sessionId = crypto.randomUUID();
this.sessions.set(sessionId, {
workingDirectory: params.workingDirectory,
history: [],
pendingPrompt: null,
});
return { sessionId };
}
async authenticate(params: acp.AuthenticateRequest): Promise<void> {
// Implement authentication if needed
}
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`);
}
session.pendingPrompt = new AbortController();
try {
// Process the prompt with your LLM
await this.processPrompt(params, session);
return { stopReason: "end_turn" };
} catch (err) {
if (session.pendingPrompt.signal.aborted) {
return { stopReason: "cancelled" };
}
throw err;
} finally {
session.pendingPrompt = null;
}
}
async cancel(params: acp.CancelNotification): Promise<void> {
this.sessions.get(params.sessionId)?.pendingPrompt?.abort();
}
private async processPrompt(
params: acp.PromptRequest,
session: AgentSession
): Promise<void> {
// Your prompt processing logic here
}
}