> ## 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.

# Implementing the Agent Interface

> Learn how to implement the Agent interface required by ACP

## 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.

```typescript theme={null}
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.

```typescript theme={null}
async initialize(
  params: InitializeRequest
): Promise<InitializeResponse>
```

<ParamField path="params.protocolVersion" type="string" required>
  The protocol version requested by the client
</ParamField>

<ParamField path="params.clientCapabilities" type="object" required>
  Capabilities advertised by the client (file system access, terminal support, etc.)
</ParamField>

<ResponseField name="protocolVersion" type="string" required>
  The protocol version the agent will use (should match the client's version)
</ResponseField>

<ResponseField name="agentCapabilities" type="object" required>
  Capabilities advertised by the agent (session loading, modes, etc.)
</ResponseField>

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](https://agentclientprotocol.com/protocol/initialization)

#### Example

```typescript theme={null}
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.

```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>

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](https://agentclientprotocol.com/protocol/session-setup)

#### Example

```typescript theme={null}
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.

```typescript theme={null}
async authenticate(
  params: AuthenticateRequest
): Promise<AuthenticateResponse | void>
```

<ParamField path="params.method" type="string" required>
  The authentication method ID that was advertised during initialization
</ParamField>

<ParamField path="params.credentials" type="object">
  Optional credentials provided by the client
</ParamField>

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](https://agentclientprotocol.com/protocol/initialization)

#### Example

```typescript theme={null}
async authenticate(params: acp.AuthenticateRequest): Promise<void> {
  // No authentication needed in this example
  return;
}
```

### prompt

Processes a user prompt within a session.

```typescript theme={null}
async prompt(
  params: PromptRequest
): Promise<PromptResponse>
```

<ParamField path="params.sessionId" type="string" required>
  The session ID to process the prompt in
</ParamField>

<ParamField path="params.messages" type="Message[]" required>
  The user messages with optional context (files, images, etc.)
</ParamField>

<ResponseField name="stopReason" type="StopReason" required>
  The reason the prompt turn ended: "end\_turn", "cancelled", or "error"
</ResponseField>

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](/agents/handling-prompts) guide for detailed information.

See protocol docs: [Prompt Turn](https://agentclientprotocol.com/protocol/prompt-turn)

#### Example

```typescript theme={null}
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.

```typescript theme={null}
async cancel(
  params: CancelNotification
): Promise<void>
```

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

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](https://agentclientprotocol.com/protocol/prompt-turn#cancellation)

#### Example

```typescript theme={null}
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.

```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>

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](https://agentclientprotocol.com/protocol/session-setup#loading-sessions)

### setSessionMode

Sets the operational mode for a session.

```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>

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](https://agentclientprotocol.com/protocol/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

```typescript theme={null}
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
  }
}
```
