Why You Can't Put a Progress Bar on an Agent
Every progress bar you have ever shipped rests on one assumption: you know the denominator. Uploading a 40 MB file? The denominator is 40 MB. Installing 212 packages? The denominator is 212. The bar is honest because the total work is known before the work begins.
An agent breaks this assumption at the root. It doesn't execute a predetermined list of steps — it discovers its remaining work as it goes. It reads a file, which reveals three more files worth reading. It runs the tests, which fail, which spawns a debugging detour nobody planned. Step 4 of 7 becomes step 4 of 19 becomes, occasionally, step 4 of 4 because the last three turned out to be unnecessary. Percent-complete for an agent isn't hard to compute. It's undefined. There is no denominator until the work is finished, at which point the answer is always 100%.
Yet look at what we ship: spinners that promise imminent completion, bars that creep to 90% and stall, labels that say "almost done…" on minute two of a task that takes eight. These are all small lies, and users catch them. The interesting design question isn't how to fake progress more convincingly — it's what honest reassurance looks like when the duration of the work is structurally unknowable.
The Denominator Problem Is Structural, Not Temporary
It's tempting to treat this as a maturity issue — models will get more predictable, telemetry will improve, and eventually we'll estimate agent runtimes the way we estimate file transfers. That misreads where the variance comes from.
A file transfer's duration varies because of throughput. Its work is fixed; only the rate is noisy, and rates can be smoothed. An agent's duration varies because the work itself is an output of the process. The plan is provisional by design: exploration reveals scope, failures trigger retries, and intermediate results decide which branches even execute. This is precisely what makes agents useful — a system that could enumerate all its steps upfront wouldn't need to be an agent. You could write it as a script and give it a real progress bar.
So the unpredictability isn't a defect to be engineered away. It is the signature of the capability you're selling. Better models widen the gap, because we hand them longer, more open-ended tasks. A 2023-era agent that autocompleted a function finished in seconds. A 2026-era agent refactoring a module runs for twenty minutes, and whether it's twelve or forty depends on what the test suite says at minute nine.
Classic UX guidance quietly assumed this problem away. Jakob Nielsen's well-known thresholds say anything over 10 seconds needs a percent-done indicator plus a way to interrupt. That advice is correct — and unimplementable here, because it presumes percent-done exists. Agent tasks blow past 10 seconds routinely and offer nothing honest to put in the bar. The old playbook doesn't fail gracefully; it fails at the axioms.
Every Fake Indicator Is a Loan Against Trust
Faced with an impossible bar, teams reach for the traditional workarounds, each a small act of what researchers politely call benevolent deception:
- The decoupled bar that advances on a timer rather than on actual work, sprinting to 80% and then crawling.
- The rotating status line — "Analyzing…", "Thinking deeply…", "Almost there…" — cycling through canned phrases uncorrelated with what the system is doing.
- The eternal spinner, which at least has the decency to promise nothing beyond "not crashed."
For short waits, this genre sort of worked. Progress bars have been lying to us for decades — easing curves that make bars feel faster, front-loaded movement when users are least invested — and the deception survived because the wait ended before the lie unraveled. Ten seconds of fiction is forgivable; the file did arrive.
Agents change the payoff matrix. When a task runs eight minutes and the bar hit 92% at minute two, the user has six full minutes to study the lie. Do this twice and they stop believing your indicators entirely — including the honest ones. The failure compounds in the notification tier too: if every milestone pings the user, you build what one design pattern catalog calls a cry-wolf dashboard, where alerts get ignored precisely when one finally matters.
And the worst option is the one most chat products ship by default: a typing indicator that emits nothing for ninety seconds. It combines every failure — no evidence of work, no estimate, no milestone, no exit — into a single animated ellipsis. The user's mental model degrades from "it's working" to "it's stuck" to "I should refresh," and refreshing is often the one action that actually destroys the work in progress.
Show Receipts, Not Percentages
If percent-complete is undefined, what's left? Evidence. You can't tell the user how far along the agent is, but you can prove it is genuinely working and let them judge the trajectory themselves. Three kinds of receipts hold up:
- Verifiable milestones. Not "35% complete" but "read 14 files," "reproduced the bug," "7 of 9 tests passing." Each claim is checkable and none implies a schedule. A visible plan with steps ticking off is the strongest version — the denominator still shifts as the plan revises, but users forgive a plan that visibly grew ("found an edge case, adding a step") in a way they never forgive a bar that silently rewound.
- The live activity feed. Streaming tool calls, current file, current command — a chronological log with a pinned "current step." This is where the research gets counterintuitive: Buell and Norton's operational-transparency experiments found that people prefer a longer wait with visible effort over instant results, because watching the labor raises the perceived value of the outcome. Agents can show real labor. Faking effort is a dark pattern; surfacing actual effort is one of the few cases where the honest choice is also the persuasive one.
- Spend-so-far. Elapsed time, tokens consumed, steps taken. No denominator required — it's an odometer, not a fuel gauge. Practitioners develop calibration from it fast: if similar tasks usually cost ~200K tokens and this one just crossed 800K, something is wrong, and the user can act on that long before any timeout fires.
- https://www.nngroup.com/articles/response-times-3-important-limits/
- https://www.nngroup.com/articles/progress-indicators/
- https://pubsonline.informs.org/doi/10.1287/mnsc.1110.1376
- https://www.aiuxdesign.guide/patterns/agent-status-monitoring
- https://developers.cloudflare.com/agents/concepts/agentic-patterns/long-running-agents/
- https://www.smashingmagazine.com/2026/02/designing-agentic-ai-practical-ux-patterns/
- https://newsletter.victordibia.com/p/4-ux-design-principles-for-multi
- https://blog.logrocket.com/ux-design/ui-patterns-for-async-workflows-background-jobs-and-data-pipelines/
- https://davechen.net/2017/02/benevolent-deception-fake-progress-bars/
