Skip to content

Latest commit

 

History

History

README.md

Kotlin client for the Agent Host Protocol

Maven Central

Pure Kotlin/JVM client library providing auto-generated wire types for the Agent Host Protocol. Designed to be consumed unmodified from Android apps, server-side JVM services, and KMP/JVM target consumers.

  • Pure Kotlin/JVM — no Android SDK dependencies; targets Java 8 bytecode (built with JDK 17 toolchain) so no AGP version requirement, no core library desugaring, no minimum Android API level beyond what kotlinx.serialization already requires.
  • Auto-generated from the canonical TypeScript protocol definitions in the parent repo. Generated sources are committed so consumers don't need a TypeScript or tsx toolchain.
  • kotlinx.serialization-native with idiomatic sealed interfaces for every discriminated union, value class bitset enums, and nullable types for optional fields.

Installation

Add the dependency to your Android or JVM project:

Gradle (Kotlin DSL)

dependencies {
    implementation("com.microsoft.agenthostprotocol:agent-host-protocol:0.2.0")
}

Gradle (Groovy DSL)

dependencies {
    implementation 'com.microsoft.agenthostprotocol:agent-host-protocol:0.2.0'
}

Maven

<dependency>
    <groupId>com.microsoft.agenthostprotocol</groupId>
    <artifactId>agent-host-protocol</artifactId>
    <version>0.2.0</version>
</dependency>

The library transitively depends on org.jetbrains.kotlinx:kotlinx-serialization-json (api scope) — you do not need to declare it separately. You DO need to apply the kotlin-serialization Gradle plugin in any module that defines its own @Serializable classes alongside this library, but you do not need it just to consume the generated AHP types.

Usage

Always use the pre-configured Ahp.json instance (or a kotlinx.serialization.json.Json instance with the same settings). The custom serializers for AHP discriminated unions require the JSON-aware encoder/decoder.

import com.microsoft.agenthostprotocol.Ahp
import com.microsoft.agenthostprotocol.generated.ActionEnvelope
import com.microsoft.agenthostprotocol.generated.StateAction
import com.microsoft.agenthostprotocol.generated.StateActionUnknown

// Decode a server-sent action envelope from the wire. Since the v0.2 channels
// reorg, every action carries the `channel` URI it belongs to; per-session
// actions like `session/titleChanged` no longer include the session URI in
// their payload.
val envelope: ActionEnvelope = Ahp.json.decodeFromString(
    ActionEnvelope.serializer(),
    """{"channel":"ahp-session:/abc","action":{"type":"session/titleChanged","title":"new"},"serverSeq":42}""",
)

println(envelope.channel)           // ahp-session:/abc
println(envelope.serverSeq)         // 42
when (val action = envelope.action) {
    is StateActionUnknown -> {
        // Future protocol versions: a no-op fall-through is required so
        // older clients can keep applying actions they DO understand.
    }
    else -> { /* handle each action subtype as needed */ }
}

What's in the box

  • com.microsoft.agenthostprotocol.AhpAhp.json configured Json instance.
  • com.microsoft.agenthostprotocol.generated.* — wire types: RootState, SessionState, ChangesetState, TerminalState, AgentInfo, AgentSelection, ActionEnvelope (with channel URI), all command params/results (InitializeParams, CreateSessionParams, SubscribeParams, InvokeChangesetOperationParams, etc.), every per-channel action type (session/*, root/*, terminal/*, changeset/*), and discriminated-union sealed interfaces (StateAction, ResponsePart, ToolCallState, ToolResultContent, MessageAttachment, SnapshotState, ChangesetOperationTarget, ReconnectResult, etc.).
  • Pure reducers — top-level rootReducer, sessionReducer, terminalReducer, and changesetReducer functions (plus a Reducer<S, A> fun-interface wrapped as RootReducer / SessionReducer / TerminalReducer / ChangesetReducer objects) that produce the next state from the current state and an applied action. Behavior parity with the canonical TypeScript reducers is verified against the shared types/test-cases/reducers/ fixture corpus.
  • Channel-scoped notification paramsSessionAddedParams, SessionRemovedParams, SessionSummaryChangedParams, AuthRequiredParams, OtlpExportLogsParams, etc. Notifications are routed by their JSON-RPC method name (e.g. root/sessionAdded, auth/required, otlp/exportLogs) — there is no embedded type discriminator union.
  • JSON-RPC envelope types (JsonRpcRequest<P>, JsonRpcResponse, etc.) and helpers (AhpCommands.initialize(id, params)).

What's NOT in the box (yet)

  • A WebSocket / network transport — bring your own (e.g. OkHttp, Ktor).
  • An example Android client — see the Swift AHPClient example for the architecture pattern; a Kotlin/Android equivalent is planned for a follow-up release.

Protocol version mapping

Two constants in com.microsoft.agenthostprotocol.generated track which protocol version this library implements:

  • PROTOCOL_VERSION — SemVer string for the version this library's source tree implements.
  • SUPPORTED_PROTOCOL_VERSIONS — every version this library is willing to negotiate (most-preferred-first). Pass it as protocolVersions on InitializeParams.

The same information is mirrored, in machine-readable form, in release-metadata.json and, in human-readable form, in CHANGELOG.md. CI verifies all three sources agree on every PR.

Building from source

Requires JDK 17+ on JAVA_HOME. Gradle wrapper handles everything else.

cd clients/kotlin
./gradlew build

To regenerate the wire types from the TypeScript protocol definitions (requires Node.js for the generator):

# from the repo root
npm install
npm run generate:kotlin

CI verifies committed sources match the generator output — see AGENTS.md for details on the generator and release pipeline.

License

MIT — see LICENSE.