ACP Kotlin SDK

Modern Kotlin toolkit for building software that speaks the Agent Client Protocol (ACP). Ship ACP-compliant agents, clients, and transports for IDE plugins, CLIs, backend services, or any JVM host—all with one cohesive SDK.
What is ACP Kotlin SDK?
ACP standardises how AI agents and clients exchange messages, negotiate capabilities, and move files. This SDK provides a Kotlin implementation of that spec:
- Type-safe models for every ACP message and capability
- Agent and client connection stacks (JSON-RPC over STDIO)
- Ktor utilities for HTTP/WebSocket transports (optional modules)
- Comprehensive samples demonstrating end-to-end sessions and tool calls
Common scenarios
- Embed an ACP client in your IDE/plugin to talk to external agents
- Build a headless automation agent that serves ACP prompts and tools
- Prototype new transports with the connection layer and model modules
- Validate your ACP integration using the supplied test utilities
Modules at a glance
Requirements
- JDK 21 (toolchain configured through Gradle)
- Kotlin 2.2.20 or newer (Gradle Kotlin DSL plugin)
- Gradle 8.6+ (wrapper included)
- JVM target today; additional targets (JS, Native, Wasm) are on the roadmap
Installation
Artifacts are published under com.agentclientprotocol. The default build version is 0.3.0-SNAPSHOT; release builds use 0.3.0.
repositories {
mavenCentral()
}
dependencies {
implementation("com.agentclientprotocol:acp:0.3.0-SNAPSHOT")
}
Snapshot builds: When consuming the -SNAPSHOT artifacts outside Maven Central, add the repository that hosts your snapshot (e.g. GitHub Packages or an internal mirror).
Quick start
Write your first agent
Set up an AgentSupport, wire the standard STDIO transport, and stream responses. The example below also shows how to call the optional FileSystemOperations extension so the agent can read files through the client.
Write your first client
Create a Client with your own ClientSessionOperations implementation. This sample exposes FileSystemOperations, grants tool-call permissions, and prints streamed updates from the agent.
Run the reference sample
Prefer a fully wired example? Launch the repository sample that pairs the agent and client shown above:
./gradlew :samples:kotlin-acp-client-sample:run
./gradlew :samples:kotlin-acp-client-sample:run \
-PmainClass=com.agentclientprotocol.samples.GeminiClientAppKt
./gradlew :samples:kotlin-acp-client-sample:run \
-PmainClass=com.agentclientprotocol.samples.V2SimpleAgentAppKt
./gradlew :samples:kotlin-acp-client-sample:run \
-PmainClass=com.agentclientprotocol.samples.V2NegotiationAppKt
./gradlew :samples:kotlin-acp-client-sample:run \
-PmainClass=com.agentclientprotocol.samples.AuthStatusAppKt
Sample projects
Each sample includes comments that explain the protocol lifecycle and can be used as templates for real applications.
The v2 samples expose a response mode through session config options. The client selects “Uppercase once”
with session/set_config_option; after replying, the agent resets to Echo and sends a config_option_update.
ClientSession.setConfigOption returns the complete option list rather than the one option that changed,
because one choice can affect the others, and later changes arrive on session.updates as
SessionUpdate.ConfigOptionUpdate — also carrying the full list.
Agents report those changes with agent.v2.ClientOperations.notify(SessionUpdate.ConfigOptionUpdate(...)),
which works while the session is idle as well as mid-turn. ACP v2 uses config options for mode selection;
dedicated modes remain available in the SDK's v1 API.
Authentication status (unstable)
An agent can advertise the draft auth/status query with auth.status = true in its initialize response.
V1 uses agentCapabilities.auth.status. V2 uses capabilities.auth.status, independent of authMethods.
This V2 location follows the V2 authentication model; the draft RFD does not yet define a V2 schema entry.
The capability, request and response types, methods, and runtime hooks require @OptIn(UnstableApi::class).
After initialization, Client.authStatus queries the agent without a session or prompt. Agents answer through
AgentSupport.authStatus with in V1, or in V2.
The response can include a human-readable and . means credentials are configured, not necessarily valid.
Calls with a missing or capability fail locally. An agent without a status handler returns JSON-RPC method not found ().
shows the V1 and V2 flows end to end.
Capabilities
Architecture
┌─────────────────┐ ┌─────────────────┐
│ Agent App │ │ Client App │
│ (AgentSupport & │ │ (ClientSupport &│
│ AgentSession) │ │ ClientSessionOps│
├─────────────────┤ ├─────────────────┤
│ Agent runtime │ │ Client runtime │
│ (`Agent`) │ │ (`Client`) │
├─────────────────┤ ├─────────────────┤
│ Protocol │ │ Protocol │
├─────────────────┤ ├─────────────────┤
│ Transport │ │ Transport │
│ (STDIO, Ktor) │◄──►│ (STDIO, Ktor) │
└─────────────────┘ └─────────────────┘
Lifecycle overview: clients establish a transport, call initialize to negotiate capabilities, open sessions (session.new), send prompts (session.prompt), and react to streamed updates (tool calls, permissions, status). Agents implement the mirrors of these methods, delegating file and permission requests back to the client when required. The Agent and Client runtime classes sit between your business logic (AgentSupport/AgentSession or ClientSupport/ClientSessionOperations) and the lower-level /transport layers.
JSON-RPC batches are supported by the shared protocol and both built-in transports.
Known limitation — JSON syntax: the SDK accepts any JSON syntax that kotlinx.serialization's Json.parseToJsonElement accepts, including some non-standard JSON such as unquoted primitive tokens. For simplicity, we rely on the library's parser and do not reimplement JSON syntax validation. Parsed values still undergo JSON-RPC envelope validation.
Contributing
Contributions are welcome! Please open an issue to discuss significant changes before submitting a PR.
- Fork and clone the repo.
- Run
./gradlew check to execute the test suite.
- Use the supplied GitHub Actions workflows to verify compatibility.
Support
- File bugs and feature requests through GitHub Issues.
- For questions or integration help, start a discussion or reach out to the maintainers through the issue tracker.
License
Distributed under the MIT License. See LICENSE.txt for details.