Agent Client Protocol (ACP) TypeScript SDK

repository·main·Indexed 42 days ago

https://github.com/agentclientprotocol/typescript-sdk

The official TypeScript implementation of the Agent Client Protocol (ACP), a standard for communication between code editors (Clients) and AI-powered coding agents (Agents). Version 1.4.0 provides an app-style API for registering handlers and managing connections via HTTP, WebSockets, and JSON-RPC. Includes support for experimental v2 features and high-level session orchestration using buildSession and withSession.

Tokens
36.5K
Snippets
102
Records
158
Agent score
53%

What's inside ACP

  1. WebSocket Transport: Server-side upgrade handling

    main

    When building compliant WebSocket servers, use an upgrade hook rather than relying on an already-upgraded socket.

    The example server uses createNodeWebSocketUpgradeHandler, which creates the ACP connection before the upgrade completes. This allows the server to add the Acp-Connection-Id header to the 101 Switching Protocols response. Frameworks that only expose the socket after the upgrade has finished cannot add this required header.

  2. HTTP Transport: Cookie management in `createHttpStream`

    main

    When using createHttpStream, the client manages cookies for the lifetime of a single stream by default. It performs the following:

    • Sends credentials on fetch requests.
    • Captures Set-Cookie headers from responses.
    • Merges captured cookies with caller-provided Cookie headers.
    • Reuses these cookies for SSE (Server-Sent Events) connections, session SSE, POST, and DELETE requests.

    To disable this behavior for stateless transports, pass the option cookies: "omit" to createHttpStream.

  3. WebSocket Transport: Client-side authentication

    main

    The method for authenticating WebSocket connections depends on the environment:

    • Node.js Clients: You can pass the Node ws constructor to createWebSocketStream to allow sending custom headers during the WebSocket handshake.
    • Browser Clients: Browsers do not allow custom WebSocket handshake headers. For browser-based clients using createWebSocketStream, use cookies or URL-level authentication instead of custom headers.
  4. Understand Agent and Client Handler Contexts

    main

    When implementing handlers using onRequest or onNotification, the SDK provides a context object (ctx) that allows you to interact with the peer. The available properties on the context depend on whether you are implementing an Agent or a Client:

    • Agent Handlers (AgentHandlerContext): Include params (the incoming request data) and client (the handle used to communicate back to the client).
    • Client Handlers (ClientHandlerContext): Include params and agent (the handle used to communicate back to the agent).

    Connection handles (returned by .connect()) also expose these peer contexts for connection-scoped work.

    // Agent handler context example
    acp.agent().onRequest(acp.methods.agent.session.prompt, async (ctx) => {
      // ctx.params contains the request data
      // ctx.client is used to notify or request from the client
      await ctx.client.notify(acp.methods.client.session.update, { ... });
      return { stopReason: "end_turn" };
    });
    
    // Client handler context example
    acp.client().onRequest(acp.methods.client.session.requestPermission, (ctx) => {
      // ctx.params contains the request data
      // ctx.agent is used to request or notify the agent
      return { outcome: { outcome: "cancelled" } };
    });
  5. Manage Active Sessions with buildSession and withSession

    main

    Instead of manually managing newSession, prompt, and session/update notifications, use the high-level session API to orchestrate client-agent flows.

    • buildSession(cwd): Creates a session builder. Use this when you need to pass a NewSessionRequest configuration (like MCP servers or _meta).
    • withSession(callback): Executes a callback within the context of an active session. It automatically disposes of session handlers when the callback finishes, even if an error is thrown.
    • session.prompt(prompt): Sends a prompt to the agent.
    • session.nextUpdate(): An async iterator/method to wait for the next session update (e.g., message chunks or status changes).
    • session.readText(): A convenience method that collects all text from agent_message_chunk updates and returns the full string once the prompt response is complete.
    • withAdditionalDirectories(paths): Used with the session builder to add absolute paths as additional workspace roots.
    // Using the high-level session API to prompt and read text
    const text = await acp.client().connectWith(stream, (ctx) =>
      ctx.buildSession("/workspace/project").withSession(async (session) => {
        session.prompt("Explain the repo");
        return session.readText();
      }),
    );
    
    // Manual loop for handling updates
    await acp.client().connectWith(stream, (ctx) =>
      ctx.buildSession("/workspace/project").withSession(async (session) => {
        session.prompt("Summarize this project");
    
        for (;;) {
          const message = await session.nextUpdate();
          if (message.kind === "stop") {
            return message.response;
          }
          console.log(message.update.sessionUpdate);
        }
      }),
    );
  6. Run the Example Agent manually

    main

    To run the minimal agent implementation (agent.ts) directly in your terminal, use npx tsx. You can then interact with it using JSON-RPC messages.

    1. Start the agent:
    npx tsx src/examples/agent.ts
    1. Send an initialization request via JSON-RPC:
    {"jsonrpc":"2.0","id":0,"method":"initialize","params":{"protocolVersion":1}}
    1. The agent should respond with its capabilities, such as:
    {"jsonrpc":"2.0","id":0,"result":{"protocolVersion":1,"agentCapabilities":{"loadSession":false}}}
  7. Use the experimental ACP v2 API

    main

    ACP v2 is currently a draft. Its wire protocol and the TypeScript API may change incompatibly in any SDK release. To use the experimental v2 features, you must use an explicit experimental import instead of the stable v1 entry point.

    import * as acp from "@agentclientprotocol/sdk/experimental/v2";
  8. Run HTTP and WebSocket transport examples

    main

    To test the streamable HTTP and WebSocket implementations, you need to run the server and then connect with a client in a separate terminal.

    1. Start the HTTP server (supports WebSocket upgrade):
    npx tsx src/examples/http-server.ts
    1. In a new terminal, run either the HTTP client or the WebSocket client:

    For HTTP:

    npx tsx src/examples/http-client.ts

    For WebSocket:

    npx tsx src/examples/ws-client.ts
    npx tsx src/examples/http-server.ts
    # In another terminal:
    npx tsx src/examples/http-client.ts
    # OR
    npx tsx src/examples/ws-client.ts