Production-ready Rails engine for building, managing, and monitoring LLM-powered AI agents
Build intelligent AI agents in Ruby with a clean DSL, automatic execution tracking, cost analytics, budget controls, and a beautiful real-time dashboard. Supports OpenAI GPT-4, Anthropic Claude, Google Gemini, and more through RubyLLM.
- Rails-Native - Seamlessly integrates with your Rails app: models, jobs, caching, and Hotwire
- Production-Ready - Built-in retries, model fallbacks, circuit breakers, and budget limits
- Full Observability - Track every execution with costs, tokens, duration, and errors
- Zero Lock-in - Works with any LLM provider supported by RubyLLM
# Template agent — structured input via .call class SearchIntentAgent < ApplicationAgent model "gpt-4o" temperature 0.0 system "You are a search intent analyzer. Extract structured data from queries." user "Extract search intent from: {query}" assistant '{"refined_query":' # Force JSON output returns do string :refined_query, description: "Cleaned search query" array :filters, of: :string, description: "Extracted filters" end end result = SearchIntentAgent.call(query: "red summer dress under $50") result.content # => { refined_query: "red dress", filters: ["color:red", "price:<50"] } result.total_cost # => 0.00025 result.total_tokens # => 150 result.duration_ms # => 850# Conversational agent — freeform input via .ask class RubyExpert < ApplicationAgent model "claude-sonnet-4-5-20250929" system "You are a senior Ruby developer with 20 years of experience." end result = RubyExpert.ask("What's the difference between proc and lambda?") puts result.content # Stream the response RubyExpert.ask("Explain metaprogramming") { |chunk| print chunk.content }# Resilient agents with automatic retries and fallbacks class ReliableAgent < ApplicationAgent model "gpt-4o" user "{query}" on_failure do retries times: 3, backoff: :exponential fallback to: ["gpt-4o-mini", "claude-3-5-sonnet"] circuit_breaker after: 10, within: 60, cooldown: 5.minutes timeout 30 end end# Vector embeddings for semantic search and RAG # app/agents/embedders/document_embedder.rb module Embedders class DocumentEmbedder < ApplicationEmbedder model "text-embedding-3-small" dimensions 512 cache_for 1.week end end result = Embedders::DocumentEmbedder.call(text: "Hello world") result.vector # => [0.123, -0.456, ...] result.dimensions # => 512 # Batch embedding result = Embedders::DocumentEmbedder.call(texts: ["Hello", "World", "Ruby"]) result.vectors # => [[...], [...], [...]]# Message classification and routing class SupportRouter < ApplicationAgent include RubyLLM::Agents::Routing model "gpt-4o-mini" temperature 0.0 cache_for 1.hour route :billing, "Billing, charges, refunds, payments" route :technical, "Bugs, errors, crashes, technical issues" route :sales, "Pricing, plans, upgrades, discounts" default_route :general end result = SupportRouter.call(message: "I was charged twice") result.route # => :billing result.total_cost # => 0.00008# Text-to-speech and speech-to-text # app/agents/audio/podcast_speaker.rb module Audio class PodcastSpeaker < ApplicationSpeaker model "tts-1" voice "onyx" speed 0.95 output_format :aac streaming true end end result = Audio::PodcastSpeaker.call(text: "Welcome to the show!") result.audio # => Binary audio data result.duration # => 1.5 result.save_to("episode.aac") # Speech-to-text transcription result = Audio::MeetingTranscriber.call(audio: "standup.mp3") result.text # => "Good morning everyone..." result.word_count # => 5432# Image generation, analysis, and pipelines # app/agents/images/logo_generator.rb module Images class LogoGenerator < ApplicationImageGenerator model "gpt-image-1" size "1024x1024" quality "hd" style "vivid" template "Professional logo design: {prompt}. Minimalist, scalable." end end result = Images::LogoGenerator.call(prompt: "tech startup logo") result.url # => "https://..." result.save("logo.png")# Evaluate agent quality with built-in scoring class SupportRouter::Eval < RubyLLM::Agents::Eval::EvalSuite agent SupportRouter test_case "billing", input: { message: "charged twice" }, expected: "billing" test_case "technical", input: { message: "500 error" }, expected: "technical" test_case "greeting", input: { message: "hello" }, expected: "general" end run = SupportRouter::Eval.run! puts run.summary # SupportRouter eval: 3/3 passed (score: 1.0)| Feature | Description | Docs |
|---|---|---|
| Agent DSL | Declarative configuration with model, temperature, parameters, description | Agent DSL |
| Execution Tracking | Automatic logging with token usage, cost analytics, and fallback tracking | Tracking |
| Cost Analytics | Track spending by agent, model, tenant, and time period | Analytics |
| Reliability | Automatic retries, model fallbacks, circuit breakers with block DSL | Reliability |
| Budget Controls | Daily/monthly limits with hard and soft enforcement | Budgets |
| Multi-Source Pricing | 7-source pricing cascade with caching for all model types | Pricing |
| Multi-Tenancy | Per-tenant API keys, budgets, circuit breakers, and execution isolation | Multi-Tenancy |
| Async/Fiber | Concurrent execution with Ruby fibers for high-throughput workloads | Async |
| Dashboard | Real-time Turbo-powered monitoring UI | Dashboard |
| Streaming | Real-time response streaming with TTFT tracking | Streaming |
| Conversation History | Multi-turn conversations with message history | Conversation History |
| Attachments | Images, PDFs, and multimodal support | Attachments |
| Embeddings | Vector embeddings with batching, caching, and preprocessing | Embeddings |
| Image Operations | Generation, analysis, editing, pipelines with cost tracking | Images |
| Routing | Message classification and routing with auto-generated prompts, inline classify | Routing |
| Audio | Text-to-speech (OpenAI, ElevenLabs), speech-to-text, dynamic pricing, 28+ output formats, dashboard audio playback | Audio |
| Agent Composition | Use agents as tools in other agents with automatic hierarchy tracking | Tools |
| Queryable Agents | Query execution history from agent classes with stats, replay, and cost breakdown | Querying |
| Evaluation | Test agent quality with exact match, contains, LLM judge, and custom scorers | Evaluation |
| Alerts | Slack, webhook, and custom notifications | Alerts |
| AS::Notifications | 11 instrumentation events across execution, cache, budget, and reliability | Events |
| Custom Middleware | Inject custom middleware globally or per-agent with positioning control | Middleware |
# Gemfile gem "ruby_llm-agents"bundle install rails generate ruby_llm_agents:install rails db:migrateUncomment one line in config/initializers/ruby_llm_agents.rb:
RubyLLM::Agents.configure do |config| config.openai_api_key = ENV["OPENAI_API_KEY"] endThen set the environment variable (e.g., in .env or Rails credentials).
Other providers
config.anthropic_api_key = ENV["ANTHROPIC_API_KEY"] config.gemini_api_key = ENV["GOOGLE_API_KEY"] config.deepseek_api_key = ENV["DEEPSEEK_API_KEY"] # ... see initializer for full listOr use environment variables directly (auto-detected by RubyLLM):
OPENAI_API_KEY=sk-... ANTHROPIC_API_KEY=sk-ant-...rails ruby_llm_agents:doctorrails generate ruby_llm_agents:demo bin/rails runner bin/smoke_test_agentOr generate a custom agent:
rails generate ruby_llm_agents:agent SearchIntent query:requiredThis creates app/agents/search_intent_agent.rb with the agent class ready to customize.
# config/routes.rb mount RubyLLM::Agents::Engine => "/agents"![]() | ![]() |
![]() | ![]() |
AI Agents: For comprehensive documentation optimized for AI consumption, see LLMS.txt
Note: Wiki content lives in the
wiki/folder. To sync changes to the GitHub Wiki, run./scripts/sync-wiki.sh.
| Guide | Description |
|---|---|
| Getting Started | Installation, configuration, first agent |
| Agent DSL | All DSL options: model, temperature, params, caching, description |
| Reliability | Retries, fallbacks, circuit breakers, timeouts, reliability block |
| Budget Controls | Spending limits, alerts, enforcement |
| Pricing | Multi-source pricing cascade, caching, configuration |
| Multi-Tenancy | Per-tenant budgets, isolation, configuration |
| Async/Fiber | Concurrent execution with Ruby fibers |
| Testing Agents | RSpec patterns, mocking, dry_run mode |
| Evaluation | Score agent quality with built-in and custom scorers |
| Error Handling | Error types, recovery patterns |
| Routing | Message classification, routing DSL, inline classify |
| Embeddings | Vector embeddings, batching, caching, preprocessing |
| Image Generation | Text-to-image, templates, pipelines, cost tracking |
| Dashboard | Setup, authentication, analytics |
| Production | Deployment best practices, background jobs |
| API Reference | Complete class documentation |
| Examples | Real-world use cases and patterns |
- Ruby >= 3.1.0
- Rails >= 7.0
- RubyLLM >= 1.12.0
Bug reports and pull requests are welcome at GitHub.
- Fork the repository
- Create your feature branch (
git checkout -b my-feature) - Commit your changes (
git commit -am 'Add feature') - Push to the branch (
git push origin my-feature) - Create a Pull Request
The gem is available as open source under the MIT License.
Built with love by Adham Eldeeb
Powered by RubyLLM



