Skip to main content
The Agent-Client Protocol defines two distinct roles: Agents and Clients. Each has specific responsibilities and capabilities in the communication flow.

Overview

Agent

AI-powered programs that autonomously write and modify code using language models

Client

Development environments (IDEs, editors) that provide the interface and control access to resources

What is an Agent?

An Agent is a program that uses generative AI to autonomously modify code. Agents receive prompts from users (via the client), process them using language models, and execute tasks using tools.

Agent Interface

The SDK defines the Agent interface that all ACP-compliant agents must implement:
src/acp.ts
export interface Agent {
  // Connection lifecycle
  initialize(params: InitializeRequest): Promise<InitializeResponse>;
  authenticate(params: AuthenticateRequest): Promise<AuthenticateResponse | void>;
  
  // Session management
  newSession(params: NewSessionRequest): Promise<NewSessionResponse>;
  loadSession?(params: LoadSessionRequest): Promise<LoadSessionResponse>;
  unstable_resumeSession?(params: ResumeSessionRequest): Promise<ResumeSessionResponse>;
  unstable_forkSession?(params: ForkSessionRequest): Promise<ForkSessionResponse>;
  unstable_listSessions?(params: ListSessionsRequest): Promise<ListSessionsResponse>;
  
  // Session operations
  prompt(params: PromptRequest): Promise<PromptResponse>;
  cancel(params: CancelNotification): Promise<void>;
  setSessionMode?(params: SetSessionModeRequest): Promise<SetSessionModeResponse | void>;
  unstable_setSessionModel?(params: SetSessionModelRequest): Promise<SetSessionModelResponse | void>;
  setSessionConfigOption?(params: SetSessionConfigOptionRequest): Promise<SetSessionConfigOptionResponse>;
  
  // Extensions
  extMethod?(method: string, params: Record<string, unknown>): Promise<Record<string, unknown>>;
  extNotification?(method: string, params: Record<string, unknown>): Promise<void>;
}

Agent Responsibilities

Agents are responsible for:
  1. Processing Prompts - Understanding user requests and generating appropriate responses
  2. Managing Language Models - Interfacing with LLMs to generate code and responses
  3. Executing Tool Calls - Performing operations like reading files, running commands
  4. Streaming Updates - Sending real-time progress updates to the client
  5. Session State - Maintaining conversation history and context
  6. MCP Integration - Connecting to Model Context Protocol servers for additional tools
Agents initiate most actions but must request permission from clients for sensitive operations.

Example: Basic Agent Structure

import { Agent, AgentSideConnection, ndJsonStream } from "@anoma/acp-sdk";

class MyAgent implements Agent {
  async initialize(params) {
    return {
      protocolVersion: 1,
      capabilities: {
        promptCapabilities: {
          multiTurn: true,
          supportedContentTypes: ["text", "image"]
        }
      },
      agentInfo: {
        name: "My AI Agent",
        version: "1.0.0"
      }
    };
  }
  
  async newSession(params) {
    const sessionId = crypto.randomUUID();
    // Initialize session state
    return { sessionId, availableModes: [] };
  }
  
  async prompt(params) {
    // Process the prompt with an LLM
    // Send updates via connection.sessionUpdate()
    return { stopReason: "endTurn" };
  }
  
  // Implement other required methods...
}

const stream = ndJsonStream(Deno.stdout.writable, Deno.stdin.readable);
const connection = new AgentSideConnection(
  (conn) => new MyAgent(conn),
  stream
);

What is a Client?

A Client is typically a code editor or IDE that provides the interface between users and AI agents. Clients manage the development environment, handle user interactions, and control access to resources.

Client Interface

The SDK defines the Client interface:
src/acp.ts
export interface Client {
  // Permission management
  requestPermission(
    params: RequestPermissionRequest
  ): Promise<RequestPermissionResponse>;
  
  // Session updates
  sessionUpdate(params: SessionNotification): Promise<void>;
  
  // File system operations (optional)
  readTextFile?(params: ReadTextFileRequest): Promise<ReadTextFileResponse>;
  writeTextFile?(params: WriteTextFileRequest): Promise<WriteTextFileResponse>;
  
  // Terminal operations (optional)
  createTerminal?(params: CreateTerminalRequest): Promise<CreateTerminalResponse>;
  terminalOutput?(params: TerminalOutputRequest): Promise<TerminalOutputResponse>;
  waitForTerminalExit?(params: WaitForTerminalExitRequest): Promise<WaitForTerminalExitResponse>;
  killTerminal?(params: KillTerminalRequest): Promise<KillTerminalResponse | void>;
  releaseTerminal?(params: ReleaseTerminalRequest): Promise<ReleaseTerminalResponse | void>;
  
  // Extensions
  extMethod?(method: string, params: Record<string, unknown>): Promise<Record<string, unknown>>;
  extNotification?(method: string, params: Record<string, unknown>): Promise<void>;
}

Client Responsibilities

Clients are responsible for:
  1. User Interface - Displaying agent responses, tool calls, and progress updates
  2. Resource Access - Providing controlled access to files, terminals, and other resources
  3. Permission Management - Prompting users for authorization before sensitive operations
  4. Environment Management - Managing working directories, MCP server connections
  5. Session Persistence - Storing and retrieving conversation history
  6. Capability Advertisement - Informing agents which features are available
Clients have the final say on all operations. They can deny any agent request and cancel operations at any time.

Example: Basic Client Structure

import { Client, ClientSideConnection, ndJsonStream } from "@anoma/acp-sdk";

class MyClient implements Client {
  async requestPermission(params) {
    // Show UI to user and get their choice
    const userChoice = await showPermissionDialog(params.options);
    return { outcome: userChoice };
  }
  
  async sessionUpdate(params) {
    // Display the update in the UI
    console.log("Agent update:", params.content);
  }
  
  async readTextFile(params) {
    const content = await Deno.readTextFile(params.path);
    return { content };
  }
  
  async writeTextFile(params) {
    await Deno.writeTextFile(params.path, params.content);
    return {};
  }
  
  // Implement other methods...
}

const stream = ndJsonStream(agentProcess.stdout, agentProcess.stdin);
const agent = new ClientSideConnection(
  () => new MyClient(),
  stream
);

Interaction Flow

Here’s how agents and clients work together:

Capabilities and Features

Both sides advertise capabilities during initialization:
{
  promptCapabilities: {
    multiTurn: true,
    supportedContentTypes: ["text", "image", "audio"]
  },
  loadSession: true,
  sessionCapabilities: {
    fork: true,
    resume: true,
    list: true
  },
  mcpCapabilities: {
    supportedVersions: ["2024-11-05"]
  }
}
{
  fs: {
    readTextFile: true,
    writeTextFile: true
  },
  terminal: true,
  authCapabilities: {
    terminal: true
  }
}
Optional methods (marked with ?) are only available if the corresponding capability is advertised during initialization.

Key Differences

AspectAgentClient
Initiates ActionsYes (prompts, tool calls)Limited (initialization, cancel)
Language ModelsInterfaces with LLMsNo LLM access
Resource AccessRequests accessProvides controlled access
User InteractionIndirect (via client)Direct (UI)
Decision MakingAutonomous with AIUser-driven
Session StorageOptionalTypically required

Extension Methods

Both agents and clients can implement custom methods beyond the ACP specification:
// Agent sends custom request to client
await connection.extMethod("myeditor.showPanel", {
  panelId: "debugger"
});

// Client handles custom methods
class MyClient implements Client {
  async extMethod(method: string, params: Record<string, unknown>) {
    if (method === "myeditor.showPanel") {
      // Handle custom method
      return { success: true };
    }
    throw new Error(`Unknown method: ${method}`);
  }
}
To avoid conflicts, prefix extension methods with a unique identifier (e.g., your domain name).

Learn More

Connections

Learn how to establish agent-client connections

Sessions

Understand session lifecycle and management

Build an Agent

Step-by-step guide to building your first agent

Build a Client

Step-by-step guide to building your first client

Build docs developers (and LLMs) love