Installation
Maven (0.14.0 — stable)
Core SDK (client + sync/async agent APIs):acp-core transitively):
Gradle
Snapshot (0.15.0-SNAPSHOT)
For unreleased features, add the snapshot repository and use the snapshot version:0.15.0-SNAPSHOT in place of 0.14.0 in your dependencies.
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 |
authenticate(request) | AuthenticateResponse | Authenticate with a method ID |
logout(request) | LogoutResponse | Clear stored credentials (0.14.0) |
newSession(request) | NewSessionResponse | Create a new session |
loadSession(request) | LoadSessionResponse | Resume an existing session (replays history) |
listSessions(request) | ListSessionsResponse | List sessions, optional cwd filter (0.12.0) |
resumeSession(request) | ResumeSessionResponse | Reconnect to session without history replay (0.12.0) |
closeSession(request) | CloseSessionResponse | Close session and free resources (0.12.0) |
deleteSession(request) | DeleteSessionResponse | Permanently delete a stored session (0.14.0) |
forkSession(request) | ForkSessionResponse | Fork a session into a new branch (0.12.0, unstable) |
setSessionConfigOption(request) | SetSessionConfigOptionResponse | Set a session config value (0.12.0) |
listProviders(request) | ListProvidersResponse | List configurable model/backend providers (0.14.0, unstable) |
setProvider(request) | SetProviderResponse | Configure a provider (protocol, base URL, headers) (0.14.0, unstable) |
disableProvider(request) | DisableProviderResponse | Disable a provider by id (0.14.0, unstable) |
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 |
@Logout | logout | Clears stored credentials (0.14.0) |
@NewSession | session/new | Creates a new agent session |
@LoadSession | session/load | Loads an existing session by ID (replays history) |
@ListSessions | session/list | Lists sessions with optional cwd filter (0.12.0) |
@ResumeSession | session/resume | Reconnects to session without history replay (0.12.0) |
@CloseSession | session/close | Closes session and frees resources (0.12.0) |
@DeleteSession | session/delete | Permanently deletes a stored session (0.14.0) |
@ForkSession | session/fork | Forks a session into a new branch (0.12.0, unstable) |
@SetSessionConfigOption | session/set_config_option | Sets a session config value (0.12.0) |
@ListProviders | providers/list | Lists configurable providers (0.14.0, unstable) |
@SetProvider | providers/set | Configures a provider (0.14.0, unstable) |
@DisableProvider | providers/disable | Disables a provider by id (0.14.0, unstable) |
@Prompt | session/prompt | Handles user prompts |
@SetSessionMode | session/set_mode | Changes operational mode |
@SetSessionModel | session/set_model | Deprecated — removed from the spec; use @SetSessionConfigOption with a "model" category option |
@Cancel | session/cancel | Cancellation notification (fire-and-forget) |
Deprecated: the session-model API (0.14.0).session/set_modeland the related types (@SetSessionModel,SetSessionModelRequest/Response,SessionModelState,ModelInfo, and themodelsfield on session responses) were removed from the ACP spec in June 2026 and are marked@Deprecated(forRemoval = true). They still work for now but will be removed in a future release. Expose model selection throughsession/set_config_optioninstead: advertise aselectconfig option whosecategoryis"model", and switch models withsetSessionConfigOption(...). This is the same mechanism used for session modes (category: "mode") and reasoning level (category: "thought_level").
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 |
authenticateHandler(handler) | Handle authenticate requests |
logoutHandler(handler) | Handle logout requests (0.14.0) |
newSessionHandler(handler) | Handle session/new requests |
loadSessionHandler(handler) | Handle session/load requests |
listSessionsHandler(handler) | Handle session/list requests (0.12.0) |
resumeSessionHandler(handler) | Handle session/resume requests (0.12.0) |
closeSessionHandler(handler) | Handle session/close requests (0.12.0) |
deleteSessionHandler(handler) | Handle session/delete requests (0.14.0) |
forkSessionHandler(handler) | Handle session/fork requests (0.12.0, unstable) |
setSessionConfigOptionHandler(handler) | Handle session/set_config_option requests (0.12.0) |
listProvidersHandler(handler) | Handle providers/list requests (0.14.0, unstable) |
setProviderHandler(handler) | Handle providers/set requests (0.14.0, unstable) |
disableProviderHandler(handler) | Handle providers/disable requests (0.14.0, unstable) |
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, authMethods, agentInfo |
AuthenticateRequest | methodId |
AuthenticateResponse | (empty) |
LogoutRequest | (empty) (0.14.0) |
LogoutResponse | (empty) (0.14.0) |
NewSessionRequest | cwd, mcpServers, additionalDirectories (additionalDirectories 0.14.0) |
NewSessionResponse | sessionId, modes, modelsmodels deprecated — see below) |
LoadSessionRequest | sessionId, cwd, mcpServers, additionalDirectories (additionalDirectories 0.14.0) |
LoadSessionResponse | modes, models |
ListSessionsRequest | cwd (optional filter), cursor (pagination) (0.12.0) |
ListSessionsResponse | sessions (list of SessionInfo), nextCursor (0.12.0) |
ResumeSessionRequest | sessionId, cwd, mcpServers, additionalDirectories (0.12.0; additionalDirectories 0.14.0) |
ResumeSessionResponse | modes, modelsmodels deprecated) |
CloseSessionRequest | sessionId (0.12.0) |
CloseSessionResponse | (empty) (0.12.0) |
DeleteSessionRequest | sessionId (0.14.0) |
DeleteSessionResponse | (empty) (0.14.0) |
ForkSessionRequest | sessionId, cwd, mcpServers, additionalDirectories (0.12.0, unstable) |
ForkSessionResponse | sessionId, modes, modelsconfigOptions (0.12.0, unstable; models deprecated) |
SetSessionConfigOptionRequest | sessionId, configId, value, type (0.12.0) |
SetSessionConfigOptionResponse | configOptions (full config state) (0.12.0) |
ListProvidersRequest | (empty) (0.14.0, unstable) |
ListProvidersResponse | providers (list of ProviderInfo) (0.14.0, unstable) |
SetProviderRequest | id, apiType, baseUrl, headers (0.14.0, unstable) |
SetProviderResponse | (empty) (0.14.0, unstable) |
DisableProviderRequest | id (0.14.0, unstable) |
DisableProviderResponse | (empty) (0.14.0, unstable) |
CreateElicitationRequest | sessionId, message, mode, requestedSchema (0.12.0, unstable) |
CreateElicitationResponse | action (accept/decline/cancel), content (0.12.0, unstable) |
CompleteElicitationNotification | elicitationId (0.12.0, unstable) |
PromptRequest | sessionId, prompt (list of ContentBlock) |
PromptResponse | stopReason |
CancelNotification | sessionId |
Session Types (0.12.0)
| Type | Fields | Description |
|---|---|---|
SessionInfo | sessionId, cwd, title, updatedAt, additionalDirectories | Session metadata returned by session/list (additionalDirectories 0.14.0) |
SessionCapabilities | list, close, resume, delete, additionalDirectories, fork | Nested capability flags on AgentCapabilities (delete, additionalDirectories 0.14.0; fork unstable) |
Config Option Types (0.12.0)
session/set_config_option is stable. The select variant is the stable shape; boolean is an SDK extension.
| Type | Description |
|---|---|
SessionConfigOption | Polymorphic: SessionConfigSelect or SessionConfigBoolean |
SessionConfigSelect | Select-type config with currentValue, category, and options list |
SessionConfigBoolean | Boolean toggle with currentValue (unstable extension) |
SessionConfigSelectOption | A named value within a select config (value, name) |
ConfigOptionUpdate | SessionUpdate variant for agent-pushed config changes |
Provider Types (0.14.0, unstable)
Model/backend routing configuration. The agent advertises support with aproviders capability; the
client manages providers via listProviders / setProvider / disableProvider.
| Type | Description |
|---|---|
ProviderInfo | A configurable provider: id, supported (protocol ids), required, current |
ProviderCurrentConfig | Current effective routing: apiType, baseUrl |
ProvidersCapabilities | Agent capability marker (presence = supported), on AgentCapabilities |
apiType / supported use well-known LlmProtocol ids (anthropic, openai, azure, vertex, bedrock) or a custom string, modeled as String in the SDK.
Elicitation Types (0.12.0, unstable)
| Type | Description |
|---|---|
ElicitationSchema | JSON Schema describing form fields (properties, required) |
ElicitationPropertySchema | Polymorphic: StringPropertySchema, NumberPropertySchema, IntegerPropertySchema, BooleanPropertySchema, MultiSelectPropertySchema |
EnumOption | Named value for select/multi-select (const, title) |
ElicitationCapabilities | Client capability for form and/or URL elicitation |
ElicitationAction | Enum: ACCEPT, DECLINE, CANCEL |
Content Types
| Type | Description |
|---|---|
TextContent | Text content with text field |
ImageContent | Image content (base64 or URL) |
Session Update Types
| Type | Description |
|---|---|
UserMessageChunk | Incremental user message text (optional messageId) |
AgentMessageChunk | Incremental response text (optional messageId — 0.14.0) |
AgentThoughtChunk | Agent thinking process (optional messageId — 0.14.0) |
ToolCall | Tool execution start |
ToolCallUpdateNotification | Tool progress update |
Plan | Agent’s planned steps |
AvailableCommandsUpdate | Advertised slash commands |
CurrentModeUpdate | Agent mode change |
UsageUpdate | Context window and cost usage |
ConfigOptionUpdate | Session config option changes |
UserMessageChunk, AgentMessageChunk, AgentThoughtChunk) carry an optional messageId: chunks sharing the same id belong to one logical message, and a change in id starts a new message (0.14.0).
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:
Session Capabilities (0.12.0)
Agents advertise session management support viaSessionCapabilities. The
NegotiatedCapabilities accessors are: supportsListSessions(), supportsCloseSession(),
supportsResumeSession(), supportsDeleteSession() (0.14.0),
supportsAdditionalDirectories() (0.14.0), and supportsForkSession() (unstable) — each with a
matching require*() that throws AcpCapabilityException.
Elicitation Capabilities (0.12.0, unstable)
Clients advertise elicitation support during initialization:@UnstableAcpApi
APIs marked @UnstableAcpApi correspond to protocol elements in schema.unstable.json. They are public and functional but may change in any minor release. When the protocol element stabilizes, the annotation is removed (compatible change). See Versioning for the full policy.
IntelliJ users can configure the Unstable API Usage inspection (Settings > Inspections > JVM languages) to flag usages.
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