Skip to main content

Overview

The AgentSideConnection class provides the agent’s view of an ACP connection, allowing agents to communicate with clients. It handles the bidirectional JSON-RPC communication and provides methods for sending session updates, requesting permissions, and accessing client capabilities. See protocol docs: Agent

Constructor

constructor(
  toAgent: (conn: AgentSideConnection) => Agent,
  stream: Stream
)
toAgent
function
required
A factory function that creates an Agent handler to process incoming client requests. The function receives the AgentSideConnection instance as a parameter.
stream
Stream
required
The bidirectional message stream for communication. Typically created using ndJsonStream() for stdio-based connections.

Example

import * as acp from "@agentprotocol/acp";
import { Readable, Writable } from "node:stream";

class MyAgent implements acp.Agent {
  constructor(private connection: acp.AgentSideConnection) {}
  // ... implement Agent interface
}

const input = Writable.toWeb(process.stdout);
const output = Readable.toWeb(process.stdin);
const stream = acp.ndJsonStream(input, output);

const connection = new acp.AgentSideConnection(
  (conn) => new MyAgent(conn),
  stream
);

Methods

sessionUpdate

Sends session update notifications to the client.
async sessionUpdate(params: SessionNotification): Promise<void>
params
SessionNotification
required
The session update to send, containing the session ID and update content (message chunks, tool calls, etc.)
This is a notification endpoint (no response expected) that sends real-time updates about session progress, including message chunks, tool calls, and execution plans.
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.
See protocol docs: Agent Reports Output

requestPermission

Requests permission from the user for a tool call operation.
async requestPermission(
  params: RequestPermissionRequest
): Promise<RequestPermissionResponse>
params
RequestPermissionRequest
required
The permission request containing the session ID, tool call details, and available options
outcome
RequestPermissionOutcome
required
The user’s decision, including the selected option ID or cancellation status
Called by the agent when it needs user authorization before executing a potentially sensitive operation. The client presents the options to the user and returns their decision.
If the client cancels the prompt turn via session/cancel, it MUST respond to this request with RequestPermissionOutcome::Cancelled.
See protocol docs: Requesting Permission

readTextFile

Reads content from a text file in the client’s file system.
async readTextFile(
  params: ReadTextFileRequest
): Promise<ReadTextFileResponse>
params.sessionId
string
required
The session ID making the request
params.path
string
required
Absolute path to the file to read
content
string
required
The file contents as a string
Only available if the client advertises the fs.readTextFile capability during initialization.
See protocol docs: Client

writeTextFile

Writes content to a text file in the client’s file system.
async writeTextFile(
  params: WriteTextFileRequest
): Promise<WriteTextFileResponse>
params.sessionId
string
required
The session ID making the request
params.path
string
required
Absolute path to the file to write
params.content
string
required
The content to write to the file
Only available if the client advertises the fs.writeTextFile capability during initialization.
Allows the agent to create or modify files within the client’s environment. See protocol docs: Client

createTerminal

Executes a command in a new terminal.
async createTerminal(
  params: CreateTerminalRequest
): Promise<TerminalHandle>
params.sessionId
string
required
The session ID creating the terminal
params.command
string
required
The command to execute
params.args
string[]
Optional command arguments
params.workingDirectory
string
Optional working directory for the command
TerminalHandle
object
required
A handle to control and monitor the terminal
Returns a TerminalHandle that can be used to get output, wait for exit, kill the command, or release the terminal. The terminal can also be embedded in tool calls by using its ID in ToolCallContent with type “terminal”.

extMethod

Sends an arbitrary request that is not part of the ACP specification.
async extMethod(
  method: string,
  params: Record<string, unknown>
): Promise<Record<string, unknown>>
method
string
required
The extension method name
params
Record<string, unknown>
required
The method parameters
Allows the agent to send custom requests to the client.

extNotification

Sends an arbitrary notification that is not part of the ACP specification.
async extNotification(
  method: string,
  params: Record<string, unknown>
): Promise<void>
method
string
required
The extension notification name
params
Record<string, unknown>
required
The notification parameters
Allows the agent to send custom notifications to the client.

Properties

signal

An AbortSignal that aborts when the connection closes.
get signal(): AbortSignal
This signal can be used to:
  • Listen for connection closure
  • Check connection status synchronously
  • Pass to other APIs (fetch, setTimeout) for automatic cancellation
const connection = new AgentSideConnection(agent, stream);

// Listen for closure
connection.signal.addEventListener('abort', () => {
  console.log('Connection closed - performing cleanup');
});

// Check status
if (connection.signal.aborted) {
  console.log('Connection is already closed');
}

// Pass to other APIs
fetch(url, { signal: connection.signal });

closed

A promise that resolves when the connection closes.
get closed(): Promise<void>
The connection closes when the underlying stream ends, either normally or due to an error. Once closed, the connection cannot send or receive any more messages.
const connection = new AgentSideConnection(agent, stream);
await connection.closed;
console.log('Connection closed - performing cleanup');

Build docs developers (and LLMs) love