Live demo · Voice + chat · Open source

Nimbus Desk. A voice agent you can call right now.

Dispute a roaming charge with it and watch it verify identity, read the bill, apply a bounded credit, and hand anything off-script to a human, all through visible function calls.

Deployment readoutLIVE DEMO
Dispute resolved end to end
~90 sec
Channels from one agent definition
3
Assertions gating every deploy
26
Production failures frozen as tests
3

The problem

The interesting engineering is not the voice.

Telecom billing disputes are high-volume, low-complexity, and emotionally charged: a customer sees a roaming charge they do not understand and calls support. Most of these calls need three things a machine does well when it is wired to real systems: verify who is calling, read the actual bill, and apply a bounded remedy. What makes it hard is the integration surface and the failure handling.

The same TypeScript agent definition runs three surfaces: the voice line, a text-chat channel, and an eval harness that plays adversarial callers against it. A fix lands once and every surface inherits it. Voice, chat, and evals never fork.

The golden path

What moves when a call runs.

  1. 01
    Verify
    Caller proves identity: exact account digits, fuzzy spoken name
  2. 02
    Read
    The agent pulls the real invoice and finds the disputed line
  3. 03
    Explain
    The charge, in plain language, from billing-system detail
  4. 04
    Remedy
    A goodwill credit inside a hard 20 EUR authority limit
  5. 05
    Summarize
    A written summary to the email on file
  6. 06
    Escalate
    Anything off-script goes to a human with a structured case summary

Every function call renders live in the UI while the caller talks, so the integration work is visible, not claimed.

Design decisions

What was built, and why it is built that way.

Mechanisms are cheap; reasons are the engineering. Each choice below is verifiable in the source.

01

Policy lives in code. The prompt is UX.

The 20 EUR credit cap and the rule that escalation ends account actions are enforced in the billing service, not requested in the prompt. Models follow instructions probabilistically; an intermittent eval failure proved it when the agent applied a credit after handing the case to a human, sometimes. A prompt line is a suggestion. A service-layer check is a guarantee.

02

One agent definition, three surfaces.

Voice, chat, and the eval harness execute the same agent instructions, the same seven typed tools, and the same billing service. Behavior must not fork between channels: when a live call exposed a bug, the fix shipped once and voice, chat, and evals all inherited it the same hour.

03

Two models, chosen per task.

The voice loop runs a realtime speech-to-speech model with semantic voice-activity detection, because conversation latency is the product. Chat and evals run a small, fast text model, because they do not need audio and cost matters. The guardrails are model-independent, they live in code, so the cheap text model is a faithful proxy of the voice agent minus the audio path.

04

The real API key never reaches the browser.

The server mints 60-second ephemeral client secrets, with the model, voice, instructions, and tools baked in server-side. A public voice demo is an open faucet to an API key; an ephemeral secret keeps the blast radius to one minute and the configuration out of the caller's hands.

05

Cost guardrails that fail closed, with honest copy.

Calls hard-cap at 3 minutes with a visible countdown. Per-IP and global daily caps plus a reconnect cooldown protect a public demo's token budget. When a cap is hit, the page says the demo is asleep instead of erroring mysteriously, and every failure state offers the chat channel as the fallback, which costs roughly a hundredth of a voice call.

06

Transcripts stay in the caller's browser.

The server logs operational metadata only: outcome, duration, turn counts, tool names and latencies. That is exactly what the ops dashboard needs for containment rate and handling time, and nothing else. Voice content is not stored because the metrics do not require it.

07

Never exact-match speech.

The first live call failed because the speech model heard Fisher when the caller said Fischer, and exact-match verification refused a legitimate customer twice. The fix went into the integration layer, not the prompt: exact match on the account digits, which are the credential, and edit-distance tolerance on the spoken name, scaled to name length. Strict on what the caller proves, tolerant on what the transcriber guesses.

08

Every production failure becomes a test.

The eval harness plays LLM-simulated personas with hidden goals against the agent, then checks invariants by reading the tool-call log: identity gates account data, credit never exceeds authority, escalation fires with the right reason and is terminal. Real bugs from live calls are frozen as regression cases, like the post-escalation credit and the agent re-asking for identity a caller had already volunteered. A capture script turns any failing conversation into a new case. That loop is what separates a deployment from a demo.

Measured, not claimed

What the dashboard shows.

The result is visible on the ops dashboard: containment rate, average handling time, tool success rate, and sessions per day, with voice and chat side by side. Every deploy is gated by the eval suite, which exits nonzero the moment a policy invariant breaks. The whole system is open source under MIT, so the claims can be read, not just believed.