Errors are the last interface agents read

nkko1 pts0 comments

Errors Are the Interface Agents Actually Read - Steel | Open-source Headless Browser API

')">

Sessions API

Pricing

Blog

Docs

We're hiring!

7.1K

Log in / Sign Up

← Back to Blog

Errors Are the Interface Agents Actually Read

Errors Are the Interface Agents Actually Read

Jun 2, 2026

Jun 2, 2026

San Francisco

Nasr Mohamed

Nasr Mohamed

TL;DR: Error messages are not just cleanup copy. For agent-facing products, they are one of the few places where the product gets to correct the agent while it is actively screwing up, before the user decides the whole thing is broken.

We've been overhauling errors recently. Not as a polish pass. Not because someone found religion about microcopy. Because the logs kept showing us the same ugly thing: people were failing, agents were confidently making it worse, and our product was giving them almost nothing useful at the moment it mattered.<br>When an error fails to do its job, the user (or the agent acting on their behalf) walks away assuming something is broken on our end. Usually it isn't. They just couldn't tell.<br>The principle I keep coming back to is simple.<br>Every bad error message is a missed activation. Every one. The error is the first place your product talks back to someone who is, right then, deciding whether you're worth their next hour. If it sounds confused, you sound confused. If it points them at the fix, you just bought yourself a little bit of trust.<br>I want to walk through what we're working on right now. Including one fight I had with a coding agent that I'm reversing my position on, live, in this article.<br>What we're moving every error toward<br>The shape we're trying to push every error into is roughly this: what happened, in the language of the user's input; which assumption or input was wrong; and how to do it correctly. Plus a link, ideally to a docs page that's structured to be parsed by an LLM as well as read by a human. Clean markdown.<br>We've built the mechanism to include docs links directly in JSON error responses, so when the user (or their agent) logs the failure, the link sits next to the message. Why this matters: a lot of what we were seeing came from people and agents who hadn't read the docs, or there was a page in the docs that already explained exactly what they'd hit, and they had no way to find it from inside their context.<br>Agents amplify that problem. They will confidently act on a bad prior unless the product corrects them at the moment of failure. That's the loop we're trying to close: the failure should carry the next useful pointer, instead of forcing the user or the agent to go hunting for it somewhere else.<br>Honestly though, the bigger lever has been embarrassingly simple: write the error like the person or agent reading it has never seen your docs, because they usually haven’t. Not more words. More context. A single sentence that names the cause and the fix beats a docs link the agent has to click to get to the same information.<br>The UUID example<br>The cleanest before/after I have is the session ID error.<br>You can optionally pass your own session ID when you create a session in Steel, and it has to be a UUID. Users (and increasingly, coding agents) kept passing in random strings. Our original error was something like "format incorrect." It didn't really mean anything. The agent would see it, shrug, try a different random string. Technically accurate. Functionally useless. The worst category.<br>We changed it to tell the user, in one line, to pass a valid UUID. That was it. The error rate on that endpoint dropped by more than half. And this was before agents got good. Even regular users were hitting that one bad sentence and bouncing.<br>A vague error doesn't fail safely. It fails quietly into the category I'd describe as "the user concludes the product doesn't work." A specific error turns that same moment into a one-second correction.<br>The happy path gets users interested. The failure path decides whether they come back.<br>The Bearer fight<br>Steel doesn't use the Authorization header at all. Our auth header is a custom one: steel-api-key: . The reason was boring and practical: Steel spends a lot of time around other people’s websites, cookies, proxies, sessions, and auth state, so we wanted our control-plane auth to be extremely explicit. steel-api-key is ugly in a useful way: you can see exactly what it is.<br>People kept sending us Authorization: Bearer anyway. Mostly coding agents. The agents were confused in the most boring possible way: they had seen ten million APIs use Bearer auth, and decided ours did too. The model would confidently tell users that's how the API works, they'd paste the snippet, the request would fail. We'd see the same pattern over and over in the logs.<br>First push: a clear error that said we don't use Bearer, with a link to the docs. The error fired. It barely moved the needle. My best guess is that the model already had Bearer baked in deep, from an old crawl or just generic API priors, and one error wasn't going...

error agents agent docs user read

Related Articles