Skip to content

A Rails agent framework for RubyLLM — define AI agents with prompts, schemas, caching, logging, cost tracking, and a built-in dashboard for monitoring LLM usage in production.

License

Notifications You must be signed in to change notification settings

adham90/ruby_llm-agents

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

489 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

RubyLLM::Agents

RubyLLM::Agents

Production-ready Rails engine for building, managing, and monitoring LLM-powered AI agents

Gem Version CI Ruby Rails License: MIT Documentation

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.

Why RubyLLM::Agents?

  • 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

Show Me the Code

# 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)

Features

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

Quick Start

Installation

# Gemfile
gem "ruby_llm-agents"
bundle install
rails generate ruby_llm_agents:install
rails db:migrate

Configure API Keys

Configure all provider API keys in one place (v2.1+):

# config/initializers/ruby_llm_agents.rb
RubyLLM::Agents.configure do |config|
  config.openai_api_key = ENV["OPENAI_API_KEY"]
  config.anthropic_api_key = ENV["ANTHROPIC_API_KEY"]
  config.gemini_api_key = ENV["GOOGLE_API_KEY"]
end

Or use environment variables directly (auto-detected by RubyLLM):

# .env
OPENAI_API_KEY=sk-...
ANTHROPIC_API_KEY=sk-ant-...
GOOGLE_API_KEY=...

Generate an Agent

rails generate ruby_llm_agents:agent SearchIntent query:required

This creates app/agents/search_intent_agent.rb with the agent class ready to customize.

Mount the Dashboard

# config/routes.rb
mount RubyLLM::Agents::Engine => "/agents"
Dashboard Overview Agent Registry
Execution Log Multi-Tenancy

Documentation

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

Requirements

  • Ruby >= 3.1.0
  • Rails >= 7.0
  • RubyLLM >= 1.12.0

Contributing

Bug reports and pull requests are welcome at GitHub.

  1. Fork the repository
  2. Create your feature branch (git checkout -b my-feature)
  3. Commit your changes (git commit -am 'Add feature')
  4. Push to the branch (git push origin my-feature)
  5. Create a Pull Request

License

The gem is available as open source under the MIT License.

Credits

Built with love by Adham Eldeeb

Powered by RubyLLM

About

A Rails agent framework for RubyLLM — define AI agents with prompts, schemas, caching, logging, cost tracking, and a built-in dashboard for monitoring LLM usage in production.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •