Quality Gates
Each badge links to the configuration that enforces it.How ACP Works
ACP uses a subprocess model by default. A client (your application, or an editor like Zed) launches an agent as a child process and communicates over stdin/stdout using JSON-RPC messages. An agent can also run remotely and accept connections over HTTP or WebSocket (see Remote agents); the messages are the same. The protocol has three phases:- Initialize — client and agent exchange protocol versions and capabilities
- Session — client creates a session with a working directory context
- Prompt — client sends messages, agent streams back responses
Overview
The ACP Java SDK provides:- Client SDK — connect to and interact with any ACP-compliant agent
- Agent SDK — build ACP-compliant agents that work in Zed, JetBrains, and VS Code
- Test utilities — in-memory transports for fast, deterministic testing
Quick Start
Try it now
The fastest way to see ACP in action is to clone the tutorial and run a module. The client example talks to the Grok CLI (signed in once withgrok login; no API key needed). The agent example runs locally with no API key either.
Client — Connect to an Agent
This example launches the Grok CLI as an ACP agent subprocess and sends it a prompt. Any CLI tool that speaks ACP over stdin/stdout works here; Grok is one such tool.AgentParameters builds the command line (grok agent stdio). StdioAcpClientTransport spawns the process and handles the JSON-RPC framing. The sessionUpdateHandler receives the agent’s response text as it streams in — without it, you’d get the stop reason but no visible output.
Agent — Build Your Own
This is the other side of the conversation. When you build an agent, editors and clients launch your code as a subprocess and send it JSON-RPC messages over stdin. Your agent handles three request types: initialize, new session, and prompt. The stdio transport reads from stdin and writes to stdout.run() blocks until the client disconnects. The module includes a demo client that launches this agent as a subprocess and exercises it — you’ll see Echo: Hello! printed when you run it.
Adding the SDK to your project
acp-core holds the client and agent SDKs and the stdio, WebSocket, and Streamable HTTP client transports. From 0.18.0 it contains no JSON implementation, so add one JSON module next to it:
0.80.0 runs on the classpath and is not yet JPMS-modular (no
module-info): two packages,
com.agentclientprotocol.sdk.agent.transport and com.agentclientprotocol.sdk.json, are split across
more than one jar (acp-core plus acp-streamable-http-jetty, and acp-core plus
acp-json-jackson2/acp-json-jackson3, respectively), which JPMS doesn’t allow for one package. A fix
is planned after 0.80.0.acp-agent-support instead — it includes acp-core and acp-json-jackson2 transitively:
Remote agents over Streamable HTTP
An agent does not have to be a subprocess. From 0.18.0 the SDK implements the ACP Streamable HTTP and WebSocket transport: the agent listens on an HTTP endpoint, and any number of clients connect to it over HTTP POST with Server-Sent Event streams, or over a WebSocket upgrade on the same path. Each connection gets its own agent. Plainhttp:// (for example on localhost) is a first-class deployment.
Agent — add acp-streamable-http-jetty:
StreamableHttpAcpAgentTransport runs an embedded Jetty listener and creates one fresh agent per remote connection through an AcpAgentFactory. The agent definition is the same builder you would use over stdio:
StreamableHttpAcpClientTransport is in acp-core. Everything after the transport is the same client code as over stdio:
WebSocketAcpClientTransport pointed at ws://localhost:8080/acp talks to the same agent unchanged.
Mounting in your own server — StreamableHttpAcpServlet (module acp-http-servlet) serves Streamable HTTP, SSE and the WebSocket upgrade together, in any Servlet 6 container (Spring Boot, Tomcat, Jetty, Undertow) at a path you choose. Register it with async support. In Spring Boot:
init() starts the SSE keep-alive and destroy() closes every connection, cancelling in-flight prompts. The servlet upgrades WebSocket requests itself, through the container’s own Jakarta WebSocket 2.1 support, on the same path; a container with none answers the upgrade 501.
The
acp-websocket-jetty module and its single-client WebSocketAcpAgentTransport were deprecated for removal in 0.18.0 and are removed in 0.80.0. Use StreamableHttpAcpAgentTransport as shown above, which serves the WebSocket upgrade for any number of clients, one agent per connection; see the 0.80.0 migration guide for the full change.Release history
Version0.18.0 adds remote agents over the Streamable HTTP and WebSocket transport and splits JSON into acp-json-jackson2 and acp-json-jackson3; see What’s New for the three changes to check when upgrading. Versions 0.15.0 through 0.17.0 changed no public API. Version 0.12.0 added session/list, session/close, session/resume, elicitation, session/fork, and session/set_config_option. Version 0.14.0 (superseding the never-released 0.13.0) adds logout, session/delete, additional workspace directories, per-chunk message IDs, and the unstable providers/* configuration methods, promotes session/set_config_option to stable, and deprecates the removed session/set_model API (use session/set_config_option with a "model" category option). Version 0.80.0 is binary-incompatible with 0.18.0 and removes session/set_model and acp-websocket-jetty; see the 0.80.0 migration guide for every breaking change. See the API Reference for installation.
Three Agent API Styles
All three styles produce identical protocol behavior. Choose based on programming preference.
Documentation
API Reference
Client API, Agent API (all three styles), protocol types, transports, errors
Tutorial
32-module progressive tutorial from client basics to IDE integration
Resources
- GitHub Repository: source code
- ACP Java Tutorial: 41 hands-on modules