{"id":50799981,"url":"https://github.com/rimdoo/anthropic-kotlin","last_synced_at":"2026-06-12T18:34:23.590Z","repository":{"id":357724610,"uuid":"1238296105","full_name":"rimdoo/anthropic-kotlin","owner":"rimdoo","description":"Idiomatic Kotlin wrapper around com.anthropic:anthropic-java — suspend / Flow / sealed types over the official Anthropic Java SDK.","archived":false,"fork":false,"pushed_at":"2026-05-14T02:52:21.000Z","size":143,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-14T03:29:28.250Z","etag":null,"topics":["anthropic","anthropic-api","claude","claude-sdk","coroutines","flow","jvm","kotlin","managed-agents","sdk"],"latest_commit_sha":null,"homepage":null,"language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rimdoo.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-14T02:00:41.000Z","updated_at":"2026-05-14T02:52:24.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/rimdoo/anthropic-kotlin","commit_stats":null,"previous_names":["rimdoo/anthropic-kotlin"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/rimdoo/anthropic-kotlin","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rimdoo%2Fanthropic-kotlin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rimdoo%2Fanthropic-kotlin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rimdoo%2Fanthropic-kotlin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rimdoo%2Fanthropic-kotlin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rimdoo","download_url":"https://codeload.github.com/rimdoo/anthropic-kotlin/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rimdoo%2Fanthropic-kotlin/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34258369,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-12T02:00:06.859Z","response_time":109,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["anthropic","anthropic-api","claude","claude-sdk","coroutines","flow","jvm","kotlin","managed-agents","sdk"],"created_at":"2026-06-12T18:34:23.010Z","updated_at":"2026-06-12T18:34:23.576Z","avatar_url":"https://github.com/rimdoo.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# anthropic-kotlin\n\nIdiomatic Kotlin wrapper around [`com.anthropic:anthropic-java`](https://central.sonatype.com/artifact/com.anthropic/anthropic-java).\n\n[![License](https://img.shields.io/badge/license-Apache_2.0-blue.svg)](LICENSE)\n[![Kotlin](https://img.shields.io/badge/kotlin-2.0.21-blueviolet.svg)](https://kotlinlang.org)\n[![JVM](https://img.shields.io/badge/JVM-17%2B-orange.svg)](https://adoptium.net)\n[![Tests](https://img.shields.io/badge/tests-118%20passing-success.svg)](sdk/src/test/kotlin)\n\n```kotlin\nval client = AnthropicOkHttpClient.fromEnv()\n\nval response = client.createMessage(\n    model = Model.CLAUDE_OPUS_4_7,\n    maxTokens = 1024,\n    messages = listOf(Message.user(\"Hello, Claude!\")),\n)\nprintln(response.text)\n```\n\n## Why\n\nThe official Java SDK is full-featured but verbose from Kotlin: builder chains, `Optional\u003cT\u003e`, `CompletableFuture\u003cT\u003e`, and `Iterator` show up in every public signature. This module wraps it with five design invariants:\n\n| Invariant | Java SDK | anthropic-kotlin |\n| --- | --- | --- |\n| Async surface | `CompletableFuture\u003cT\u003e` | `suspend fun T` |\n| Streams | `StreamResponse\u003cT\u003e` (closeable iterator) | `Flow\u003cT\u003e` |\n| Polymorphic types | `Optional\u003cX\u003e` + `isX()` + `asX()` | `sealed class` + `when`-exhaustive |\n| Optional fields | `Optional\u003cT\u003e` | Kotlin `T?` |\n| Construction | `Foo.builder().bar(...).build()` | named + default parameters |\n\n```kotlin\n// Java SDK\nMessageCreateParams params = MessageCreateParams.builder()\n    .model(Model.CLAUDE_OPUS_4_7)\n    .maxTokens(1024)\n    .addUserMessage(\"hi\")\n    .build();\nMessage m = client.messages().create(params);\nString text = m.content().get(0).asText().text();\n\n// anthropic-kotlin\nval response = client.createMessage(\n    model = Model.CLAUDE_OPUS_4_7,\n    maxTokens = 1024,\n    messages = listOf(Message.user(\"hi\")),\n)\nval text = response.text\n```\n\n## Install\n\nThe artifact version tracks the underlying `com.anthropic:anthropic-java` release.\n\n```kotlin\ndependencies {\n    implementation(\"io.github.rimdoo:anthropic-kotlin:2.30.0\")\n}\n```\n\n`mavenCentral()` is in your build by default, so no repository changes needed.\n\n## Quickstart\n\n### Set the API key\n\n```bash\nexport ANTHROPIC_API_KEY=sk-ant-...\n```\n\n### Single-turn chat\n\n```kotlin\nval client = AnthropicOkHttpClient.fromEnv()\n\nval response = client.createMessage(\n    model = Model.CLAUDE_OPUS_4_7,\n    maxTokens = 1024,\n    messages = listOf(Message.user(\"What is Kotlin?\")),\n)\nprintln(response.text)\n```\n\n### Multi-turn conversation\n\n```kotlin\nclient.createMessage(\n    model = Model.CLAUDE_OPUS_4_7,\n    maxTokens = 1024,\n    messages = listOf(\n        Message.user(\"What's Kotlin?\"),\n        Message.assistant(\"A JVM language with null-safety and coroutines.\"),\n        Message.user(\"How is it different from Java?\"),\n    ),\n)\n```\n\n### Streaming with `Flow`\n\n```kotlin\nclient.streamMessage(\n    model = Model.CLAUDE_OPUS_4_7,\n    maxTokens = 1024,\n    messages = listOf(Message.user(\"Write a haiku.\")),\n).collect { event -\u003e\n    when (event) {\n        is MessageStreamEvent.ContentBlockDelta -\u003e print(event.delta.text)\n        is MessageStreamEvent.MessageStop -\u003e println()\n        else -\u003e {}\n    }\n}\n```\n\n### System prompt with caching\n\n```kotlin\nclient.createMessage(\n    model = Model.CLAUDE_OPUS_4_7,\n    maxTokens = 1024,\n    system = systemPrompt {\n        text(\"Very long static context...\", cache = CacheControl.Ephemeral)\n        text(\"Today: ${LocalDate.now()}\")\n    },\n    messages = listOf(Message.user(\"Question?\")),\n)\n```\n\n### Tool use\n\n```kotlin\nval weather = Tool(\n    name = \"get_weather\",\n    description = \"Look up current weather\",\n    inputSchema = jsonSchema {\n        property(\"city\", type = \"string\", required = true)\n    },\n)\n\nval response = client.createMessage(\n    model = Model.CLAUDE_OPUS_4_7,\n    maxTokens = 1024,\n    tools = listOf(weather),\n    toolChoice = ToolChoice.Auto,\n    messages = listOf(Message.user(\"Weather in Seoul?\")),\n)\n\nval toolUse = response.content.filterIsInstance\u003cContentBlock.ToolUse\u003e().firstOrNull()\nif (toolUse != null) {\n    // Run the tool yourself, then send the result back:\n    val followup = client.createMessage(\n        model = Model.CLAUDE_OPUS_4_7,\n        maxTokens = 1024,\n        tools = listOf(weather),\n        messages = listOf(\n            Message.user(\"Weather in Seoul?\"),\n            Message.assistant(content = response.content),\n            Message.toolResult(toolUseId = toolUse.id, content = \"Sunny, 21°C\"),\n        ),\n    )\n    println(followup.text)\n}\n```\n\n### Vision\n\n```kotlin\nclient.createMessage(\n    model = Model.CLAUDE_OPUS_4_7,\n    maxTokens = 1024,\n    messages = listOf(\n        Message.user(\n            ContentBlock.Image.url(\"https://example.com/cat.jpg\"),\n            ContentBlock.Text(\"What is this?\"),\n        ),\n    ),\n)\n```\n\n### Error handling\n\n```kotlin\nval result = runCatching {\n    client.createMessage(/* ... */)\n}\nresult.onFailure { e -\u003e\n    when (e) {\n        is AnthropicException.RateLimit -\u003e println(\"retry after ${e.retryAfter}\")\n        is AnthropicException.Auth -\u003e error(\"API key invalid\")\n        is AnthropicException.BadRequest -\u003e println(e.message)\n        else -\u003e throw e\n    }\n}\n```\n\n### Token counting\n\n```kotlin\nval tokens = client.countMessageTokens(\n    model = Model.CLAUDE_OPUS_4_7,\n    messages = listOf(Message.user(\"Hello, world!\")),\n)\nprintln(tokens.inputTokens)\n```\n\n## Managed Agents\n\nFull coverage of the beta Managed Agents API (Agent / Environment / Session / Vault / MemoryStore + every sub-service). Create an autonomous agent that can run tools inside a managed container, send it user events, and stream events back:\n\n```kotlin\nval agent = client.createAgent(\n    name = \"Coding Assistant\",\n    model = AgentModel.CLAUDE_OPUS_4_7,\n    system = \"You write clean, well-documented code.\",\n    tools = listOf(AgentTool.Toolset20260401), // bash + file ops + web search\n)\n\nval environment = client.createEnvironment(name = \"quickstart-env\")\n\nval session = client.createSession(\n    agentId = agent.id,\n    environmentId = environment.id,\n    title = \"Fibonacci task\",\n)\n\nclient.sendSessionEvents(\n    sessionId = session.id,\n    events = listOf(\n        UserEvent.Message(\n            text = \"Generate the first 20 Fibonacci numbers and save to fibonacci.txt\",\n        ),\n    ),\n)\n\nclient.streamSessionEvents(session.id)\n    .takeWhile { event -\u003e\n        when (event) {\n            is SessionStreamEvent.AgentMessage -\u003e { print(event.text); true }\n            is SessionStreamEvent.AgentToolUse -\u003e { println(\"\\n[Using ${event.name}]\"); true }\n            is SessionStreamEvent.SessionStatusIdle -\u003e false\n            else -\u003e true\n        }\n    }\n    .collect()\n```\n\nSee [`sample/src/main/kotlin/.../ManagedAgentsQuickstart.kt`](sample/src/main/kotlin/com/rimdoo/anthropic/sample/ManagedAgentsQuickstart.kt) for the runnable version.\n\n## API surface\n\n| Area | Functions |\n| --- | --- |\n| **Messages** | `createMessage`, `streamMessage`, `countMessageTokens` |\n| **Batches** | `createBatch`, `retrieveBatch`, `cancelBatch`, `deleteBatch`, `listBatches`, `batchResults` |\n| **Models** | `listModels`, `retrieveModel` |\n| **Completions** (legacy) | `createCompletion`, `streamCompletion` |\n| **Beta Files** | `uploadFile`, `retrieveFileMetadata`, `listFiles`, `deleteFile` |\n| **Managed Agents** | `createAgent` + retrieve/update/archive/list, `listAgentVersions` |\n| **Managed Environments** | full CRUD |\n| **Managed Sessions** | full CRUD + events (list / send / stream) + threads (list / retrieve / archive / events / stream) + resources (list / retrieve / addFile / update / delete) |\n| **Managed Vaults** | full CRUD + credentials (create with `CredentialAuth.{McpOAuth, StaticBearer}` / list / retrieve / archive / delete / mcpOAuthValidate) |\n| **Managed MemoryStores** | full CRUD + memories (full CRUD) + memoryVersions (list / retrieve / redact) |\n\n**68 public extension functions** on `AnthropicClient`, every one smoke-tested. See `:sdk:test`.\n\n### Sealed types\n\n`MessageStreamEvent`, `ContentBlock`, `ContentDelta`, `Tool`, `ToolChoice`, `CacheControl`, `ThinkingConfig`, `UserEvent`, `OutcomeRubric`, `CredentialAuth`, `NetworkPolicy`, `AgentTool`, `BatchResultStatus`, `SessionStreamEvent`, `AnthropicException` — all `when`-exhaustive.\n\n### Sample module\n\n```bash\nexport ANTHROPIC_API_KEY=sk-ant-...\n\n./gradlew :sample:run                 # Quickstart (Messages API)\n./gradlew :sample:runStreaming        # Flow\u003cMessageStreamEvent\u003e\n./gradlew :sample:runToolUse          # tool-use roundtrip\n./gradlew :sample:runManagedAgents    # full Managed Agents flow\n```\n\nSee [`sample/README.md`](sample/README.md).\n\n## Build \u0026 test\n\n```bash\n./gradlew :sdk:build                  # compile + assemble\n./gradlew :sdk:test                   # 118 unit tests (~3s, no network)\n./gradlew :sdk:publishToMavenLocal    # ~/.m2/repository/io/github/rimdoo/...\n```\n\n### Test layout\n\n`:sdk:test` runs offline — every test stubs the Java SDK via [mockk](https://mockk.io) so the full Builder chain executes (catching missing-required-field bugs at unit-test time, not at runtime).\n\n| Class | Purpose | Count |\n| --- | --- | --- |\n| `MappersTest` | Every `*.toRaw()` / `.toParam()` / Message factory / Tool lazy build | 29 |\n| `DslTest` | `jsonSchema { }` / `systemPrompt { }` builders | 7 |\n| `ExceptionsTest` | `AnthropicException` subtype fields | 7 |\n| `ClientApiSmokeTest` | Every public `AnthropicClient.*` extension via mockk-stubbed client | 75 |\n\n## Versioning\n\n`anthropic-kotlin` mirrors the underlying `com.anthropic:anthropic-java` version (currently `2.30.0`). A new wrapper release follows each Java SDK release; only the `gradle/libs.versions.toml` `anthropic` entry needs to change, and the Maven `version` of the artifact tracks it via `libs.versions.anthropic.get()`.\n\n## License\n\n[Apache 2.0](LICENSE) — same as the underlying Java SDK.\n\n## Acknowledgments\n\nBuilt on top of the official [Anthropic Java SDK](https://github.com/anthropics/anthropic-sdk-java). This project is not affiliated with Anthropic.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frimdoo%2Fanthropic-kotlin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frimdoo%2Fanthropic-kotlin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frimdoo%2Fanthropic-kotlin/lists"}