I've been building web applications for 30 years, and Rails apps since 2006. Once I got a taste of that sweet, sweet convention-over-configuration, I never wanted to go back. DHH released Rails with ActiveRecord, and ActiveRecord needed only two lines of Ruby to start pulling data out of a database -- an amazing feat for the time. But it didn't stop there: it also modeled table joins the way developers actually talk about databases.
Developers think "Orders has many Product Items." In a Rails app, the Order class gets one line to make that connection: has_many :product_items. The code reads exactly the way a developer already thinks about it.
That's Desire Path Design. A desire path is what a grounds foreman gets by watching where people actually walk between buildings, then paving the sidewalk there -- instead of laying down the "optimized" path some architect drew up for aesthetics and construction cost. ActiveRecord succeeded because it stopped trying to be a pure relational mapper and started being a human one. DHH realized we don't think in terms of JOIN logic; we think in terms of has_many.
Now a new player has joined the game: AI agents. And they have their own opinions.
When an agent calls a method that doesn't exist, we usually call that a "hallucination" and try to prompt-engineer it away -- we're the architect posting "Keep Off the Grass" signs. Steve Yegge, ex-Google and ex-Amazon, argues we should be the foreman instead.
Yegge recently hit on something that feels exactly like the early days of Rails. While building tools for agents, he stopped trying to fix their prompts and started fixing his code instead. If an agent hallucinated a command that didn't exist, he didn't tell it it was wrong -- he went and built the command. That's Desire Paths design applied to software: if every agent thinks your CLI should work a certain way, they're telling you what the most intuitive version of your software actually looks like. You can spend your life fighting their "hallucinations," or you can make them real, until every guess the agent makes turns out to be correct.
In the VC world we look for efficiency. Yegge proposes something like a survival ratio for developer tools that reads a lot like a formula for technical debt versus utility: Survival(Tool) equals Savings times Usage, divided by Awareness Cost plus Friction Cost. Savings asks whether the tool actually saves tokens and money, or whether the agent is better off writing the logic itself. Awareness asks whether the agent even knows the tool exists without a bloated, expensive system prompt. Friction asks how many times the agent trips over your weird syntax before it gives up. If friction is high, the agent just routes around you -- it writes its own messy workaround because your "correct" way is too hard to follow.
For those of us in the Rails ecosystem, this is just convention over configuration for the LLM age. Design for guessability: if an agent keeps trying to call task.close instead of your actual task.update(status: :archived_final_v2), add the close method. Reduce the awareness cost: use predictable patterns, so if your API looks like every other RESTful resource the agent has seen in training, it doesn't need to read your docs to get it right.
Being "right" as a developer used to mean forcing users to follow your perfect schema. If you're building for agents, that instinct is a liability. The goal isn't the most elegant, rigid architecture -- it's the most discoverable one. We should stop treating agent errors as bugs and start treating them as feature requests. If the machines keep hallucinating a better version of your app, maybe it's time to start paving the path they're actually taking.