Why is Ruby on Rails a great fit for AI agents Ruby on Rails is a strong fit for AI agents because of its token efficiency, predictability, and ecosystem ergonomics, according to an analysis by Martin Alderson, co-founder of CatchMetrics. Alderson found up to a 2.6x gap in token efficiency between programming languages, with Ruby ranking among the most efficient, which is critical for LLMs operating within finite context windows. What makes a programming framework good for autonomous AI agents? It's how well the language and APIs communicates intent within the tight constraints that LLMs operate under. Agents need to read code, understand it, and generate more of it, all within a finite context window. That means three things matter most: token efficiency how much meaning fits in how few tokens , predictability how consistently code is structured so the model doesn't have to guess , and ecosystem ergonomics how pleasant and productive the tooling is for iterative agent workflows . Ruby on Rails happens to excel at all three. What are AI agents? Traditional AI usage like running a single ChatGPT prompt is mostly linear and reactive. You ask a question and receive an answer. An autonomous agent is dynamic by contrast. It can break a task into steps, follow them one by one, recover from errors, and adjust their behavior based on new information. Agents are processes with access to tools and memory to orchestrate complex work. Tools let agents do things beyond the usual text APIs like running code or searching the web. Memory allows agensts to keep track of context across individual steps or even across sessions. Control logic defines how they decide what to do next. Token efficiency for both humans and robots When it comes to AI efficiency, most will bring up tokens. But what are tokens anyway? When it comes to large language models LLMs , tokens are the basic units of text that model either reads or generates. They are processable text chunks that don't always map to words but which these models understand. A token can be a whole word, part of a word, punctuation, or special characters. A word unbelievable might be split into un , believ , and able . Different models rely on different tokenization rules, so these chunks are not always the same. The process of turning raw text into these chunks is called tokenization . Context windows LLMs currently cannot process unlimited amount of text. The amount of data models can process is limited by computer memory which significantly increases with bigger context length . We call the maximum length a model can work with at a given time a context window and we measure it in tokens. This memory constrain includes the entire prompt, system instructions, conversation history, and the model's response. Less tokens as input enables longer answers and vice versa. When it comes to programming, the usage compounds between source files being read, changes being applied, and diffs being reviewed. Token windows significantly increased from the GPT-3.5 era of 4096 tokens and are now approching numbers higher than 1 million with models like Opus 4.6 and Sonnet 4.6. But even today the efficiency factor is significant when it comes to entire codebases. We are still spending energy, prolonging response times, and increasing cost. Ruby token efficiency Different programming languages means different token efficiency and context windows. This is where Ruby stands out. Martin Alderson, a co-founder of CatchMetrics, made a bit of a fuss lately with a post titled Which programming languages are most token-efficient? https://martinalderson.com/posts/which-programming-languages-are-most-token-efficient/ . You might not know Martin, but his writing was previously praised by OpenAI co-founder Andrej Karpathy and his posts put him to top 100 most highest-ranking personal blogs on Hacker News for 2025. In his post, Alderson looks at tasks from the RosettaCode project that have implementation across all 19 most popular mainstream languages. He then ran them through the GPT-4 tokenizer to get the number of tokens required for the solution. The results showed up to 2.6x gap between the most efficient and least efficient languages from the list. That’s pretty significant difference as it's the result between one to almost three files in the context window. Have a look yourself: The updated post also features a mention of the J language which could get efficiency around the half of Closure which dominates the graph. Looks like array languages can be extremely token-efficient. Ruby isn't first on this list, but it is number one when only the major languages are considered. As the author of Rails, David Heinemeier Hansson DHH , has said many times "Rails wouldn't exist without Ruby." Ruby was always putting the human experience of writing and reading above other metrics. No, not just the reading part like many others. Writing too. And it's interesting to realize that coming close to English language isn't just helpful for people, but also just as effective for AI. Language models got increasingly better in working with larger context windows over time, but the numbers of exchanged tokens still play a vital role in their practicality. More tokens means smaller available context, slower responses, and higher cost to run. As DHH puts it https://x.com/dhh/status/2013611188651794611 : The answer is of course agentic workflows. If you've used coding agents for any length of time, you'll quickly reach a point where you hit the dreaded 'compaction' stage. Compaction is the process most agents use when they reach the limit of the context window. It condenses earlier parts of the conversation - preserving recent context and key artifacts but losing a lot of the detail from earlier in the session. Rails token efficiency Of course, Rails is more than Ruby, and lots of people will point out that the framework is large with lots of project generated files and other ceremony. There are not wrong, but is that a problem? Well, a software engineer and researcher Felipe Maciel Ramos Vieira tried to answer this question in his comparative view called SyntaxTax https://felipemrvieira.github.io/SyntaxTax/dashboard/ that prioritizes the most context-efficient web stacks Felipe's report implement the same API features in different stacks and compare how many tokens the handwritten code consumes. The Rails framework won at lowest handwritten costs and it was second as lowest total cost. When we talk about big opinionated frameworks it was also first in total efficiency 1 primary handwritten efficiency. While neither report is detailed and comprehensive enough to be considered scientific there are definitely indicators that being compact, terse, and expressive might as well mean token efficient. Less ambiguity for the model Ruby's brevity is a good start but can mean very little without the generated tokens being correct. Modern LLMs can write valid code in almost any language. Agents don't fail at syntax, but they may struggle with ambiguity. They have harder time with architectural decisions. They must ask questions like Where should this logic go? , What pattern should I follow? , and How does this connect to the rest of the system? Very flexible frameworks leave these questions wide open, and every unanswered question is a chance for the agent to do guess work. Not in Rails. These questions tend to be already answered at the start because of the Rails' Convention over Configuration approach to building applications. An approach that had already lifted a lot of weight from people teams finds its new value in agentic workflows. Convention over Configuration Rails conventions act as implicit instructions. If there's a resource :posts route, there's a PostsController controller with CRUD action. If there's a PostsController , there is likely a Post model with user business logic and persistance conveniently provided by Active Record. If there's a has many relationship, there is a foreign key of a certain name. Naming things, structure of files, configuration or lack of . These are building stones that an agent can rely on. Just a simple thing as agreeing on singular vs plural naming saves a lot of overhead. It also makes things consistent. Consistency was good for humans and is equally helpful now with robots. Configuration Convention over Configuration means less need for writing configuration files, although default configuration files exist in Rails. And funnily enough, they also follow Convention over Configuration by specifying predefined environment like development or production , and standardizing how Rails components or gems accept configuration. Rails projects start with many files by default so it seems as if Rails cannot compete with micro frameworks on that minimalism front. However, that's deliberate choice with its own benefits and if we only really cared for the size, we can build a single file application as Greg Molnar shows us https://greg.molnar.io/blog/a-single-file-rails-application/ : frozen string literal: true require 'bundler/inline' gemfile true do source 'https://rubygems.org' gem 'rails', '~ 7.0.4' gem 'sqlite3' end require 'rails/all' database = 'development.sqlite3' ENV 'DATABASE URL' = "sqlite3: {database}" ActiveRecord::Base.establish connection adapter: 'sqlite3', database: database ActiveRecord::Base.logger = Logger.new STDOUT ActiveRecord::Schema.define do create table :posts, force: true do |t| end create table :comments, force: true do |t| t.integer :post id end end class App < Rails::Application config.root = dir config.consider all requests local = true config.secret key base = 'i am a secret' config.active storage.service configurations = { 'local' = { 'service' = 'Disk', 'root' = './storage' } } routes.append do root to: 'welcome index' end end class WelcomeController < ActionController::Base def index render inline: 'Hi ' end end App.initialize run App But this kind of minimalism is only helpful in micro examples. Typical applications will inevitably grow, so this is less of a concern. Generating more files at the beginning shows where we want things to live. It complements all of the other important design choices in Rails. Effortlessly RESTful A big part of any web application, be it something user facing or just an API https://serpapi.com , is its RESTful interface, coming from Representational State Transfer REST coined by Roy Fielding in 2000. There is lot of plumbing in representing state and data, and it's something that's practically solved since the Rails early days. When it comes to implementing Rails applications, you don't need to prompt "Create a RESTful controller with standard CRUD actions, following the naming convention…" — you just say "Add posts to this app" , and the agent can fill in the rest correctly, because the conventions tell it everything it needs to know. These conventions fundamentally changes how agents behave. Instead of guessing, they can infer. Instead of generating plausible-but-wrong code, they land on the idiomatic solution from the start. Less decision-making means better performance . Agents are not creative problem solvers in the human sense; they are pattern completion systems. Every extra decision you force them to make increases the chance of incorrect structure, inconsistent naming, or broken integration. Rails removes entire categories of these decisions this way. The result is more reliable code generation, faster iteration loops, and fewer corrections by humans. Baked-in features Rails packs a lot of functionality out of the box. This is by design as the framework has always believed that Convention over Configuration isn't just about file structure, it's about shipping defaults that are genuinely production-ready. Rails is extracted, not designed. There is no committee adding imaginary nice-to-have features. New features are extracted from real world applications. As an example, I was thinking about using Django early in my career and followed its releases over the years. Perhaps it's not entirely fair given the smaller team and different commercial attention, but Django always missed things Rails already had. Many things were added over time to Django as well, but Rails continues to have opinionated answers to almost anything. Django still largely leaves these as "pick your own adventure." Rails is a framework of frameworks. When you create a Rails application, you're not starting with a router and a blank slate. You're getting Active Record, Action Mailer, Active Job, Action Cable, Active Storage, and more. All integrated, all following the same conventions, all tested together, and on top supported by Hotwire and Solid libraries, which expand on these core frameworks even further. Some of these main frameworks are: Active Record is the database layer. Models map to tables, associations are declared with one line has many, belongs to , and queries are chainable Ruby instead of raw SQL. Migrations version your schema alongside your code. Active Model handles model's validations, serialization, type casting, dirty tracking, and more even without full database-backed Active Record so you can use it in your own plain Ruby objects modeling your domain layer. Action View is the templating layer. ERB templates, partials, layouts, helpers, and form builders. Form helpers handle CSRF tokens, URL generation, and type-appropriate inputs automatically. Action Controller & Action Dispatch are the HTTP layer. Controllers handle requests, dispatch routes them. You declare routes in one file routes.rb and they map to controller actions. Action Dispatch also handles middleware and request/response objects. Action Mailer brings email as controllers. Each mailer is a class with methods that correspond to email templates. You call UserMailer.welcome user .deliver later and get templated HTML/text email with the same layout system as your views. Active Job is the common interface for background jobs. You define a job class with a perform method, call MyJob.perform later args , and Rails queues it. It works with many adapters from Sidekiq, to Solid Queue. Action Cable is the Rails WebSockets integration. Channels work like controllers for persistent connections. You subscribe to channels and broadcast data from anywhere in your application. Action Mailbox routes inbound emails to mailbox classes, similar to how Action Controller routes HTTP requests to controllers. Handles ingestion from Postmark, Sendgrid, Mailgun, or raw SMTP. Active Storage handles upload, storage, URL generation, transformations, and variants of your model's file attachments. It comes with swappable backends and supports direct uploads to S3/GCS/Azure in production. Action Text brings rich text content editing to your application backed by the editor of your choice defaults to Lexxy . It's an abstraction for your rich text fields that integrates with Active Storage for embedded attachments. This tight integration is unique to Rails. All and more is available to your agents in a single package. Take just the storage for example. It's not just that you can attach a file to your model, you can immediately use a form helper for that, make it a direct upload, create more efficient variants, use it later in a background job or WYSIWYG editor. This kind of internal standardization can make complex features feel easy during agentic programming as it's the experience of our Engineering Director Illia Zub https://x.com/ilyazub when it came to using Rails Engines https://x.com/ilyazub /status/2079573049586663923 : I asked @GitHubCopilot to research the options and propose a plan. Then I kept reviewing it and writing, "Nah, I feel this can be simpler and more consistent." After several rounds of feedback to the plan, it landed on a Rails engine ... The result is a whole new feature in only a handful of files. It reuses our existing controller directly instead of making a separate API call, which is super nice. And that's not all. Solid Trifecta Another example of this philosophy is the so-called Solid Trifecta stack: Solid Cache , Solid Queue , and Solid Cable . These three libraries let you replace Redis and other external services with your primary database, either with MySQL, PostgreSQL or SQLite. Solid Trifecta is designed to reduce complexity. Even if they are not technically part of the Rails code directly, Rails ships with all three as defaults in new applications. Most frameworks would tell you to figure out your own message queue and caching layer, but Rails has one. They all plug into to a higher level APIs like Active Job which still lets you replace them with alternatives at any moment while keeping the same API interface. The new directions around SQLite is especially interesting given how much simplification you can do to your architecture. Testing Even the default test suite reflects this philosophy. Minitest , the Rails' default testing framework, supports parallel test execution leveraging multiple cores with a single configuration line. You don't need to reach for a separate gem or configure a CI matrix differently. It's there, it works, and it's fast. The assumption is that your tests should run quickly on the hardware you already have. On the other hand, lots of applications including SerpApi still choose RSpec , mainly for its DSL syntax focused on specifying behavior. Since it's a more popular option, it's also a great alternative for agentic coding. Rails usually gives you something out of the box, but still makes choosing an alternative easy. The alternatives in Rails are usually limited to a few of options, like here with RSpec being the only common alternative to Minitest, but that's a good thing. Coding agents do better with things that are well used and understood. Training data The Rails predictable nature and long list of features are great, but it's the real world use that makes the training possible. Rails is what I call the OG of all modern web frameworks; one that brought MVC and Active Record patterns to the masses, and inspired a whole generation of frameworks since that. Laravel author Taylor Otwell mentioned several times https://www.friendly.show/2278525/episodes/15825442-taylor-otwell-how-rails-inspired-laravel-live-from-rails-world-2024 how he got inspired by Rails, namely by Active Record, to create Eloquent ORM. This kind of history and pedigree helped Rails accumulate a list of famous open source projects with well-structured codebases. Some of the projects you might heard about include Spree eCommerce , Redmine project management , GitLab DevOps , Diaspora social network , Discourse forums , Maybe finance , and Chatwoot customer support . But it's not just the grand past. Recently, 37signals specifically made many of its applications source available. Campfire, Writebook, and Fizzy sources are now available for LLM training as well. The Rails foundation even started to publish this kind of applications as a small directory directly on the web as Reference Apps https://rubyonrails.org/docs/reference-apps . The Rails documentation, namely the part called Rails Guides , also stands out as a source on how to write Rails code. Since Rails applications tend to look similar, models get better generalizing patterns they can follow for writing new code or refactoring. Rails Guides are also coming through a bit of an update now, with completely new guides being written like the one on Accessibility https://github.com/rails/rails/pull/57293 made by a blind programmer Bruno Prieto. Ruby also had an agent-friendly documentation long before we heard about AI agents. Apart from RDoc, the usual documentation generator, Ruby has a tool called RI https://ruby.github.io/rdoc/RI md.html which is a command line interface documentation: ri Hash Document for class Hash. ri Array sort Document for instance method sort in class Array. ri read Documents for methods ::read and read in all classes and modules. ri ruby:dig methods Document for page dig methods. By passing the --no-pager option, we get results printed directly to the terminal. Today's agents are powerful enough to fetch even HTML documentation, but it's nice to have this option, especially for completely local development. World-class libraries I think that originally lots of people thought that with all LLM training happening in other languages, Ruby could felt behind. That's no longer true. The thing is that Ruby doesn't need to have the best ecosystem for LLM training. Very few companies can afford to train a model from scratch anyways. On the other hand, every developer wants to take advantage of calling LLM, embedding data, fine tune models, and run their own agents. Using agents to build AI features might look like a scene from Inception, but it's actually our reality. And that's where both Ruby and Rails have a lot to offer today. The RubyLLM revolution The things started to look better with an unofficial ruby-openai https://github.com/alexrudall/ruby-openai gem for integrating ChatGPT, today also with an option to use the official openai-ruby https://github.com/openai/openai-ruby library from OpenAI . But a small revolution started with RubyLLM https://rubyllm.com which brought the most beautiful API for Ruby chat interfaces: chat = RubyLLM.chat model: "gpt-4o-mini" response = chat.ask "What's the day today?" response = response.content A simple chat is just the beginning. RubyLLM's elegance really shows as you reach for more advanced features. Need to analyze an image, a PDF, or an audio file? It's the same interface: chat.ask "What's in this image?", with: "ruby conf.jpg" chat.ask "Summarize this document", with: "contract.pdf" chat.ask "Describe this meeting", with: "meeting.wav" Want to stream a response in real time? Pass a block: chat.ask "Tell me a story about Ruby" do |chunk| print chunk.content end RubyLLM doesn't stop with an interface to text models. Even image generation, transcribing audio, and embeddings follow the same pattern of radical simplicity: Generate images RubyLLM.paint "a sunset over mountains in watercolor style" Transcribe audio to text RubyLLM.transcribe "meeting.wav" Create embedding RubyLLM.embed "Ruby is elegant and expressive" These calls will use image, speech-to-text, and embedding models instead, but the DSL is similar. The problem with simple model calls is that they are not complete systems. They understand intent well, but are not that good at executing arbitrary tasks. That's why early tools like LangChain came with a way to abstract tools which is something that's already offered by all leading LLM companies. Tools enable models to interact with external tools by outputting JSON objects that specify functions and their arguments. This allows models to retrieve live data, something they otherwise lack as they are trained on existing data. Imagine you need for a model to help you with Search Engine Optimization SEO . You can now write a tool to get live Google search results using SerpApi and provide it to your chat context: class SearchGoogle < RubyLLM::Tool description "Search Google and return top organic results for a query" params do string :query, description: "The search query" integer :num, description: "Number of results to return max 100, default 10 " end def execute query:, num: 10 client = SerpApi::Client.new engine: "google", api key: ENV.fetch "SERPAPI API KEY" results = client.search q: query, num: num, 100 .min client.close results :organic results || .map do |r| { position: r :position , title: r :title , url: r :link , snippet: r :snippet } end end end chat = RubyLLM.chat model: "gpt-4o-mini" .with tools SearchGoogle chat.ask "What are the top 5 Google results for 'ruby on rails'?" Want a reusable agent with its own personality and tools? Then you can define the above tool-augmented chat as its own agent: class SeoAgent < RubyLLM::Agent model "gpt-4o-mini" instructions <<~PROMPT You are an SEO research assistant. You help users investigate Google search rankings, analyze competitors, and review historical position data for the sites and keywords. Use the tools available to you whenever a question requires live search data. PROMPT tools CheckKeywordPosition, SearchGoogle, FindCompetitors end agent = SeoAgent.new response = agent.ask "What are the top 5 Google results for 'ruby on rails'?" Now your application has agents with access to internal and external tools to do their best work. The DSL for that is small, compact, and beautiful. Yes, it's just an abstraction really. These agents aren't autonomous agents that writes your code. Abstractions do matter though. Good abstractions will DRY your code and become the predictable patterns for your code writing agents. If you want to see another example, go read my previous post How to implement AI agents in Rails with RubyLLM https://serpapi.com/blog/how-to-implement-rubyllm-agents/ . RubyLLM and Rails RubyLLM isn't just a Ruby library, it comes with a first-class ActiveRecord integration. A single acts as chat declaration gives you a persistent, database-backed chat complete with message history, tool calls, and model switching: class SeoChat < ApplicationRecord acts as chat end chat = Chat.create model: "claude-sonnet-4" chat.ask "What's onpage SEO?" Even better, we can now update our agent to also have persistence using this model by declaring chat model : class SeoAgent < RubyLLM::Agent chat model SeoChat model "gpt-4o-mini" instructions "You are an SEO research assistant..." tools CheckKeywordPosition, SearchGoogle, FindCompetitors end Compare all of this to the usual experience where you configure clients, define message schemas, manage request formats and write case statements for provider-specific quirks. MCPs Model Context Protocol MCP is making AI-assisted Rails development far more practical by giving agents structured access to application context instead of forcing them to rely on massive prompts. Rather than pasting files into a chat window, developers can expose tools that let agents inspect routes, models, database schemas, controllers, jobs, and other parts of an app directly. The rails-mcp-server https://github.com/maquina-app/rails-mcp-server project brings this idea to Rails by exposing application internals through MCP-compatible tooling. This allows AI agents such as Claude Code, Cursor, or terminal-based assistants to query the application in a much more targeted and reliable way, similarly as they would do for SerpApi API using the SerpApi MCP https://serpapi.com/blog/introducing-serpapis-mcp-server/ . Another interesting project is rails-ai-context https://github.com/crisnahine/rails-ai-context , which focuses on automatically generating structured Rails context for AI tools. Instead of manually curating prompts, the gem helps agents understand relationships between routes, models, Stimulus controllers, validations, and other parts of the stack. More tools The RubyLLM and MCP tooling are excellent additions to an already rich ecosystem of gems handling anything from agentic workflows like Active Agent https://activeagents.ai/ and authorization like Action Policy https://github.com/palkan/action polic , to analytics like Ahoy https://github.com/ankane/ahoy and search like Searchkick https://github.com/ankane/searchkick . Kamal https://kamal-deploy.org , the recent addition to the default Rails application Gemfile, is especially interesting given the agents can now use it to deploy your application on your own terms. This simple deploy tool comes with built-in gapless deployments, local Docker registry, or SSL/TLS support. Your agents now only need something like a Digital Ocean or Hetzner token for handling everything. Rails doesn't always come with many gem alternatives given the relatively smaller community, but the libraries it has are usually of a higher quality and the consolidation of choices once again benefit the training and output of coding agents. Future What about the future? Can Rails still keep up? Luckily, it seems that Rails is well positioned for a successful future thanks to its leadership and the Rails Foundation which now heavily invests in the documentation and ecosystem. We are now getting new guides and improvements every day. 37signals, the company DHH co-founded, and the one that's constantly giving back to Rails is on the trajectory to adopt agents in their apps, be it with agent skills or the new CLIs. This adoption is important, because DHH and 37signals still remain the stewardship of Rails. In one of the latest piece Promoting AI agents https://world.hey.com/dhh/promoting-ai-agents-3ee04945 , DHH shares his optimistic view on the progress in agent coding: But with these autonomous agents, the experience is very different. It's more like working on a team and less like working with an overly-zealous pair programmer who can't stop stealing the keyboard to complete the code you were in the middle of writing. With a team of agents, they're doing their work autonomously, and I just review the final outcome, offer guidance when asked, and marvel at how this is possible at all. DHH seems to have a healthy view on AI, continuously adopting new ways of working with it and reevaluating the status quo. Similarly, the new Rails documentation work aimed directly at AI agents https://github.com/rails/rails/blob/main/AGENTS.md is also another step forward. Better machine-readable documentation combined with MCP tooling gives agents access to authoritative framework knowledge and paves the way for agents to work on the Rails codebase itself. Fin It's not that Rails is the winner in every single caregory we could consider for agentic coding. There are more token-efficient languages than Ruby, they are frameworks that are more popular, more minimal, with a faster runtime, and with project leaders more bullish on AI. But the thing with Rails is that it ranks high enough in all these categories, from token efficiency to high quality guides. Considering all of that, Rails is the most attractive framework for robots today, just as it once was for humans. At SerpApi we continue to bet on Rails to build the world-class SERP API and we invest in its thriving ecosystem and community. We joined the Rails foundation, we are sponsoring the upcoming Rails World in Austin, and we continue to work on our Open Source projects like SerpTrail https://serpapi.com/blog/introducing-serptrail-self-hosted-search-rank-tracker/ and Nokolexbor https://github.com/serpapi/nokolexbor . Join us in our effort to make Rails better.