Anthropic Ruby SDK: Install, Client, Streaming, Tools
Install the official Anthropic Ruby SDK (the anthropic gem), initialize the client, send messages, stream responses, and call Claude tools from Rails.
The official Anthropic Ruby SDK is a gem named anthropic, and it is the one you want for any new Ruby or Rails project talking to Claude. This page is the short version: what the gem is, how to tell it apart from the older community gem with a similar name, how to install it, and how to make the three calls you will actually use most: create a message, stream a response, and run a tool.
If you want the full agent build (tool design, the loop, background jobs, human approval, and testing), that lives in my guide to building AI agents in Ruby with the Anthropic SDK. This page is the install-and-reference companion to it.
What the Anthropic Ruby SDK Is
The Anthropic Ruby SDK is the official client library, published by Anthropic as the anthropic gem at anthropics/anthropic-sdk-ruby. In one line: the anthropic gem is maintained by Anthropic and wraps the Claude API for Ruby.
It gives you a threadsafe Anthropic::Client, a messages.create call for one-shot completions, streaming helpers for token-by-token output, typed tools defined as Ruby classes, and a tool_runner that drives the whole agent loop. It is a code-generated SDK (Ruby 3.2.0+), which is why the API surface is broad and consistent across the message, streaming, and tool paths.
Which Gem Is the Official One
The official one is anthropic, by Anthropic. The confusion is historical: the popular community gem by Alex Rudall was originally also named anthropic, and it was deliberately renamed to ruby-anthropic to hand the anthropic name over to Anthropic's official SDK. So if a tutorial from 2024 tells you to gem "anthropic" and then calls Anthropic.configure with an access_token, it is describing the old community gem under its old name. That API no longer ships as anthropic.
Here is the disambiguation, because "which anthropic ruby gem" is the single most common source of setup bugs I see:
| Gem name | Status | Maintainer | When to use it |
|---|---|---|---|
anthropic |
Official SDK, actively developed (1.x) | Anthropic | New Ruby/Rails projects; anything wanting streaming, typed tools, or the tool runner |
ruby-anthropic |
Community gem, maintained | Alex Rudall | Existing apps already built on it, or when you specifically want its lighter, hand-written API |
anthropic (pre-1.0, old name) |
Retired name | Alex Rudall | Never for new code; this name now points at the official SDK |
You may also run across an older obie/anthropic fork from the pre-official-SDK era. It is historical; new projects should ignore it and install the official gem.
The practical tell at runtime: the official SDK is instantiated with Anthropic::Client.new(api_key: ...), while the community ruby-anthropic client uses Anthropic::Client.new(access_token: ...) or a global Anthropic.configure block. Different keyword, different gem. If you paste a snippet and Ruby complains about an unknown keyword, you are almost certainly mixing the two.
Install the anthropic Gem
Add gem "anthropic" to your Gemfile, run bundle install, and set ANTHROPIC_API_KEY. That is the whole install; the SDK needs Ruby 3.2.0 or newer.
# Gemfile
gem "anthropic"
bundle install
Then make the API key available in the environment. The client reads ANTHROPIC_API_KEY by default, so you never hard-code it:
export ANTHROPIC_API_KEY="sk-ant-..."
A few things worth pinning down before you go further:
- Ruby version. The SDK requires Ruby 3.2.0 or newer. On anything older,
bundle installwill refuse the gem. - Pin the version. The gem moves quickly (it is well into the 1.x line), and the tool runner still lives under a
betanamespace. Pin it in your Gemfile (for examplegem "anthropic", "~> 1.54") and read the changelog before bumping, so a minor upgrade never silently changes behavior under you. - Keep the key out of git. In Rails,
ENV["ANTHROPIC_API_KEY"]orRails.application.credentialsboth work; the client just needs the value at boot.
Initialize the Client
Create one Anthropic::Client and reuse it. The client is threadsafe and manages its own connection pool, so building a fresh one per request wastes connections for no benefit. In Rails, an initializer assigning a constant is the natural home:
# config/initializers/anthropic.rb
ANTHROPIC = Anthropic::Client.new(
api_key: ENV.fetch("ANTHROPIC_API_KEY")
)
Using ENV.fetch rather than ENV[] means the app fails loudly at boot if the key is missing, instead of failing on the first API call in production. From here, ANTHROPIC is the one client the whole process shares.
If you prefer not to lean on the default, you can pass the key explicitly (shown above) or configure timeouts and retry counts per client. The important part is the lifecycle: build once, share everywhere.
Send Your First Message
Call messages.create with a model, a max_tokens cap, and a messages array. This is the core of the SDK, and every other feature builds on it:
message = ANTHROPIC.messages.create(
model: "claude-sonnet-5",
max_tokens: 1024,
messages: [
{ role: "user", content: "Summarize what a Rails initializer is in one sentence." }
]
)
# content is an array of typed blocks; the text lives on the first one.
puts message.content.first.text
Three required parameters: model, max_tokens, and messages. The response is a Message object, not a raw hash, so message.content is an array of content blocks and message.usage carries the input and output token counts you will want to log for cost tracking. Multi-turn conversations are just a longer messages array alternating role: "user" and role: "assistant".
That single call is the whole SDK in miniature. Everything below is a variation on it.
Streaming Responses
Use messages.stream and iterate stream.text when you want tokens as they arrive instead of waiting for the full response. This is what keeps a chat UI responsive:
stream = ANTHROPIC.messages.stream(
model: "claude-sonnet-5",
max_tokens: 1024,
messages: [
{ role: "user", content: "Draft a two-line deploy announcement." }
]
)
stream.text.each do |chunk|
print chunk # each token as the model produces it
end
If you would rather block until the response is complete (for a background job, say, where there is no user watching), the stream exposes accumulation helpers: stream.accumulated_text returns the whole string once the stream closes, stream.accumulated_message returns the full Message object, and stream.until_done simply blocks until it finishes. Pick incremental or blocking per use case; you do not need both on the same stream.
In a Rails app this pairs cleanly with Turbo Streams or ActionCable: broadcast each chunk as it arrives and the user watches the answer type itself out.
Tool Use (Function Calling)
Define tools as Anthropic::BaseTool subclasses with a typed input schema, then either pass them to messages.create or hand them to the tool runner. A minimal tool looks like this:
# The typed input the model must fill in.
class LookupOrderInput < Anthropic::BaseModel
required :order_id, Integer, doc: "The order ID to look up"
end
class LookupOrder < Anthropic::BaseTool
doc "Look up a single order by its ID. Use when the user asks about one specific order."
input_schema LookupOrderInput
# `input` is the parsed, typed schema object.
def call(input)
Order.where(id: input.order_id)
.as_json(only: %i[id status total_cents placed_at])
end
end
The doc string is what the model reads to decide when to call the tool, so treat it as an interface description, not an afterthought. The input_schema gives you typed, validated arguments (Anthropic::EnumOf[...] constrains a field to a fixed set of values), which stops the model from inventing inputs your code cannot handle.
The SDK can then run the entire tool loop for you: call the model, execute any tool it requests, feed the result back, and repeat until it produces a final answer. That helper is beta.messages.tool_runner:
ANTHROPIC.beta.messages.tool_runner(
model: "claude-sonnet-5",
max_tokens: 1024,
messages: [
{ role: "user", content: "What's the status of order 5591?" }
],
tools: [LookupOrder.new]
).each_message do |message|
# Each turn streams through here: tool-use requests, results, final answer.
Rails.logger.info(message.content)
end
Note the beta.messages namespace: the tool runner is still under beta, so its shape can change between releases. That is the main reason to pin your gem version. This is only the minimal shape; tool descriptions, authorization scoping, human approval, and testing are the parts that actually matter in production.
Using It Inside Rails
Call the client from a service object or background job using the constant from your initializer. That constant is available everywhere, so a plain service object or background job is usually all the structure you need:
class SummaryJob < ApplicationJob
queue_as :ai
def perform(document_id)
document = Document.find(document_id)
message = ANTHROPIC.messages.create(
model: "claude-sonnet-5",
max_tokens: 512,
messages: [
{ role: "user", content: "Summarize this in three bullets:\n\n#{document.body}" }
]
)
document.update!(summary: message.content.first.text)
end
end
Two Rails-specific habits pay off immediately. First, run anything multi-turn (streaming chats, tool loops) in a background job rather than a controller action, because an agent loop makes several API round trips and will happily blow past a web request timeout and tie up a Puma worker. Second, if a tool touches your database, scope its query through the same Pundit policy or tenant scope your controllers use, so the model can never read more than the user it acts for.
For the deeper Rails patterns (background jobs, authorization, streaming to the browser, observability, and testing the loop with the API stubbed), start at the Rails AI Agents hub and then the full agent-building walkthrough.
Anthropic Ruby SDK vs Alternatives
The official gem is the default; the alternatives make sense only in narrow cases. Here is how the options actually stack up:
| Approach | Streaming and tools | Maintenance | When to reach for it |
|---|---|---|---|
Official anthropic gem |
Built-in: streaming, typed tools, tool_runner |
Official, code-generated, frequent releases | Almost always; the default for new projects |
ruby-anthropic (alexrudall) |
Streaming and tools, hand-written API | Community, maintained | Existing apps already on it; a lighter surface |
| Raw HTTP (Faraday/Net::HTTP) | You build everything yourself | You own it entirely | Extreme dependency minimalism, or an unusual proxy setup |
| No SDK (other providers) | N/A for Claude | N/A | When a provider ships no official Ruby SDK at all, as with Gemini in Ruby |
The honest read: reach for the raw-HTTP path only when you have a specific reason to avoid the dependency, because you will end up reimplementing streaming parsing and the tool loop by hand, and both are easy to get subtly wrong. The official SDK is the low-risk choice, and it is where new features land first.
When Not to Reach for This Gem
The anthropic gem is the wrong starting point in a few cases. If you are calling a different provider (OpenAI, Gemini, a local model), this gem does not help you; it is Claude-only. If you have an existing app already built on ruby-anthropic and it works, migrating to the official SDK is a rewrite of your client code for no new capability, so weigh that against the maintenance benefit rather than switching reflexively. And if you truly need zero third-party gems, a thin Faraday wrapper is defensible, as long as you accept that you now own streaming and retries yourself. For everything else, install anthropic and move on.
Start With One Message
Install the gem, set ANTHROPIC_API_KEY, build one Anthropic::Client in an initializer, and get a single messages.create call returning text before you add anything else. Streaming, tools, and the tool runner are all variations on that one call, and confirming the simplest version works first saves you from debugging the SDK and your agent logic at the same time. When you are ready to go from a single call to a real agent, the building AI agents in Ruby guide picks up exactly where this page leaves off.
Building on Claude in a Rails app and want a second pair of hands on the architecture? I help teams with AI agent design, tool safety, and the authorization and observability patterns that make an LLM feature safe to ship. Reach out at hello at nsinenko.com.
Further Reading
- Building AI Agents in Ruby with the Anthropic SDK - the full agent build: tools, the loop, background jobs, human approval, and testing
- Rails AI Agents - the pillar hub for tool calling, cost control, guardrails, and observability
- Claude Agent SDK in Ruby - the higher-level agent framework, and how it differs from the raw SDK
- anthropic-sdk-ruby on GitHub - the official gem, README, and runnable examples
- The anthropic gem on RubyGems - version history and install page