Skip to content

Official Rust SDK request — Where The Rust At? (follow-up to #747) #1559

@mothajammas

Description

@mothajammas

There is, against all judgment, a song attached. Begin there.

Where.The.Rust.At.mp4

Following up on #747 (closed Nov 2024). At the time, the response was:

Unfortunately there isn't a Rust SDK yet. We're actively working on Java & Ruby SDKs and there are a couple of other languages in our pipeline before Rust.

As of May 2026, the official SDK lineup is Python, TypeScript, Java, Go, Ruby, C#, PHP, and the ant CLI. Every language that was "in the pipeline before Rust" has shipped. Filing a fresh ask with a concrete use case rather than a general one.

Use case

I spent years building and maintaining fleets of distributed VMs. The thing that work taught me to value most was the absence of a versioned runtime. A single static binary that just lives on every host, no Python pinning, no JVM patch cycles, no "which Node is on this image" archaeology. Rust is the natural language for those tools.

Our team's (aka myself + Claude) dev/ops CLI is built that way: single binary, distributed via cargo-dist, ~1,500 LOC. The newest subcommand drafts release notes by pulling commits since the last cli/v* tag, sending them to Sonnet 4.5, and asking for a recommended version bump plus a CHANGELOG entry styled to match what we already have. One Messages API call per release.

Without an official Rust SDK, that integration is:

  • Direct reqwest POST to /v1/messages
  • Hand-rolled serde::Deserialize types for Message, ContentBlock, Usage, and the error envelope
  • Defensive markdown-fence stripping in case the model wraps the JSON output in ```json blocks
  • No streaming, no retry/backoff, no tool-use plumbing

It works. But every line of it is code I asked Claude Code to write knowing I'd throw it out the day an official crate ships, roughly 10x more LOC than the actual feature warrants, all of it shaped exactly like what the Python/TS/Go SDKs already define. Streaming, tool-use, longer-running agents are all approachable in the other SDK languages and uneconomical to attempt in Rust today, so those adjacent workflows keep getting routed to Python despite Rust being the better operational fit.

Why Rust now

  • Rust has become the default for performance-sensitive CLIs (ripgrep, fd, cargo-dist, sccache, uv) and infrastructure code (kube projects, observability stacks).
  • The data plane of AI tooling itself is increasingly Rust: candle, mistral.rs, llama-cpp-rs, tch-rs.
  • The current Rust Anthropic ecosystem is four single-maintainer wrappers (anthropic, clust, aici, etc.), all lagging API features. Community SDKs accumulating around an absent official one is the gap an Anthropic-maintained crate would close.
  • Pattern reference: OpenAI never published an official Rust SDK, and async-openai (community-maintained) accumulated millions of downloads. But OpenAI's Rust community is much larger than Anthropic's. Consolidating the smaller Anthropic-Rust surface around one official crate would have outsized impact relative to OpenAI's calculus.

Suggested MVP scope

Mirroring the shapes other SDKs already nail:

  • Anthropic::from_env() constructor reading ANTHROPIC_API_KEY
  • client.messages().create() sync + async (Tokio runtime)
  • Typed Message, ContentBlock, Usage, error types
  • Streaming via futures::Stream<Item = StreamEvent>
  • client.beta().messages() namespace for beta-header parity with the other SDKs

Tool-use, prompt caching, the files API, and the rest could land in subsequent releases.

Workaround until then

Sticking with the hand-rolled reqwest approach. Happy to test a preview / beta release against the use case above when one becomes available.


PS: the song is genuine. We hit a wall with the hand-rolled HTTP plumbing during a release-pipeline refactor; the rant about it kept getting more rhythmic until it became lyrics. Written collaboratively with Claude Code, who wrote most of the reqwest code described above, and who deserves an official SDK to consult instead of inventing the same wire shapes from scratch every session.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions