Busy signals
Ten ways software says it's working on something, side by side on one run of an agent, and what each one tells you: that it's alive, what it's doing, how long, how to stop it.
Spinner and verb
Pondering…
A playful verb keeps it company; the seconds and tokens are what tell you it's moving.
Pulsing dot
Calm and unmistakably alive, and silent about everything else.
Typing dots
Borrowed from people typing: it promises words are coming, not when.
Shimmering label
Thinking…
A light sweeping through the words: alive, and the words can say which step it's on.
Steps
- Thinking…
- Searching the site
- Reading 3 pages
- Checking the forecast
Each tool call as a line, ticked off: the most it can tell you, if the steps are known.
Progress bar
Honest when the work is measured. Here it's faked, crawling toward 90% until it isn't.
Skeleton
The shape of the answer before the answer: good when the shape is known.
Streaming
The answer is its own signal, once it starts; before that, it needs one of the others.
A face
Thinking…
Thinks with its face, talks while the words come: charm first, information second.
Orb
Presence without text, for when there's no screen to read: a mood, not a status.
Thinking, 1s in.
// One made-up run of an agent, in seconds, and every signal reads the same moment of it.
export const PHASES = [
{ value: "waiting", label: "Waiting", from: 0 },
{ value: "thinking", label: "Thinking", from: 1.2 },
{ value: "tools", label: "Using tools", from: 5.4 },
{ value: "answering", label: "Answering", from: 9.6 },
{ value: "done", label: "Done", from: 13.6 },
];
// A progress bar for work of unknown length, as they're usually faked:
// slower and slower toward 90%, never past it, until it jumps to full.
export function fakeProgressAt(t: number) {
if (phaseAt(t) === "done") return 1;
return 0.9 * (1 - Math.exp(-t / 3.2));
}
// Each signal is scored on four questions: is it alive, doing what, for how long, how do I stop it.
{ value: "verb", name: "Spinner and verb", tells: { alive: "yes", what: "partly", howLong: "yes", stop: "yes" } },
{ value: "dot", name: "Pulsing dot", tells: { alive: "yes", what: "no", howLong: "no", stop: "no" } },Four questions
Anyone waiting on software wants four things answered: is it still alive, what is it doing, how long will it be, and how do I stop it. A busy signal can answer any of them, and most answer one. The marks under each signal say which: a tick where it answers, a dash where it hints, a cross where it's silent.
Being alive is the cheapest, and every signal manages it: anything that moves will do. What it's doing takes words, which is why a label that runs through Thinking, Searching and Writing says more than a dot that pulses the same way through all of them. How long is the hard one, because an agent rarely knows. The honest answer is how long it's been: the seconds and tokens a terminal agent counts up as it works, not a bar that pretends to know what's left.
The faked bar
The progress bar here is the usual fake for work of unknown length: it races to half, slows, and creeps toward 90% for as long as the work takes, then jumps to full. It feels like progress while it misreports it, and once someone has watched one stall at 90% they stop believing bars.
Words over spinners
The best combine: a small motion to show it's alive, words for what it's doing, a counter for how long, and the key that stops it. While an agent uses tools, the steps say the most, each call a line that ticks off; once there's an answer, streaming says the most, since the answer is its own signal. The cloud from this site says the least, and that's fine: it's a character, not a status bar, and the stage beside it says Thinking… in words.
Everything here plays from one clock, read ten times a second and only while it's on screen. Each signal's own motion is CSS, transform and opacity only, paused off screen; under reduced motion nothing moves, and the words still change as you pick a phase.