What Should Go in AGENTS.md for a Rails App?
One of the first things that annoyed me about coding agents was how much time they could spend figuring out a repository. The models were already getting good at writing Rails code, but they didn’t know much about the application they were working in.
I’d ask for a feature and watch an agent dig through file after file looking for patterns. Or it would skip that part, make a reasonable guess, and write something that worked but didn’t really fit the rest of the app.
I started adding AGENTS.md files pretty early on. I wanted the agent to know what sort of app it had opened, which decisions had already been made, and where to look before coming up with its own approach.
I ended up taking this pretty far with Rails Baseline, a Rails SaaS starter where I wrote the agent documentation alongside the code. I even tested it by giving fresh agents product features without telling them how to handle billing, permissions, or the rest of the architecture. That gave me a much better idea of what instructions were actually useful.
Start with the application, not a Rails style guide
Section titled “Start with the application, not a Rails style guide”An agent probably doesn’t need another explanation of what an Active Record model is. It does need to know how your application handles accounts, authorization, billing, and background jobs.
Some of that belongs right in AGENTS.md. What Rails version are you on? Is this an account-based SaaS? Are you using Pundit or something else for authorization? Does the frontend use Hotwire, React, or a mixture? How do you run the tests?
I’d also tell the agent where to look when a task needs more detail.
For example, here’s a starting point for an account-based Rails app:
# Working in this app
- Rails 8, PostgreSQL, ERB, Turbo, and Stimulus.- Accounts own tenant data; users belong to accounts through memberships.- Authorization uses Pundit.- Billing uses Pay with Stripe.
Before changing authorization, read docs/authorization.md and look atan existing policy and its tests.
Before changing billing or webhooks, read docs/billing.md and checkthe Pay version installed in this app.
For background jobs, read docs/jobs.md and follow an existing job.
Run the tests relevant to your change. For permission changes,include a test that checks access from another account.Run bin/rubocop and fix any offenses before finishing.A real application’s file would cover more of the app than this example, but the idea is the same: give the agent the basics, then point it to the details instead of trying to explain everything upfront. It has enough to get started without me repeating the setup in every prompt.
Notice that the billing instructions don’t try to explain every Pay API or webhook edge case. That can live in the billing documentation, where the agent can read it when it’s actually working on billing.
And this isn’t an argument that AGENTS.md needs to be tiny. The one in Rails Baseline is fairly substantial. I care more about what information belongs in the initial context and what should be available when the task calls for it.
“Write clean code” isn’t an instruction
Section titled ““Write clean code” isn’t an instruction”I’ve seen plenty of agent instructions that read like a list of general programming advice.
“Follow best practices.” “Keep things maintainable.” “Write clean code.”
Okay, but what do you mean? Even another developer would have to ask.
Compare that with telling an agent that the application uses Pundit, that account-owned records need to be scoped before authorization, and that it should inspect an existing policy before adding a new one.
Now it has something it can actually check against the code.
If I want the code to follow the project’s style rules, I can tell the agent to run bin/rubocop and fix the offenses. RuboCop won’t tell me whether the feature is well designed, but at least it’s checking something specific instead of guessing what I mean by “clean.”
The same goes for “write tests.” Which tests? Are you using Minitest or RSpec? Is there a command that runs the checks you expect before a PR? What behavior absolutely needs a negative test?
I still put general expectations in agent files where they help. I just try to make them specific to the repository instead of filling the file with advice that could apply to any project on GitHub.
Pay and Stripe taught me this the hard way
Section titled “Pay and Stripe taught me this the hard way”Billing was one of the places where I kept having to steer agents back onto the rails.
I’d ask for a Stripe billing feature in a Rails app using Pay. The agent might hallucinate a Pay API that didn’t exist, jump straight into Stripe calls when Pay should handle that part, or get through checkout and only partially implement the webhook handling. Sometimes webhooks were skipped altogether.
I tried pointing agents at Pay documentation or code from another application. That helped, but I was still having to explain the same things in later sessions.
What eventually worked was documenting the approaches that had actually survived implementation and testing. Agents could inspect the installed library version, the APIs we’d verified, and working code that showed when to use Pay and when a direct Stripe call was appropriate.
The root agent file didn’t need to become a manual for the Pay gem. It needed to send the agent to that material before the agent started writing billing code.
These days, billing in my better-documented apps is a much less eventful experience. It’s not that an agent can’t write a bug anymore. I just don’t spend nearly as much time correcting the same fundamental Pay and Stripe mistakes.
That leaves me free to describe the feature I want instead of explaining how the payment integration works every time.
Let the code explain the rest
Section titled “Let the code explain the rest”Documentation is great until it disagrees with the application.
If an agent is adding another Pundit policy, I’d rather it read a nearby policy and its tests than follow a beautifully written document describing a pattern nobody uses anymore.
This is why I like keeping the instructions in a few layers. AGENTS.md covers the big decisions and tells the agent where to go. Architecture documents explain the decisions that affect the whole app. Contracts and recipes cover areas like billing, jobs, and common extensions. Existing code and tests show what actually works.
You don’t have to load all of those files for every task. A CSS change probably doesn’t need the complete Stripe billing documentation in context. A subscription change definitely does.
The important part is making it easy for an agent to find the relevant material before it starts guessing.
The instructions get better as you build
Section titled “The instructions get better as you build”I didn’t sit down and design a perfect collection of instructions before writing code. Most of what I use now came from building applications, pushing back when an agent made a bad decision, and documenting the approach once we had something working.
I also use an agent-maintained feedback document during some development sessions. It records places where instructions weren’t clear, where I asked the agent to change an approach, or where the finished feature didn’t match what I had in mind.
That feedback isn’t automatically promoted into AGENTS.md. I look through it and decide what is useful enough to keep. Sometimes the lesson belongs in a contract, a recipe, or a reusable skill. Sometimes it was just a bug in one feature, and fixing the code and test is enough.
I’ve also had agents look across multiple applications at working implementations and the docs that helped produce them. That’s been useful for finding patterns worth carrying into the next project.
This process has worked well enough that I made a private Phoenix starter based on what I’d learned building Rails Baseline. I wanted the same head start when Elixir and Phoenix made more sense for an application. The framework and language details had to change, of course, but a lot of the lessons about accounts, permissions, billing, testing, and giving agents useful context carried over.
What I’d do in a new Rails app
Section titled “What I’d do in a new Rails app”If I’m starting another account-based Rails SaaS, I’ll probably use Baseline. That’s one reason I built it.
If I were starting with rails new, I’d begin with an AGENTS.md that describes the application, the stack, the decisions I already know, how to run the tests, and where to find deeper documentation. Then I’d spend some time on the big sections of the app as they take shape: authentication, billing, authorization, and jobs.
I wouldn’t try to predict every instruction the agent could possibly need. I’d document what I know, let it work, review the result, and write down the lessons that are likely to come up again.
At this point, the well-documented parts of my Rails apps are pretty close to just working when I hand an agent a new product feature. I still review the code and test the result. I’m just spending a lot more time talking about what the product should do and a lot less time explaining the same Rails SaaS plumbing.
If you’re curious how that played out in practice, I tested Rails Baseline with fresh agents and deliberately left the architecture out of the prompts.