affectUI › Components › Agents
Agent Queue
The work waiting for your agents, and how fast it moves – jobs drop into a live queue, glide into free worker slots as growing bars and land in Done or Failed, while a depth chart shows the backlog build up when a rate limit pauses the workers and drain when they resume.
Part of affectUI Pro. Install: npx shadcn@latest add https://www.affectui.com/r/agent-queue.json · Import from @/components/ui/agent-queue
When to use
- A job queue in an agent product – how many tasks wait, which worker runs what, and how fast the backlog moves
- Watching backpressure live: a provider rate-limits, the workers pause, the queue builds up and drains again
- An ops view next to your agents where people can pause the queue, add or remove workers, or move a job to the front
When not to use
- Several agents side by side over time – use Agent Lanes
- Handing work to a specific agent by hand – use Delegate Board
- A list of background tasks with their results – use Agent Inbox
- Where the time and money of one run go – use Trace Waterfall
Usage
import { AgentQueue, type QueueJob, type QueueWorker } from "@/components/ui/agent-queue";
const workers: QueueWorker[] = [
{ id: "w1", name: "Sonnet 5.5" },
{ id: "w2", name: "GPT-6 Sol" },
];
const jobs: QueueJob[] = [
{ id: "j1", name: "Summarize ticket #4821", kind: "llm", status: "running", worker: "w1",
enqueuedAt: t0, startedAt: t0 + 1200, progress: 0.4 },
{ id: "j2", name: "Embed 240 docs", kind: "tool", status: "queued", enqueuedAt: t0 + 800 },
{ id: "j3", name: "Draft reply – Acme", kind: "llm", status: "queued", priority: "high", enqueuedAt: t0 + 2100 },
];
export function Jobs() {
// Times are on one clock (epoch ms here) – without now, the component ticks Date.now while there is work
return <AgentQueue jobs={jobs} workers={workers} backpressure={20} />;
}Props
| Name | Type | Default | Description |
|---|---|---|---|
jobs | QueueJob[] | { id, name, kind, status, enqueuedAt, priority?, startedAt?, endedAt?, worker?, progress?, estimate?, attempt?, maxAttempts?, detail?, icon?, error? } – waiting, running and recently finished jobs | |
kind | "llm" | "tool" | "agent" | "human" | Per job – picks its tint: LLM calls violet, tool calls teal, sub-agents slate, human review blue | |
status | "queued" | "running" | "done" | "failed" | Per job – a job that goes from running back to queued with a higher attempt shows as a retry | |
priority | "high" | "normal" | "low" | "normal" | Per job – a high one glides past the others to the front |
progress / estimate | number | Per job – 0–1 while it runs, or the expected run time in ms to estimate it | |
workers | QueueWorker[] | { id, name, detail?, icon? } – the slots; their number is the concurrency | |
now | number | The clock, on the same scale as the job times – without it, the component keeps its own (Date.now) | |
rateLimits | { from, until, label? }[] | Stretches when the provider rate-limits – while one is active the running jobs pause in amber with a countdown | |
paused / onPausedChange | boolean / (paused) => void | The queue is paused; the handler shows a Pause/Resume button | |
onConcurrencyChange | (workers: number) => void | Shows a – N + stepper for the number of workers | |
minConcurrency / maxConcurrency | number | 1 / 8 | The stepper's range |
backpressure | number | A depth that means trouble – a dashed line on the chart; above it Waiting turns amber | |
window | number | 120000 | How far back the depth chart looks, in ms |
totals | { done?, failed? } | Counts since the start, when jobs only holds the recent ones | |
openId / defaultOpenId | string | null | null | The job whose card is pinned, controlled or uncontrolled |
onOpenChange | (id: string | null, job?: QueueJob) => void | A job's card was pinned or closed | |
onPromote / onCancel | (job: QueueJob) => void | Show "Move to front" and "Cancel" in a pinned card | |
title / name | string | "Queue" | Heading, and the queue's name muted next to it |
className | string | Extra class on the root |
Keyboard
- Tab: Moves into the jobs (one job is in the tab order), then to the card's buttons
- ArrowUp / ArrowDown / ArrowLeft / ArrowRight: Walks through the running jobs, slot by slot, then the queue from the front; Home and End jump to the ends
- Enter / Space: Pins or closes the focused job's card
- Esc: Closes the card
Accessibility
- Every job is a real button, labelled with its name, kind, how long it waited or ran, its place in line, priority and attempt
- Roving focus – only one job is in the tab order, so the flow is a single stop
- The pinned card is a dialog with a close button; Esc closes it and returns focus to the job
- Rate limits, their end, failures, retries and crossing the backpressure line are announced in a polite live region
- The chart is an image with a text summary: how many wait now, the peak, the average and the rate-limited stretches
- Pause is a toggle button with aria-pressed; the stepper's buttons say what they do and the count is announced
Responsive
- Built on a container query and the measured width: wide, the flow runs left to right – queue, workers, Done and Failed
- Under 600px the flow stacks: queue on top, the workers below (just their marks, the rail gets the room), Done and Failed side by side
- The four numbers wrap to two columns; under 440px Pause and the stepper get a row of their own
- Dark mode built in: switches when an ancestor (usually <html>) has the class dark or data-theme="dark"
Requirements
- React 19
Related
- Agent Lanes – Where every agent is right now – a live timeline with a lane per agent, tasks growing into “now”, hand-offs drawn between agents and approvals right on the block
- Delegate Board – Hand work to your agents by dragging it onto them – each agent previews its new “busy until” time, or switch to Auto and every new task goes to whoever is free first
- Agent Inbox – All your background agent tasks in one calm list – live clocks and status tags, filter tabs with rolling counts, rows that unfold to the last steps with Approve, Reject, Retry or Open, and glide to their new place
- Trace Waterfall – Where the time and money of an agent run go – every LLM call, tool call and sub-agent as a bar on a live timeline, with tokens and cost per step, the slowest call marked and branches that fold into their parent