The sixth stop on my AI roadmap is the one engineers skip and users never forgive. You can have a great model, good retrieval, and safe tools, and still ship something that feels broken, because the answer took nine seconds to appear, arrived as a wall of text, and never said where it came from. The interface is where a person decides whether to trust the thing. That makes it a real part of the work, not a coat of paint.
Two assistants, same knowledge
Picture two shop assistants with identical training. One starts answering immediately, points at the label when quoting a price, and says “I am not sure, let me check” when they are not. The other stares silently for ten seconds, then delivers a confident paragraph with no source, including the parts they made up. Same knowledge. You trust only one of them. Every pattern at this stop is about being the first assistant.
Stream it, and let them stop it
AI replies are generated one token at a time, and the single biggest difference from every other interface you have built is that you can show them as they arrive. This is streaming: instead of a spinner and then a wall of text, words appear immediately. Same answer, radically better feel, because the user is reading while the model is still writing.
Two details make streaming feel right. Show a clear “still writing” indicator, and always give a stop button that cancels the request, because a user who realises the answer is heading the wrong way should not have to wait for it to finish. Here is the feel, in plain JavaScript:
// pretend tokens arrive one by one
for (const token of answer.split(" ")) {
if (stopped) break
output.textContent += token + " "
await wait(60)
}
TIP
Render plain text the instant it arrives, but hold a code block until its closing fence shows up. A half-finished code block flickering between broken and fixed states looks worse than a brief pause. Buffer the tokens, and render progressively.
Show where it came from, and say when it does not know
Two habits build more trust than any amount of polish.
Citations. Whenever an answer draws on a document, show the source next to the claim, and make it clickable. This turns “trust me” into “here is the paragraph”, and it makes a wrong answer visible instead of confident. If you built retrieval at an earlier stop, this is where it pays off on screen.
Admitting uncertainty. A model that has no good answer will produce one anyway unless the product gives it a way out. Design an explicit “I could not find that” state, make it look deliberate rather than like an error, and offer what to do next. Production AI features distinguish several different failure modes (nothing found, not allowed, too long, tool failed, model error, rate limited), and each needs its own recovery path, not one generic “something went wrong”.
flowchart LR Q[User asks] --> S[Stream the answer] S --> C[Show citations] C --> F[Thumbs up or down] F -->|feeds| E[Evals and fixes] E --> Q
Feedback. A thumbs up and thumbs down on every answer costs nothing to add and is the cheapest signal you will ever get about what is actually wrong. It feeds directly into the next stop.
Latency is a design problem, not just a speed problem
Models are slow compared to anything else in your app, and you cannot fully fix that. You can design around it: stream (above), show a skeleton or a “thinking about your question” state immediately, and put anything long-running in the background with a notification rather than a frozen screen. A two-second wait with visible progress feels faster than a one-second wait in silence.
WARNING
Generative UI, where the model builds interface elements on the fly, is the most over-applied pattern of 2026. It is impressive in a demo and confusing in a product when the layout keeps changing. Use it for a narrow, well-defined case, or not at all. A stable interface with a streamed answer inside it beats a shape-shifting one.
The tools you actually reach for
| Job | Popular tools | Note |
|---|---|---|
| Streaming chat hooks | Vercel AI SDK UI (useChat), assistant-ui | Free/OSS; handle streaming, stop, and message state |
| Chat UI kits | assistant-ui, shadcn AI components | Free/OSS building blocks with citations and feedback |
| Rendering replies | react-markdown, Shiki | Free/OSS; buffer code blocks until complete |
Trust is designed, not assumed
The lesson from this stop is that the model’s quality is only half of what a user experiences. The other half is whether the interface streams, cites, admits uncertainty, and asks for feedback. Those are design decisions, they are cheap, and they are what separates an AI feature people rely on from one they try once. Build the screen with the same care as the pipeline behind it.
Show the work, show the source, and let them stop you.
Sources
- metacto: AI chat UX patterns for production interfaces for streaming, the stop button, failure modes, and generative UI cautions
- Setproduct: designing AI chat interfaces, anatomy, patterns, pitfalls for the anatomy of a chat interface and uncertainty cues
- thefrontkit: AI chat UI best practices for 2026 for progressive rendering and buffering code blocks