Skip to main content
When your tool returns, the model narrates the data. A glance card is the visual half of that answer: native blocks — headers, lists, stats, charts — rendered by VoiceOS’s own components. It’s the same block language the VoiceOS agent itself answers with, so your card is automatically on-brand, dark-glass themed, and restyle-proof.
The notch showing 'What voices do I have?' and an ElevenLabs Voices card listing Rachel with a green Default badge, Adam, Bella, and Antoni.

Design target: a two-second read. Not a dashboard — the one thing the user wants to see.

Attaching a card

Spread glanceResult([...]) into your tool’s JSON result:
That adds a _voiceos_glance: { blocks } key to your payload. VoiceOS lifts it out before the model sees the result — the model reads your data, never your UI JSON.
Never put information only in the card. The model narrates from the JSON data. A card-only fact is a fact the agent can’t say out loud.

Background completion

Background tools return the same card format. Await the work in your handler, then include glanceResult in the final result:
For custom widgets, replace glanceResult(...) with widgetResult(html, { height: 240, data: exported }). Background completion also accepts the card in MCP structuredContent. VoiceOS chimes on completion and queues the card until the top notch is idle. Clicking the completed task in the side notch restores the same card, including widget HTML and data. Attach the card through _voiceos_glance; Markdown UI fences do not support custom widgets. Keep your summary data alongside the card for fallback.

The budget

Your folder’s bun verify.ts catches shape mistakes before users do.

The vocabulary

Every prop, cap, and edge case: glance block reference.

Four patterns that work

The lookup — header + list

The bread and butter.
A Hacker News card in the notch: globe icon, 'Front page' trailing label, and three story rows with authors, comment counts, and point scores.

Rows carry a subtitle and a trailing value — enough to scan, never enough to read.

The metric card — header + stats + one chart

A Coffee Tracker card with two stat tiles — 12 this week, 87 all time — and a labeled bar chart Monday through Sunday.

The full three-block budget: identity, the numbers, the shape of the numbers.

The status glance — a row

Puts a ring beside its caption.
A compact notch card with a green progress ring containing a car icon beside the stat '51% · 189 mi' labeled 911 Carrera.

One block, two things side by side — the smallest card worth showing.

The composition — splitBar

What something is made of.
A Sleep card with a bed icon, '7 h 58 min' trailing label, and a segmented bar splitting the night into Deep, Core, REM, and Awake with a color-dot legend.

Segment colors are assigned by index, never by you — so composition can't read as good or bad.

Tones, glyphs, and app icons

  • tone is a meaning, not a color. good, bad, or neutral — the renderer owns the hues. You never pick colors; that’s how every card stays on-brand.
  • Glyphs come from a fixed allowlist of 34 names (calendar, clock, mail, globe, coffee, sparkle, …) — see the full list. Unknown names invalidate the block.
  • appIcon renders a real app logo (e.g. "notion") in headers and list rows, and wins over icon. It only renders when the row’s visible title starts with that app’s name — so one brand can never masquerade as another.
  • Numbers are strings you format. stats.value caps at 20 chars — send "5 hr 56 min", not 21360. Deltas color by sign: leading - is red, + is green.

How cards behave

  • Blocks animate in with the notch’s staggered blur-in; charts rise and wipe. All motion respects prefers-reduced-motion.
  • clock and countdown tick once per second. Prefer until (an ISO timestamp) over seconds — an absolute target survives re-renders.
  • Cards render in the notch’s answer column and scroll internally if the viewport is tight. On small screens, less is more.
  • One failing block never sinks the card — every block renders inside its own error boundary.

Next: Confirmation cards

Tools that act need approval first — declare the card the user approves on.