Installation
Snapshot builds are published to Maven Central Snapshots. Add the snapshot repository to your build.Maven
Add the snapshot repository, then the dependency:acp-core transitively):
Gradle
Add the snapshot repository:Three Agent API Styles
Quick Comparison
| Feature | Annotation-based | Sync | Async |
|---|---|---|---|
| Entry Point | @AcpAgent class | AcpAgent.sync() | AcpAgent.async() |
| Handler Style | Annotated methods | Lambda callbacks | Lambda callbacks returning Mono |
| Return Values | Auto-converted (String → PromptResponse) | Direct protocol types | Mono<ProtocolType> |
| Boilerplate | Lowest | Moderate | Moderate |
| Best For | Most applications | Simple blocking handlers | Reactive applications |
| Runtime | AcpAgentSupport | AcpSyncAgent | AcpAsyncAgent |
When to Use Each
- Annotation-based — default choice. Least boilerplate, auto-converts return types, supports interceptors and custom argument resolvers.
- Sync — when you want explicit control over every handler without annotations. Blocking void methods for sending updates.
- Async — when your agent needs non-blocking I/O. Uses Project Reactor
Monofor composable async chains.
Client API
AcpClient — Factory
| Method | Return Type | Description |
|---|---|---|
sync(transport) | AcpSyncClient.Builder | Create blocking client builder |
async(transport) | AcpAsyncClient.Builder | Create reactive client builder |
AcpSyncClient — Blocking Client
| Method | Return Type | Description |
|---|---|---|
initialize() | InitializeResponse | Protocol handshake with defaults |
initialize(request) | InitializeResponse | Handshake with custom capabilities |
newSession(request) | NewSessionResponse | Create a new session |
loadSession(request) | LoadSessionResponse | Resume an existing session |
prompt(request) | PromptResponse | Send prompt, block until response |
cancel(notification) | void | Cancel current prompt (fire-and-forget) |
getAgentCapabilities() | NegotiatedCapabilities | Capabilities reported by agent |
close() | void | Close connection |
Builder Configuration
Example — Complete client lifecycle
This launches Gemini CLI as an ACP agent subprocess and sends it a prompt.AgentParameters builds the command line; StdioAcpClientTransport spawns the process and handles JSON-RPC framing over stdin/stdout.
Agent API — Annotation-Based
Theacp-agent-support module provides a declarative programming model using annotations.
Annotations
Class-Level
| Annotation | Description |
|---|---|
@AcpAgent | Marks a class as an ACP agent. Optional name and version attributes. |
Handler Methods
| Annotation | JSON-RPC Method | Description |
|---|---|---|
@Initialize | initialize | Protocol initialization and capability negotiation |
@NewSession | session/new | Creates a new agent session |
@LoadSession | session/load | Loads an existing session by ID |
@Prompt | session/prompt | Handles user prompts |
@SetSessionMode | session/set_mode | Changes operational mode |
@SetSessionModel | session/set_model | Changes the AI model |
@Cancel | session/cancel | Cancellation notification (fire-and-forget) |
Parameter Annotations
| Annotation | Description |
|---|---|
@SessionId | Injects the current session ID as String |
@SessionState | Injects session-specific state |
Flexible Method Signatures
Handler methods support flexible parameter resolution:Return Value Handling
| Return Type | Conversion |
|---|---|
| Protocol response type | Passed through directly |
String | Converted to PromptResponse.text(value) |
void | Converted to PromptResponse.endTurn() |
Mono<PromptResponse> | Unwrapped and returned |
SyncPromptContext
Available in @Prompt handlers. Provides blocking methods for agent-client interaction:
AcpAgentSupport — Bootstrap
Interceptors
Cross-cutting concerns like logging, metrics, or error handling:Example — Complete annotation-based agent
Agent API — Sync (Builder)
Blocking handlers with plain return values. No annotations.Builder Methods
| Method | Description |
|---|---|
initializeHandler(handler) | Handle initialize requests |
newSessionHandler(handler) | Handle session/new requests |
loadSessionHandler(handler) | Handle session/load requests |
promptHandler(handler) | Handle session/prompt requests |
cancelHandler(handler) | Handle session/cancel notifications |
Example
Prompt Handler Context
Thecontext parameter in promptHandler provides:
| Method | Description |
|---|---|
getSessionId() | Current session ID |
sendMessage(text) | Send AgentMessageChunk |
sendThought(text) | Send AgentThoughtChunk |
sendUpdate(sessionId, update) | Send any SessionUpdate |
readFile(path, offset, limit) | Read file from client |
writeFile(path, content) | Write file on client |
requestPermission(request) | Ask client for permission |
getClientCapabilities() | Check client capabilities |
Agent API — Async (Builder)
Reactive handlers returningMono. Uses Project Reactor.
Example
sendMessage(), sendUpdate(), etc. return Mono<Void>, composable with .then() and .flatMap().
Convenience Methods vs Full API
The SDK provides convenience methods that cover the most common operations. Use these by default — they produce cleaner code and handle the protocol details for you.When convenience methods are enough (~80% of cases)
When to use the full API (~20% of cases)
Drop to the full API when you need control that convenience methods don’t expose:Protocol Types
All protocol types are defined inAcpSchema as Java records.
Request/Response Types
| Type | Fields |
|---|---|
InitializeRequest | protocolVersion, clientCapabilities |
InitializeResponse | protocolVersion, agentCapabilities, sessionIds |
NewSessionRequest | cwd, mcpServers |
NewSessionResponse | sessionId, restoredSessionState, contextDocuments |
LoadSessionRequest | sessionId, cwd, mcpServers |
LoadSessionResponse | restoredSessionState, contextDocuments |
PromptRequest | sessionId, prompt (list of Content) |
PromptResponse | stopReason |
CancelNotification | sessionId |
Content Types
| Type | Description |
|---|---|
TextContent | Text content with text field |
ImageContent | Image content (base64 or URL) |
Session Update Types
| Type | Description |
|---|---|
AgentMessageChunk | Incremental response text |
AgentThoughtChunk | Agent thinking process |
ToolCall | Tool execution start |
ToolCallUpdateNotification | Tool progress update |
Plan | Agent’s planned steps |
AvailableCommandsUpdate | Advertised slash commands |
CurrentModeUpdate | Agent mode change |
Stop Reasons
| Value | Description |
|---|---|
END_TURN | Agent finished responding |
MAX_TOKENS | Token limit reached |
REFUSAL | Agent refused the request |
CANCELLED | Prompt was cancelled |
Convenience Methods
Capabilities
Client Capabilities
Advertised duringinitialize:
NegotiatedCapabilities
Check capabilities before using them:
require methods that throw AcpCapabilityException if unsupported:
Transports
| Transport | Client Class | Agent Class | Module |
|---|---|---|---|
| Stdio | StdioAcpClientTransport | StdioAcpAgentTransport | acp-core |
| WebSocket | WebSocketAcpClientTransport | WebSocketAcpAgentTransport | acp-core / acp-websocket-jetty |
| In-Memory | via InMemoryTransportPair | via InMemoryTransportPair | acp-test |
Stdio Transport
The default transport. The client launches the agent as a subprocess and communicates via JSON-RPC over stdin/stdout. This is the same mechanism Zed, JetBrains, and VS Code use to talk to agents. Client side —AgentParameters specifies the command to launch. Any executable that speaks ACP over stdin/stdout works (Gemini CLI, your own agent JAR, etc.):
WebSocket Transport
For network-based communication. Client (JDK-native, no extra dependencies):In-Memory Transport
For testing. No subprocess or network I/O.Errors
Exception Hierarchy
| Exception | Description |
|---|---|
AcpProtocolException | JSON-RPC protocol error with code and message |
AcpCapabilityException | Tried to use an unsupported capability |
AcpConnectionException | Transport-level connection failure |
Error Codes
Agent-Side Error Handling
ThrowAcpProtocolException from handlers to send structured errors to clients:
Test Utilities
Theacp-test module provides utilities for testing without subprocesses.
InMemoryTransportPair
Packages
| Package | Description |
|---|---|
com.agentclientprotocol.sdk.spec | Protocol types (AcpSchema.*) |
com.agentclientprotocol.sdk.client | Client SDK (AcpClient, AcpAsyncClient, AcpSyncClient) |
com.agentclientprotocol.sdk.agent | Agent SDK (AcpAgent, AcpAsyncAgent, AcpSyncAgent) |
com.agentclientprotocol.sdk.agent.support | Annotation-based agent runtime (AcpAgentSupport) |
com.agentclientprotocol.sdk.annotation | Agent annotations (@AcpAgent, @Prompt, etc.) |
com.agentclientprotocol.sdk.capabilities | Capability negotiation (NegotiatedCapabilities) |
com.agentclientprotocol.sdk.error | Exceptions (AcpProtocolException, AcpCapabilityException) |
com.agentclientprotocol.sdk.test | Test utilities (InMemoryTransportPair) |
Maven Artifacts
| Artifact | Description |
|---|---|
acp-core | Client and Agent SDKs, stdio and WebSocket client transports |
acp-annotations | @AcpAgent, @Prompt, and other annotations |
acp-agent-support | Annotation-based agent runtime (includes acp-annotations + acp-core) |
acp-test | In-memory transport and test utilities |
acp-websocket-jetty | Jetty-based WebSocket server transport for agents |
See Also
- ACP Java SDK GitHub — Source code
- ACP Java Tutorial — 30 hands-on modules
- Agent Client Protocol — Official specification