May 30, 2026 · 10 min read
Five patterns I keep seeing in agent products that work
Five things I keep noticing in the agent products that actually make it out the door.
Most agent products fail at the same five places. The ones that work solve all five. I keep seeing this across every agent product I work on, ours and others. Here they are, each with the failure mode it prevents.
1. Stream everything from the first token
Latency is the silent killer. An agent that takes four seconds before showing anything feels broken, regardless of how impressive the eventual answer is. Users will wait twice as long for a streaming response as they will for a blocking one. The same total elapsed time feels different.
The fix is mechanical, three parts.
First, stream the response token-by-token from the moment the request hits your server. Use SSE or WebSockets. Do not buffer.
Second, the moment the user submits, show a thinking indicator. A pulsing dot, a typing cursor, anything that signals presence. The indicator must appear within 100ms of the click; if it takes longer, the user starts to doubt. Use an optimistic UI update on submit; show the indicator before the network round-trip.
Third, never go silent for more than 800ms without a sign of life. If the model is composing a long response and the first token hasn't arrived, send a keep-alive event. If you're calling a slow tool, stream a "calling tool X" status before the tool returns.
Failure mode this prevents: the visitor refreshes the page because they think it's broken. They leave. They never come back.
Anti-pattern to watch for: the developer who, six months in, hardens the latency by adding a "loading..." text after a 500ms delay. That's a thermometer for a fever. Fix the underlying streaming, not the visible symptom.
2. Render the agent's work, not just its output
A black-box answer is hard to trust. Users will not trust an agent that says "done" without showing what it did. They will trust an agent whose work is visible, even if the work is imperfect.
The pattern: every tool call the agent makes, render as a step card the user can expand. Show the tool name, the elapsed time, the human-readable summary, and the raw input and output one tap deep. Claude Code does this with its tool transcripts. Lena Agent does this with its canvas. Both products converged on this independently because it solves the same problem: trust.
A useful test: if your agent does five things in a row, can the user see all five things? Or do they just see "I helped you with that"? If the answer is the second, the agent is a black box, and the next time it makes a mistake, the user has no recourse but to distrust the whole product.
Failure mode this prevents: the user catches the agent in one mistake and stops trusting it for anything. With visible work, the user sees the mistake in context, can correct it, and rebuilds trust. With a black box, one mistake is fatal.
Anti-pattern to watch for: the "show your reasoning" pattern where the model dumps its chain-of-thought as a wall of prose. That's not visible work; that's a transcript dump. Visible work is structured: tool name, status, elapsed time, input, output. Structured because the user is trying to scan it, not read it.
3. Generative UI over static UI
Pre-designed screens cap the agent's expressive range. The agent can do twenty things, but the UI was built for the seven the designer imagined. The result is screens that look thin (the data is sparser than the screen accommodates) and screens that look overloaded (the data is richer than the screen handles).
The fix is the view-primitive pattern I described in essay 2. Design the atoms, not the screens. Let the agent compose at runtime.
This is the single biggest UX unlock I've found in building agents. It is also the most expensive to set up correctly, because you have to design a primitive library that has the right grain (atoms small enough to compose, large enough to feel coherent) and the right fallback layouts (for when the agent produces something invalid).
A useful test: can you describe your agent's home screen without saying "the home screen"? If you can ("a list of step cards from the last conversation, an input bar at the bottom, a takeaway tray on the right"), you're generative. If you can't ("just our main view"), you're static and probably bottlenecked.
Failure mode this prevents: the agent grows in capability over time and the UI fights it. Each new tool requires a new screen. The cost-per-feature stays high. The product loses to a competitor whose UI was generative from day one.
Anti-pattern to watch for: the "we'll add a new tab when we need it" pattern. Tabs proliferate, then become a nav bar, then a hamburger menu, then a buried settings page. Generative UI sidesteps all of this by never tab-bound in the first place.
4. Voice-supported, not voice-required
The wow demo always involves voice. The daily usage is mostly tap. Both have to work. If you launch voice-required, users on the train or in a meeting will never use the product. If you launch tap-only, your demo doesn't land, your TikTok doesn't go viral, and your first impression is forgettable.
The discipline: every primary action is reachable by speaking. Tap is supported and never required. The agent picks the right modality for each response (voice for short confirmations, text for long answers, both for the demo moments).
A useful test: open your product on a phone, mute the speaker, sit in a coffee shop. Can you complete the most important user flow without anyone hearing you? If yes, you're voice-supported correctly. If no, the voice is required and you've capped your real-world usage.
Failure mode this prevents: the demo lands but retention drops because users don't have private spaces to use voice. Or the opposite: tap works fine but no one shares the product because there's no wow moment.
Anti-pattern to watch for: voice as a setting buried three menus deep. Voice has to be a one-tap toggle visible on the primary surface, or users will never discover it.
5. Generalized graders, not pre-trained per-domain classifiers
Pre-trained classifiers are expensive to build and don't scale across categories. Every new domain requires a new model, new labeled data, new evaluation set. The cost-per-domain stays high.
An LLM that reasons over structured inputs (landmarks, statements, data, code) against a natural-language target works on day one for any new domain. You trade some precision for breadth.
Concrete example: in Maestro, we grade physical form by passing MediaPipe hand landmarks and a natural-language target ("the user is attempting the Charlier cut; the failure mode to watch for is the pinky going under instead of over on move 2") to Sonnet 4.6. The model returns a structured correction. This works on day one for any card-cut. It also works on day one for harmonica embouchure, juggling toss arcs, and chess opening principles, because the grading mechanism is "reason about the input against a natural-language target," not "classify into one of N predefined categories."
The precision is lower than a domain-specific classifier. The breadth is wider by two orders of magnitude. For most agent products, breadth is what you need.
Failure mode this prevents: the cold-start problem for any new domain. With pre-trained classifiers, supporting a new skill means weeks of data collection and training. With generalized grading, it's one prompt and a target description.
Anti-pattern to watch for: the team that wants to build "the best possible grader" for their first domain. Perfect is the enemy of breadth. The 80% generalized grader is more valuable than the 95% per-domain classifier, because the 80% grader works for the 99 other domains you don't have data for yet.
A bonus sixth thing
Trust the system prompt more than you trust the model.
Models drift. Anthropic releases a new version, the model behaves slightly differently, your prompts start producing different outputs. The fix is to put as much of the agent's behavior in the system prompt as possible, not in the model's training. System prompts are versioned by you, in your repo, and they stay stable when the model changes.
Concretely: put the agent's voice rules, its tool-use policies, its forbidden behaviors, and its fallback strategies in the system prompt. The system prompt should be at least 2,000 tokens for any non-trivial agent. People who try to keep their system prompts short to "let the model figure it out" pay for it in unpredictability.
Closer
These five are just the places I keep coming back to: where I've watched agent products (mine very much included) get fast, trustworthy, expressive, accessible, and general, or fail to. None of it feels settled to me yet. If you've built agents, I'd love to hear which one you think I've got wrong.