Overview
The ClientSideConnection class provides the client’s view of an ACP connection. It implements the Agent interface, giving you access to all agent methods.
Constructor
Creates a new client-side connection to an agent.
new ClientSideConnection(
toClient: (agent: Agent) => Client,
stream: Stream
)
toClient
(agent: Agent) => Client
required
A function that creates a Client handler to process incoming agent requests. The function receives the connection instance (implementing the Agent interface) and should return your Client implementation.
The bidirectional message stream for communication. Typically created using ndJsonStream() for stdio-based connections.
Example
import * as acp from "@agentclientprotocol/acp";
import { spawn } from "node:child_process";
import { Writable, Readable } from "node:stream";
// Spawn the agent process
const agentProcess = spawn("my-agent", ["--flag"]);
// Create bidirectional stream
const input = Writable.toWeb(agentProcess.stdin);
const output = Readable.toWeb(agentProcess.stdout) as ReadableStream<Uint8Array>;
const stream = acp.ndJsonStream(input, output);
// Create the connection
const client = new MyClient();
const connection = new acp.ClientSideConnection(
(_agent) => client,
stream
);
Methods
The ClientSideConnection implements the full Agent interface:
initialize()
Establishes the connection and negotiates protocol capabilities.
await connection.initialize(
params: InitializeRequest
): Promise<InitializeResponse>
The protocol version to use (e.g., acp.PROTOCOL_VERSION).
params.clientCapabilities
ClientCapabilities
required
Capabilities advertised by the client (file system, terminal support, etc.).
The negotiated protocol version.
Capabilities supported by the agent.
Available authentication methods.
Example
const initResult = await connection.initialize({
protocolVersion: acp.PROTOCOL_VERSION,
clientCapabilities: {
fs: {
readTextFile: true,
writeTextFile: true,
},
terminal: true,
},
});
console.log(`Connected using protocol v${initResult.protocolVersion}`);
newSession()
Creates a new conversation session with the agent.
await connection.newSession(
params: NewSessionRequest
): Promise<NewSessionResponse>
The working directory for the session (absolute path).
MCP servers the agent should connect to for this session.
Unique identifier for the created session.
The initial mode of the session.
Modes available for this session.
Example
const session = await connection.newSession({
cwd: "/home/user/project",
mcpServers: [],
});
console.log(`Session created: ${session.sessionId}`);
loadSession()
Loads an existing session to resume a previous conversation.
Only available if the agent advertises the loadSession capability.
await connection.loadSession(
params: LoadSessionRequest
): Promise<LoadSessionResponse>
The ID of the session to load.
MCP servers to connect to for this session.
prompt()
Processes a user prompt within a session.
await connection.prompt(
params: PromptRequest
): Promise<PromptResponse>
The session ID to send the prompt to.
Array of content items (text, images, files, etc.).
Why the agent stopped (e.g., "finished", "cancelled", "error").
Example
const result = await connection.prompt({
sessionId: session.sessionId,
prompt: [
{
type: "text",
text: "Refactor the parseConfig function",
},
],
});
console.log(`Agent stopped: ${result.stopReason}`);
cancel()
Cancels ongoing operations for a session.
await connection.cancel(
params: CancelNotification
): Promise<void>
The session ID to cancel operations for.
Example
// Cancel the ongoing prompt
await connection.cancel({
sessionId: session.sessionId,
});
setSessionMode()
Sets the operational mode for a session.
await connection.setSessionMode(
params: SetSessionModeRequest
): Promise<SetSessionModeResponse>
The mode to switch to (must be in availableModes).
authenticate()
Authenticates the client using the specified authentication method.
await connection.authenticate(
params: AuthenticateRequest
): Promise<AuthenticateResponse>
The ID of the authentication method to use.
setSessionConfigOption()
Sets a configuration option for a session.
await connection.setSessionConfigOption(
params: SetSessionConfigOptionRequest
): Promise<SetSessionConfigOptionResponse>
Properties
signal
AbortSignal that aborts when the connection closes.
const signal: AbortSignal = connection.signal;
Useful for:
- Listening for connection closure
- Checking connection status synchronously
- Passing to other APIs for automatic cancellation
Example
// Listen for closure
connection.signal.addEventListener('abort', () => {
console.log('Connection closed - cleaning up');
cleanupResources();
});
// Check status
if (connection.signal.aborted) {
console.log('Connection is already closed');
}
// Pass to fetch for automatic cancellation
fetch(url, { signal: connection.signal });
closed
Promise that resolves when the connection closes.
const closed: Promise<void> = connection.closed;
Example
// Wait for closure
await connection.closed;
console.log('Connection closed - performing cleanup');
// Or use it in a race
const result = await Promise.race([
connection.prompt({ sessionId, prompt }),
connection.closed.then(() => {
throw new Error('Connection closed unexpectedly');
}),
]);
Extension Methods
extMethod()
Sends an arbitrary request that is not part of the ACP spec.
await connection.extMethod(
method: string,
params: Record<string, unknown>
): Promise<Record<string, unknown>>
To avoid conflicts, prefix extension methods with a unique identifier (e.g., domain name).
extNotification()
Sends an arbitrary notification that is not part of the ACP spec.
await connection.extNotification(
method: string,
params: Record<string, unknown>
): Promise<void>
Complete Example
import * as acp from "@agentclientprotocol/acp";
import { spawn } from "node:child_process";
import { Writable, Readable } from "node:stream";
class MyClient implements acp.Client {
async requestPermission(params: acp.RequestPermissionRequest) {
// Implementation
return { outcome: { outcome: "approved" } };
}
async sessionUpdate(params: acp.SessionNotification) {
console.log("Update:", params.update);
}
}
async function main() {
// Spawn agent
const agentProcess = spawn("my-agent");
const stream = acp.ndJsonStream(
Writable.toWeb(agentProcess.stdin),
Readable.toWeb(agentProcess.stdout) as ReadableStream<Uint8Array>
);
// Create connection
const client = new MyClient();
const connection = new acp.ClientSideConnection(
(_agent) => client,
stream
);
// Initialize
await connection.initialize({
protocolVersion: acp.PROTOCOL_VERSION,
clientCapabilities: { fs: { readTextFile: true } },
});
// Create session
const session = await connection.newSession({
cwd: process.cwd(),
mcpServers: [],
});
// Send prompt
await connection.prompt({
sessionId: session.sessionId,
prompt: [{ type: "text", text: "Hello!" }],
});
// Wait for completion
await connection.closed;
}
main().catch(console.error);
See Also