| name | rubyllm |
| version | 1.14.1 |
| description | One beautiful Ruby API for GPT, Claude, Gemini, and more. Use this skill when building AI-powered applications with RubyLLM - chatbots, AI agents, RAG applications, content generators, vision/audio analysis, embeddings, image generation, and Rails integration. Supports 15+ providers with a unified interface.
|
| allowed-tools | ["Bash(bundle *)","Bash(bin/rails *)"] |
RubyLLM v{{ page.version }}
One beautiful Ruby API for GPT, Claude, Gemini, and more.
RubyLLM provides a unified interface for working with AI models across 15+ providers. Build chatbots, AI agents, RAG applications, and content generators with the same simple API.
Gem Version: 1.14.1
Installation
Ruby Project
bundle add ruby_llm
RubyLLM.configure do |config|
config.openai_api_key = ENV['OPENAI_API_KEY']
config.anthropic_api_key = ENV['ANTHROPIC_API_KEY']
config.gemini_api_key = ENV['GEMINI_API_KEY']
end
Rails Integration
bundle add ruby_llm
bin/rails generate ruby_llm:install
bin/rails db:migrate
bin/rails ruby_llm:load_models
bin/rails generate ruby_llm:chat_ui
Quick Start
chat = RubyLLM.chat
response = chat.ask "What is Ruby on Rails?"
chat.ask "Write a story" do |chunk|
print chunk.content
end
class Weather < RubyLLM::Tool
description "Get weather"
param :city, desc: "City name"
def execute(city:)
"Sunny in #{city}"
end
end
chat.with_tool(Weather).ask "Weather in Paris?"
Core Features
Ecosystem Gems
Chat API
chat = RubyLLM.chat(model: 'gpt-5.4')
response = chat.ask "What is Ruby?"
chat.ask "Show me an example"
chat.messages.each do |msg|
puts "[#{msg.role}] #{msg.content}"
end
chat.with_instructions "You are a Ruby expert. Be concise."
Providers
RubyLLM supports 15+ providers through a unified API:
| Provider | Models | Vision | Tools | Audio |
|---|
| OpenAI | GPT-4, GPT-4o, o1, o3 | ✅ | ✅ | ✅ |
| Anthropic | Claude 3/4 | ✅ | ✅ | ❌ |
| Google | Gemini 1.5/2.0/2.5/3.0 | ✅ | ✅ | ✅ |
| xAI | Grok-1/2/3 | ✅ | ✅ | ❌ |
| AWS Bedrock | Claude, Llama, Titan | ✅ | ✅ | ❌ |
| Ollama | Local models | ✅ | ✅ | ✅ |
| OpenRouter | 300+ models | ✅ | ✅ | ❌ |
| Perplexity | Search models | ❌ | ✅ | ❌ |
| Mistral | Mistral/Mixtral | ✅ | ✅ | ❌ |
| DeepSeek | DeepSeek-V3 | ❌ | ✅ | ❌ |
| VertexAI | Google Cloud | ✅ | ✅ | ✅ |
| GPUStack | Self-hosted | ✅ | ✅ | ❌ |
| Azure OpenAI | Enterprise OpenAI | ✅ | ✅ | ✅ |
Provider Setup
RubyLLM.configure do |config|
config.openai_api_key = ENV['OPENAI_API_KEY']
config.anthropic_api_key = ENV['ANTHROPIC_API_KEY']
config.gemini_api_key = ENV['GEMINI_API_KEY']
config.xai_api_key = ENV['XAI_API_KEY']
config.perplexity_api_key = ENV['PERPLEXITY_API_KEY']
config.mistral_api_key = ENV['MISTRAL_API_KEY']
config.deepseek_api_key = ENV['DEEPSEEK_API_KEY']
end
Model Selection
chat = RubyLLM.chat(model: 'claude-sonnet-4-6')
chat = RubyLLM.chat(model: 'claude-sonnet-4-6', provider: 'bedrock')
RubyLLM.models.supporting(:vision)
RubyLLM.models.find('gpt-5.4')
Prompt Caching (Anthropic)
raw_block = RubyLLM::Content::Raw.new([
{
type: 'text',
text: File.read('large_document.txt'),
cache_control: { type: 'ephemeral' }
}
])
chat.add_message(role: :system, content: raw_block)
response = chat.ask(raw_block)
puts "Cached tokens: #{response.cached_tokens}"
Extended Thinking
Give models more computation budget for complex reasoning (o1, o3, Claude Opus).
New in v1.10
chat = RubyLLM.chat(model: 'claude-opus-4.5')
.with_thinking(effort: :high)
response = chat.ask("Complex problem")
puts response.thinking&.text
puts response.thinking&.signature
puts response.thinking_tokens
Effort Levels
chat.with_thinking(effort: :low)
chat.with_thinking(effort: :medium)
chat.with_thinking(effort: :high)
chat.with_thinking(effort: :none)
chat.with_thinking(budget: 10_000)
Streaming with Thinking
chat.ask "Solve step by step" do |chunk|
print chunk.thinking&.text
print chunk.content
end
Streaming
chat.ask "Write a story" do |chunk|
print chunk.content
$stdout.flush
end
chat = RubyLLM.chat
.on_new_message { print "Assistant > " }
.on_end_message { |msg| puts "\n✓ Done (#{msg.output_tokens} tokens)" }
chat.ask "Hello" do |chunk|
print chunk.content
end
Multi-Modal
chat.ask "What's in this image?", with: "photo.jpg"
chat.ask "Summarize this", with: "report.pdf"
chat.ask "Transcribe", with: "meeting.mp3"
chat.ask "Analyze", with: ["image.jpg", "doc.pdf", "notes.txt"]
Token Tracking
response = chat.ask "Hello"
puts "Input: #{response.input_tokens}"
puts "Output: #{response.output_tokens}"
puts "Cached: #{response.cached_tokens}"
puts "Thinking: #{response.thinking_tokens}"
model = RubyLLM.models.find(response.model_id)
cost = (response.input_tokens * model.input_price_per_million / 1_000_000) +
(response.output_tokens * model.output_price_per_million / 1_000_000)
Error Handling
begin
response = chat.ask "Hello"
rescue RubyLLM::AuthenticationError
rescue RubyLLM::RateLimitError => e
sleep e.retry_after
retry
rescue RubyLLM::TimeoutError
rescue RubyLLM::ContextLengthExceededError
rescue RubyLLM::Error => e
end
Error Types
| Error | HTTP | Description |
|---|
BadRequestError | 400 | Invalid parameters |
UnauthorizedError | 401 | Invalid API key |
PaymentRequiredError | 402 | Billing issue |
RateLimitError | 429 | Rate limit exceeded |
ContextLengthExceededError | - | Token limit |
ServerError | 500 | Provider error |
ServiceUnavailableError | 502/503/504 | Service down |
Debugging
export RUBYLLM_DEBUG=true
Shows full request/response details in logs.
Best Practices
Tool Security
class SafeTool < RubyLLM::Tool
param :input, desc: "User input"
def execute(input:)
raise ArgumentError if input.length > 1000
end
end
Cost Control
simple_chat = RubyLLM.chat(model: 'gpt-5-nano')
complex_chat = RubyLLM.chat(model: 'claude-sonnet-4-6')
Context Management
if chat.messages.sum { |m| m.input_tokens + m.output_tokens } > 100_000
summary = summarize(chat.messages.first(40))
chat.reset_messages!
chat.add_message(role: :system, content: summary)
end
Resources