Deterministic UIs need loading, error and empty states; AI surfaces add thinking, uncertainty and refusal — and they need a feedback channel, because output quality is a distribution, not a constant. Implement the full state rubric from your design system, and wire thumbs, edits and regenerates into the eval set that actually improves the product.
Tier: Core · Workflow area: AI features in the client
This playbook gives the AI surface its missing state machine and turns user reactions into engineering signal instead of a decorative thumbs row.
Skip nothing here for "internal tools" — internal users abandon bad AI surfaces just as fast, they just do it silently.
Implement the AI state rubric as first-class states. Beyond loading/error/empty, an AI surface has states deterministic UIs never needed. Enumerate them in the component's state type — not as ad-hoc conditionals:
Build the states as design-system components, once. A GenerationStatus, a Citation chip, a RefusalNotice, a FeedbackBar — reviewed for accessibility (pb-33 covers the screen-reader side of streaming) and reused across every AI surface, so the product's AI states are consistent rather than re-improvised per feature. Add each to your preview/Storybook matrix in all variants.
Instrument implicit signal — it is bigger and more honest than thumbs. Emit structured events with a shared schema (surface, model, promptVersion — hashed/IDs, not raw text, in analytics):
ai_response_regenerated — the strongest cheap dissatisfaction signal.ai_response_stopped mid-stream — wrong direction or too slow.ai_output_edited — for insertable drafts, capture an edit-distance bucket; heavy rewrites mean the draft missed.ai_response_copied / inserted / link-clicked — acceptance signals.ai_session_abandoned — thinking state shown, user left before completion.Make explicit feedback cheap, then ask for one more step. Thumbs up/down on every assistant turn, one tap, no modal. On thumbs-down only, offer optional structured tags (wrong, outdated, refused unnecessarily, formatting, unsafe) plus free text. Acknowledge in-UI what feedback does ("helps improve answers") — response rates roughly double when the affordance looks alive rather than decorative.
Close the loop into the eval set. This is the step that separates signal from theater: flagged interactions (thumbs-down, heavy edits, immediate regenerates) are queued with full context — prompt, retrieved context, output, model and prompt version — into a review tool. A human triages weekly: real failure or user error; genuine failures become eval cases (input plus expected-behavior assertion) in the suite that gates prompt and model changes. Report the loop's health as metrics: feedback rate, triage throughput, and regression count caught by eval cases sourced from user feedback. When a fix ships for a failure class, you have a defensible "we fixed the thing users flagged" narrative — the loop is visible to users and stakeholders alike.
Thinking, uncertainty, refusal, error and empty are product states with designed components — and every thumbs-down is a future eval case. The feedback bar is not a sentiment widget; it is the intake pipe of your quality system.
FeedbackBar; it does not do your analytics or eval plumbing.All of this is your own UI and pipeline — no provider dependency. In restricted shops the constraint is where flagged interactions (which contain prompts and outputs) may be stored: keep the corpus in your tenancy alongside other user data, run triage clustering with an in-tenancy or local model, and keep third-party analytics to text-free event metadata only.
A flagged-interaction corpus concentrates your users' most sensitive prompts in one table. Apply retention limits and access controls to it from day one — it is a honeypot by construction.