Agent orb
AIProThe presence of a voice agent: AI color turning inside a sphere, faster while it listens, thinks and talks, and swelling with the loudness of the voice.
npx prodular-ui add agent-orbPart of Prodular UI Pro. Preview and read the docs freely, install with a license. See pricing
Voice agent
Switch the state. The orb turns faster as the agent gets busier and follows the loudness while it listens or talks. The loudness is simulated here.
Listening
"use client"
import * as React from "react"
import { AgentOrb, type AgentOrbState } from "@/components/ui/agent-orb"import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"
const caption: Record<AgentOrbState, string> = { idle: "Ask about any invoice, customer or payment run.", listening: "Listening", thinking: "Checking the October payment run", talking: "Three invoices are still open for Tidewater Freight, $14,200.00 in total.",}
export default function AgentOrbVoice() { const [state, setState] = React.useState<AgentOrbState>("listening") const [level, setLevel] = React.useState(0)
// Simulated loudness. In a product, read it from the microphone or the speech output. React.useEffect(() => { if (state !== "listening" && state !== "talking") { setLevel(0) return } let frame = requestAnimationFrame(function tick(now) { setLevel(Math.abs(Math.sin(now / 180) * Math.cos(now / 410))) frame = requestAnimationFrame(tick) }) return () => cancelAnimationFrame(frame) }, [state])
return ( <div className="flex w-full max-w-md flex-col items-center gap-6 text-center"> <AgentOrb size="xl" state={state} level={level} /> <p aria-live="polite" className={state === "listening" || state === "thinking" ? "m-0 min-h-12 text-sm text-muted-foreground shimmer motion-reduce:shimmer-none" : "m-0 min-h-12 text-sm text-foreground"} > {caption[state]} </p> <ToggleGroup variant="outline" size="sm" spacing={0} value={[state]} onValueChange={(v) => v.length && setState(v[0] as AgentOrbState)} aria-label="Agent state" > <ToggleGroupItem value="idle">Idle</ToggleGroupItem> <ToggleGroupItem value="listening">Listening</ToggleGroupItem> <ToggleGroupItem value="thinking">Thinking</ToggleGroupItem> <ToggleGroupItem value="talking">Talking</ToggleGroupItem> </ToggleGroup> </div> )}Sizes
sm 24px for a status pill, default 40px, lg 64px and xl 96px for a voice screen.
import { AgentOrb } from "@/components/ui/agent-orb"
export default function AgentOrbSizes() { return ( <div className="flex flex-wrap items-end justify-center gap-10"> {(["sm", "default", "lg", "xl"] as const).map((size) => ( <div key={size} className="flex flex-col items-center gap-3"> <AgentOrb size={size} /> <span className="text-[13px] text-muted-foreground">{size}</span> </div> ))} <div className="flex items-center gap-2.5 self-center rounded-full border bg-card py-1.5 ps-1.5 pe-4 shadow-xs"> <AgentOrb size="sm" state="talking" /> <span className="text-sm font-medium">Relay is talking</span> </div> </div> )}Anatomy
<AgentOrb state={state} level={level} size="xl" />Guidance
Use it when
- Use it as the face of a voice agent: on a call screen, a voice mode, or a pill that says the agent is talking.
- Show one orb per agent, in the place people look while they talk to it.
- Pair it with words: a caption of what it heard or is saying, and a way to stop it.
Avoid
- Text chat. A streaming Response and the AI mark already show that a model is writing.
- Using it as a spinner for work that is not a voice conversation.
- Several orbs on one screen. It stops meaning that someone is listening.
Rules for AI agents
Published in llms-full.txt, the registry and the MCP server, so coding agents follow them when they build with this component.
- Pass state on every change: listening while the microphone is open, thinking between the end of speech and the first audio out, talking while audio plays, idle otherwise.
- Drive level from real audio: RMS of the microphone while listening, of the speech output while talking, from 0 to 1, about 15 times a second. Leave it at 0 in idle and thinking.
- The orb announces its state through its label. Also show a text caption, and keep a visible stop or mute control next to it.
- Use size sm inside pills and headers, xl on a full voice screen. Do not change its colors; it uses the AI tokens.
API
AgentOrb
| Prop | Type | Default | Description |
|---|---|---|---|
| state | "idle" | "listening" | "thinking" | "talking" | "idle" | Sets the speed and the spoken label. Exposed as data-state. |
| level | number | 0 | Loudness from 0 to 1. Grows the orb by up to 8%. |
| size | "sm" | "default" | "lg" | "xl" | "default" | 24, 40, 64 or 96px. |
| label | string | Accessible label. Defaults to the state, for example "Assistant is listening". |
Installation
The Prodular UI CLI adds the source to components/ui with everything it depends on. In a project that already uses shadcn/ui, the shadcn CLI installs it from the Prodular registry too. See Installation for the first setup.
npx prodular-ui add agent-orb# or, with the registry in components.jsonnpx shadcn@latest add @prodular/agent-orb