GitHub - rubyonai/rails-llm-integration: 🔥🔥 A Claude Skill that teaches Claude Code how to write LLM features

3 min read Original article ↗

The missing Rails convention for LLM calls.

A Claude Skill that teaches Claude Code how to write LLM features
using the patterns Rails devs already know.

Ruby Rails Claude Skill License

Works with ruby_llm · langchain-rb · ruby-openai · anthropic-rb


Why This Exists

Rails has conventions for email, jobs, storage, and config. But not for LLM calls. So every team ends up with something like this:

# Raw API call in a controller. No retries, no cost tracking, blocks the request.
def create
  client = OpenAI::Client.new(access_token: ENV["OPENAI_API_KEY"])
  response = client.chat(parameters: {
    model: "gpt-4o",
    messages: [{ role: "user", content: "Describe #{@product.name}" }]
  })
  @product.update!(description: response.dig("choices", 0, "message", "content"))
end

It works, but it doesn't scale:

  • No retries. Rate limits and transient failures fail silently.
  • No cost visibility. You can't tell what you're spending per request or per day.
  • Scattered prompts. Prompt strings live inline across controllers, services, and rake tasks.
  • No consistency. Every developer wires up LLM calls their own way.

Important

This skill gives Claude Code a set of Rails conventions for LLM calls so it generates consistent, structured code whenever you ask it to build AI features.

What It Looks Like

LLM::GenerateDescriptionJob.perform_later(product_id: @product.id)

Behind that one line, Claude generates this structure for you:

app/
  services/llm/
    product_description_service.rb    # Business logic, validation, parsing
    base_service.rb                   # Tracing, retries, cost tracking (inherited)
  jobs/llm/
    generate_description_job.rb       # Async with typed retry rules
  prompts/
    product_descriptions/
      generate.system.erb             # Versioned in git, tested on its own
      generate.text.erb
config/
  llm.yml                            # Model routing + budget caps (like database.yml)

Each service follows the same pattern:

module LLM
  class ProductDescriptionService < BaseService
    self.task_type = :generation    # Routes to the right model automatically

    def validate_params!(params)
      raise ArgumentError, "product required" unless params[:product]
    end

    def prompt_template
      "product_descriptions/generate"
    end

    def parse_response(response)
      content = response.dig(:choices, 0, :message, :content)
      { description: content.strip }
    end
  end
end

Same structure for every LLM feature in your app.

Installation

cp -r rails-llm-integration/ your-rails-app/.claude/skills/rails-llm-integration/

Then open Claude Code in your Rails project and ask it to build a feature:

> Add AI-powered product descriptions to my app
> Set up LLM service objects with cost tracking
> Create a ticket classification service using ruby_llm

Note

Claude reads the skill's reference docs and generates code following these conventions.

Reference Docs

references/

File Covers
client-setup.md ruby_llm, langchain-rb, ruby-openai, anthropic-rb
service-patterns.md BaseService, Result, concerns, error types
job-patterns.md Sidekiq queues, retry rules, batch processing
proxy-routing.md config/llm.yml, model routing, budget caps
eval-pipeline.md Braintrust, LLM-as-judge, CI gates
prompt-management.md ERB templates in app/prompts/
testing-guide.md WebMock, VCR, shared examples, CI strategy
generators.md llm:install and llm:service generators

templates/

File Covers
base_service.rb.tt BaseService with concerns
base_job.rb.tt BaseJob with retry rules
llm.yml.tt Model routing and budget config
migrations/ Batches, dead letters, eval cases, experiments

scripts/

File Covers
audit_llm_usage.rb Finds anti-patterns in your codebase

Who This Is For

Rails developers shipping LLM features to production.

Covers

Category Gem Use Case
Recommended ruby_llm Multi-provider, clean DSL, ActiveRecord integration
RAG langchain-rb Vector search, pgvector, embeddings, agents
Direct ruby-openai OpenAI-only projects
Direct anthropic-rb Anthropic-only projects
Proxy LiteLLM / Portkey Multi-provider routing, cost tracking
Evals Braintrust Trace logging, quality scoring, CI gates

Contributing

See CONTRIBUTING.md for details.

  • Production-proven. Every pattern must come from real production use.
  • Copy-pasteable. Code blocks should drop into a Rails app as-is.

License

MIT License. See LICENSE for details.


Claude Code is powerful. This skill makes it consistent.