We were designing a site for an infrastructure product, so we did the obvious thing and went to read twenty-three of them. Vercel, Stripe, Supabase, Neon, Railway, Fly, Clerk, WorkOS, Convex, Better Auth, Modal, E2B and a dozen more, all fetched on the same day.
We fetched them with a tool rather than a browser. We arrived as an agent, in other words. That turned out to be the whole story.
Six of them handed back a different website.
Not a stripped-down version of the marketing page. A different document, with a different reader, a different voice, and different instructions. Resend, Neon, Railway, Fly, Liveblocks and Convex all served something closer to an operator's handbook: which CLI to install, whether to use MCP or the CLI and when, a mental model of the resource hierarchy, and a list of things to ask a human about first.
The second front door
The pattern is common enough now to have conventions. One domain, two faces, selected by Accept header, user agent, or a path suffix.
The human face is the one you know. A positioning line, a logo wall, product panels with dashboard screenshots, testimonials, a fat footer. Vercel's homepage contains zero code blocks. The teaching has moved entirely into the docs.
The agent face is newer and stranger:
llms.txtand per-page markdown mirrors. Vercel's docs return markdown with YAML frontmatter if you ask that way.- Dedicated setup pages.
convex.dev/agent-setup.mdis a call-to-action on Convex's site. The CTA is a URL ending in.md. Railway hasagents.railway.com. Cloudflare has/agent-setup/. - MCP servers as a distribution channel.
npx -y add-mcp https://mcp.vercel.com -g. - Skills and plugins as packaging.
npx skills add liveblocks/skills. - Copyable prompts. Cloudflare offers a separate one for Claude, Codex, Cursor and OpenCode. Supabase's pricing page has "Copy as Markdown", "Ask ChatGPT" and "Ask Claude" buttons under the heading.
- No marketing at all. Fly's agent face opens with a curl install line and
sprite org auth. That is the page.
Stripe goes furthest. Every documentation section carries three controls — Ask about this section, Copy for LLM, View as Markdown — and stripe docs works from the terminal. The documentation has become an addressable resource for a reader that is not a person. Mintlify, which sells documentation infrastructure, now describes itself as the knowledge platform built for agents and grades customers on a metric it calls an agent score: can agents read your docs?
That is all good craft. If you are building a developer product, copy it. But it is not the part we want to talk about.
The part that is an authorization policy
Here is the running order of Neon's agent page. The Primitives, then Setup, then Get a Backend, then What do you want to do?, then Ask a human before, then Don't scaffold deprecated stuff, then Machine Interfaces.
"Ask a human before" covers deleting things, running migrations, and changing billing. Railway publishes its own version under "before destructive actions."
Read those sections as structure rather than as prose. They enumerate a set of operations. They classify each one. They specify different control flow for the dangerous class: stop, surface it, get a person. And they are addressed to an autonomous process that is about to act on a production system with real credentials.
That is an authorization policy. It was written by the people who understand the blast radius best. It is public, it is versioned alongside the docs, and it is specific.
It is also enforced by nothing at all.
It would be cheap to mock this, and it would be wrong. These teams are not naive. They shipped the only control available at the layer they own. A database company cannot reach into your agent's execution loop. The one channel it has to your agent is the text that agent reads, so writing the boundary into that text is the correct move. We would have done the same.
But it is worth being exact about what this kind of policy cannot do, because every item on the list matters.
It is advisory. Nothing stops the operation. If the agent proceeds anyway — an oddly worded task, a context window that pushed the guardrail out, a model in a hurry — the migration runs, and the gap between policy and outcome produces no signal.
It has no attenuation. If your agent hands a subtask to another agent, nothing carries "ask before migrating" with it. The instruction lives in one context window and dies there. Whatever runs downstream starts with no constraint.
It cannot be revoked. A policy delivered by being read has no mechanism for being unread. It also cannot be narrowed for one caller, one project, or one hour.
It produces no audit. There is no record of the decision and no record of the boundary having been considered. Afterwards you cannot tell "the agent asked and a human approved" apart from "the agent never thought about it." Two very different events, no trace of either.
And the reader is the subject. The instruction restricting the agent is delivered to that agent, to apply to itself. The party being constrained is the party enforcing the constraint.
That last one is the same structural problem as telling a model not to share confidential information, which we have argued against before and then went and tested rather than asserted. Prose asking an agent to restrain itself is not a boundary. It is a request, made to the one party that wants the task finished.
What is new here is not that someone tried prompt-based safety again. It is who is writing it. This is not a model provider telling an agent to behave. This is the owner of the resource — the database, the deploy pipeline, the billing account — publishing a boundary for their own system, to strangers' agents, over the public web. They are not trying to make a model well behaved. They are trying to express a permission.
A specification waiting for a runtime
Each of those five gaps has a known fix. None of it is research.
An operation that must not proceed without approval is an escalation, and it can be a real outcome: not a denial, not a pass, but a third state that stops execution and puts the decision in front of a person. Attenuation across a delegation hop is solved the moment authority is a signed object rather than a sentence, because each hop can carry a subset of the last. Revocation and expiry come along with that same change. Audit is what you get when the decision is made by something whose job is making decisions, instead of by a language model reading a paragraph about itself.
The interesting thing about Neon's list is that it is already the input to all of this. "Deletes, migrations and billing changes require human approval" is a policy written in English that would translate almost mechanically into a policy that runs. The classification work, which is the part that requires knowing the system, is done. What is missing is a runtime that can hold it.
That is roughly what we are building, so weigh the conclusion accordingly. The observation holds without us, though. The industry has already worked out that agents need permission boundaries, and has independently converged on writing them down. Six of twenty-three sites, with no coordination, publishing the same category of text.
The next step is not convincing anyone that the boundary matters. Neon and Railway made that argument better than we could, on their own documentation, unprompted. The next step is making the boundary something other than a paragraph the agent is trusted to have read.
The full teardown — design tokens measured from the DOM, documentation layouts, onboarding ladders and pricing structures across all 23 sites — is separate work. This post is about one finding in it.