RubyLLM made 2026 the year of Ruby AI agents. Rails teams building agent features inside existing apps want HTTP-first integrations, not heavy SDKs. This tutorial wires RubyLLM plus Scavio into a Rails app with a working search tool.
Prerequisites
- Rails 8+
- Ruby 3.3+
- A Scavio API key
- The ruby_llm gem
Walkthrough
Step 1: Add the ruby_llm gem
RubyLLM ships an agent DSL with tool support.
bundle add ruby_llm
bundle add faradayStep 2: Create a Scavio tool class
Any Ruby callable works as a RubyLLM tool.
# app/agents/tools/scavio_search.rb
class ScavioSearch
include RubyLLM::Tool
description 'Search the web across Google, Reddit, and YouTube.'
param :query, type: :string
def execute(query:)
res = Faraday.post('https://api.scavio.dev/api/v1/search',
{ query: query }.to_json,
{ 'x-api-key' => ENV['SCAVIO_API_KEY'], 'Content-Type' => 'application/json' })
JSON.parse(res.body).dig('organic_results') || []
end
endStep 3: Define the agent
RubyLLM agent DSL binds tools to the chat loop.
# app/agents/research_agent.rb
class ResearchAgent < RubyLLM::Agent
model 'claude-sonnet-4-6'
tools ScavioSearch
system_prompt 'Research agent. Cite every claim.'
endStep 4: Call the agent from a controller
Works in a Rails controller or a background job.
# app/controllers/research_controller.rb
class ResearchController < ApplicationController
def create
result = ResearchAgent.chat(params[:question])
render json: { answer: result }
end
endStep 5: Wire a test route
Verify end-to-end in the browser.
# config/routes.rb
post '/research', to: 'research#create'
# curl: curl -XPOST localhost:3000/research -d 'question=what is rubyllm'Python Example
# Ruby tutorial; Python parity call:
import os, requests
API_KEY = os.environ['SCAVIO_API_KEY']
r = requests.post('https://api.scavio.dev/api/v1/search',
headers={'x-api-key': API_KEY},
json={'query': 'rubyllm 2026'})
print(r.json().get('organic_results', [])[:3])JavaScript Example
// Ruby tutorial; JS parity call:
const API_KEY = process.env.SCAVIO_API_KEY;
const r = await fetch('https://api.scavio.dev/api/v1/search', {
method: 'POST',
headers: { 'x-api-key': API_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({ query: 'rubyllm 2026' })
});
console.log(((await r.json()).organic_results || []).slice(0, 3));Expected Output
Rails endpoint returns agent answers grounded in Scavio search results. Works inside synchronous controllers or Sidekiq jobs.