or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

agent-connection.mdclient-connection.mderrors.mdindex.mdinterfaces.mdprotocol-types.mdstream.md
tile.json

interfaces.mddocs/

Protocol Interfaces

The ACP SDK defines two core interfaces that implementations must provide: Agent and Client. These interfaces define the contract for communication between agents and clients.

Agent Interface

The Agent interface defines the methods that all ACP-compliant agents must implement. Agents are programs that use generative AI to autonomously modify code.

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

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

newSession

Creates a new conversation session with the agent.

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 return an auth_required error if the agent requires authentication.

authenticate

Authenticates the client using the specified authentication method.

Called when the agent requires authentication before allowing session creation. The client provides the authentication method ID that was advertised during initialization.

After successful authentication, the client can proceed to create sessions without receiving an auth_required error.

prompt

Processes a user prompt within a session.

This method handles the whole lifecycle of a prompt:

  • Receives user messages with optional context (files, images, etc.)
  • 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

cancel

Cancels ongoing operations for a session.

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

Optional Methods

loadSession

Loads an existing session to resume a previous conversation.

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

setSessionMode

Sets the operational mode for a session.

Allows switching between different agent modes (e.g., "ask", "architect", "code") that affect system prompts, tool availability, and permission behaviors.

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.

setSessionModel

UNSTABLE - Selects a model for a given session.

This capability is not part of the spec yet and may be removed or changed at any point.

extMethod

Extension method for handling arbitrary requests that are not part of the ACP spec.

To help avoid conflicts, it's a good practice to prefix extension methods with a unique identifier such as domain name.

extNotification

Extension notification for handling arbitrary notifications that are not part of the ACP spec.

Client Interface

The Client interface defines the methods that all ACP-compliant clients must implement. Clients are typically code editors (IDEs, text editors) that provide the interface between users and AI agents.

interface Client {
  // Required methods
  requestPermission(params: RequestPermissionRequest): Promise<RequestPermissionResponse>;
  sessionUpdate(params: SessionNotification): Promise<void>;

  // Optional file system capabilities
  readTextFile?(params: ReadTextFileRequest): Promise<ReadTextFileResponse>;
  writeTextFile?(params: WriteTextFileRequest): Promise<WriteTextFileResponse>;

  // Optional terminal capabilities
  createTerminal?(params: CreateTerminalRequest): Promise<CreateTerminalResponse>;
  terminalOutput?(params: TerminalOutputRequest): Promise<TerminalOutputResponse>;
  releaseTerminal?(params: ReleaseTerminalRequest): Promise<ReleaseTerminalResponse | void>;
  waitForTerminalExit?(params: WaitForTerminalExitRequest): Promise<WaitForTerminalExitResponse>;
  killTerminal?(params: KillTerminalCommandRequest): Promise<KillTerminalResponse | void>;

  // Optional extension points
  extMethod?(method: string, params: Record<string, unknown>): Promise<Record<string, unknown>>;
  extNotification?(method: string, params: Record<string, unknown>): Promise<void>;
}

Required Methods

requestPermission

Requests permission from the user for a tool call operation.

Called by the agent when it needs user authorization before executing a potentially sensitive operation. The client should present the options to the user and return their decision.

If the client cancels the prompt turn via session/cancel, it MUST respond to this request with RequestPermissionOutcome::Cancelled.

sessionUpdate

Handles session update notifications from the agent.

This is a notification endpoint (no response expected) that receives real-time updates about session progress, including message chunks, tool calls, and execution plans.

Note: Clients SHOULD continue accepting tool call updates even after sending a session/cancel notification, as the agent may send final updates before responding with the cancelled stop reason.

Optional File System Methods

readTextFile

Reads content from a text file in the client's file system.

Only available if the client advertises the fs.readTextFile capability. Allows the agent to access file contents within the client's environment.

writeTextFile

Writes content to a text file in the client's file system.

Only available if the client advertises the fs.writeTextFile capability. Allows the agent to create or modify files within the client's environment.

Optional Terminal Methods

createTerminal

Creates a new terminal to execute a command.

Only available if the terminal capability is set to true. The agent must call releaseTerminal when done with the terminal to free resources.

terminalOutput

Gets the current output and exit status of a terminal.

Returns immediately without waiting for the command to complete. If the command has already exited, the exit status is included.

releaseTerminal

Releases a terminal and frees all associated resources.

The command is killed if it hasn't exited yet. After release, the terminal ID becomes invalid for all other terminal methods. Tool calls that already contain the terminal ID continue to display its output.

waitForTerminalExit

Waits for a terminal command to exit and returns its exit status.

This method returns once the command completes, providing the exit code and/or signal that terminated the process.

killTerminal

Kills a terminal command without releasing the terminal.

While releaseTerminal also kills the command, this method keeps the terminal ID valid so it can be used with other methods. Useful for implementing command timeouts that terminate the command and then retrieve the final output.

Note: Call releaseTerminal when the terminal is no longer needed.

Optional Extension Methods

extMethod

Extension method for handling arbitrary requests that are not part of the ACP spec.

To help avoid conflicts, it's a good practice to prefix extension methods with a unique identifier such as domain name.

extNotification

Extension notification for handling arbitrary notifications that are not part of the ACP spec.

Implementation Examples

Basic Agent Implementation

import { Agent, InitializeRequest, NewSessionRequest, PromptRequest, AuthenticateRequest, CancelNotification } from '@agentclientprotocol/sdk';

const agent: Agent = {
  async initialize(params: InitializeRequest) {
    return {
      protocolVersion: 1,
      agentCapabilities: {
        mcpCapabilities: { http: true, sse: false },
        promptCapabilities: { image: true, audio: false, embeddedContext: true }
      },
      agentInfo: {
        name: 'my-agent',
        version: '1.0.0'
      }
    };
  },

  async newSession(params: NewSessionRequest) {
    const sessionId = crypto.randomUUID();
    return {
      sessionId,
      modes: {
        availableModes: [
          {
            id: 'code',
            name: 'Code Mode',
            description: 'AI-powered code editing'
          },
          {
            id: 'ask',
            name: 'Ask Mode',
            description: 'Answer questions without editing code'
          }
        ],
        currentModeId: 'code'
      }
    };
  },

  async authenticate(params: AuthenticateRequest) {
    // Validate credentials
    if (validateAuth(params.methodId)) {
      return {};
    }
    throw RequestError.authRequired();
  },

  async prompt(params: PromptRequest) {
    const { sessionId, prompt } = params;

    // Process prompt with language model
    const response = await processWithLLM(prompt);

    return {
      stopReason: 'end_turn'
    };
  },

  async cancel(params: CancelNotification) {
    // Cancel ongoing operations for the session
    cancelSession(params.sessionId);
  },

  // Optional methods
  async loadSession(params: LoadSessionRequest) {
    const history = await loadSessionHistory(params.sessionId);
    // Stream history via session/update notifications
    return {
      modes: getSessionModes(params.sessionId)
    };
  },

  async setSessionMode(params: SetSessionModeRequest) {
    updateSessionMode(params.sessionId, params.modeId);
    return {};
  }
};

Basic Client Implementation

import { Client, RequestPermissionRequest, SessionNotification, ReadTextFileRequest, WriteTextFileRequest } from '@agentclientprotocol/sdk';
import * as fs from 'fs/promises';

const client: Client = {
  async requestPermission(params: RequestPermissionRequest) {
    // Show permission dialog to user
    const result = await showPermissionDialog({
      toolCall: params.toolCall,
      options: params.options
    });

    if (result.cancelled) {
      return { outcome: { outcome: 'cancelled' } };
    }

    return {
      outcome: { outcome: 'selected', optionId: result.selectedOptionId }
    };
  },

  async sessionUpdate(params: SessionNotification) {
    switch (params.update.sessionUpdate) {
      case 'agent_message_chunk':
        // Display streaming content to user
        appendToDisplay(params.update.content);
        break;

      case 'tool_call':
        // Show tool execution
        showToolCall(params.update);
        break;

      case 'plan':
        // Display execution plan
        showPlan(params.update.entries);
        break;

      case 'available_commands_update':
        // Update command palette
        updateCommands(params.update.availableCommands);
        break;

      case 'current_mode_update':
        // Update mode indicator
        updateModeIndicator(params.update.currentModeId);
        break;
    }
  },

  // Optional file system methods
  async readTextFile(params: ReadTextFileRequest) {
    try {
      let content = await fs.readFile(params.path, 'utf-8');

      // Handle line range if specified
      if (params.line !== undefined) {
        const lines = content.split('\n');
        const start = params.line - 1;
        const end = params.limit ? start + params.limit : lines.length;
        content = lines.slice(start, end).join('\n');
      }

      return { content };
    } catch (error) {
      throw RequestError.resourceNotFound(params.path);
    }
  },

  async writeTextFile(params: WriteTextFileRequest) {
    await fs.writeFile(params.path, params.content);
    return {};
  },

  // Optional terminal methods
  async createTerminal(params: CreateTerminalRequest) {
    const terminal = createTerminalProcess(params);
    const terminalId = registerTerminal(terminal);

    return { terminalId };
  },

  async terminalOutput(params: TerminalOutputRequest) {
    const terminal = getTerminal(params.terminalId);
    return {
      output: terminal.getOutput(),
      exitStatus: terminal.exitStatus,
      truncated: terminal.wasTruncated()
    };
  },

  async releaseTerminal(params: ReleaseTerminalRequest) {
    const terminal = getTerminal(params.terminalId);
    terminal.kill();
    unregisterTerminal(params.terminalId);
    return {};
  },

  async waitForTerminalExit(params: WaitForTerminalExitRequest) {
    const terminal = getTerminal(params.terminalId);
    const { exitCode, signal } = await terminal.waitForExit();
    return { exitCode, signal };
  },

  async killTerminal(params: KillTerminalCommandRequest) {
    const terminal = getTerminal(params.terminalId);
    terminal.kill();
    return {};
  }
};

Capability Negotiation

Capabilities are negotiated during the initialize handshake:

Client Capabilities

interface ClientCapabilities {
  fs?: FileSystemCapability;
  terminal?: boolean;
}

interface FileSystemCapability {
  readTextFile?: boolean;
  writeTextFile?: boolean;
}

Example:

const clientCapabilities = {
  fs: {
    readTextFile: true,
    writeTextFile: true
  },
  terminal: true
};

Agent Capabilities

interface AgentCapabilities {
  loadSession?: boolean;
  setSessionMode?: boolean;
  mcp?: McpCapabilities;
  prompt?: PromptCapabilities;
}

interface McpCapabilities {
  http?: boolean;
  sse?: boolean;
}

interface PromptCapabilities {
  image?: boolean;
  audio?: boolean;
  embeddedContext?: boolean;
}

Example:

const agentCapabilities = {
  loadSession: true,
  mcpCapabilities: {
    http: true,
    sse: false
  },
  promptCapabilities: {
    image: true,
    audio: false,
    embeddedContext: true
  }
};

Notes

  • Both interfaces support optional extension methods for custom functionality
  • Capabilities must be negotiated during initialization
  • Optional methods should only be called if the corresponding capability is advertised
  • All methods are async and return Promises
  • Implementations should handle errors appropriately using RequestError