AriaStory
Powered byAgora

She doesn't wait for you to finish.

A real-time voice sales agent, built on Agora's Conversational AI Engine. Interrupt her mid-sentence and she stops instantly — that's Agora's own barge-in detection, native to the call, not something scripted after the fact.

Talk to AriaSee how she thinks

The problem

Scripts break the moment a real customer shows up.

A scripted voice bot holds together right up until someone interrupts mid-sentence, changes a number they already gave, or asks something out of order — then it restarts the flow, or hands off blind. A real salesperson doesn't do that. They listen, adapt, and keep the thread. That's the gap Aria is built for.

Powered by

Agora

Agora is the phone system. This backend is the person.

Every hard problem in real-time voice — hearing the customer, catching the exact instant they start talking over Aria, turning her reply into speech that sounds spoken rather than read — is Agora's Conversational AI Engine, not code this team wrote. Under credential_mode: managed, Agora holds the real Deepgram and MiniMax connections and injects its own vendor keys server-side, so this team never opened a separate speech-to-text or text-to-speech account at all — it's bundled straight into what they already pay Agora.

Streaming ASR — DeepgramStreaming TTS — MiniMaxNative barge-inTurn-taking & VADManaged vendor credentialsRuntime voice switching

And Agora calls us — not the other way around. Once per turn, at a URL minted per session, shaped exactly like an OpenAI chat completion. Agora never sees the sales conversation happening inside it; it just carries the call.

Built with

Real vendors, wired in — not simulated.

Everything below is actually running, not a slide of logos.

Gemini Deepgram MiniMaxEspoCRM Next.js FastAPI Docker Oracle Cloud Caddy Expo

Provider-agnostic where it counts: the reasoning loop runs on Gemini today, with Groq and Anthropic wired in as real, benchmarked, swappable alternates — see the brain.

The brain

Ten tools, one decision at a time.

What Agora hands us each turn is a transcript. What we do with it is the actual product.

Not a decision tree

Every turn, a tool-calling loop decides — live — whether to search the product knowledge base, update the lead, check the calendar, log an objection, or hand off to a human: search_pricing_rag, crm_upsert_lead, calendar_book_meeting, negotiate_deal, escalate_to_human, and five more.

Three layers of negotiation

A discount request is the most ordinary thing on a sales call, and the most dangerous thing to hand an LLM outright. Aria can concede 3% herself, instantly. Past that, a separate deal-desk agent can go to 10% — only against a real commitment. Past that, a human is asked, without ending the call.

The clamp is code, not a prompt

An 18% walk-away floor is enforced in engine.authorise, deterministically. Feed the desk a 40% recommendation and what comes back out is a capped offer, aclamped flag, and a reason — every round written to the CRM as an audit line.

Grounded, not guessed

Every price, spec, and comparison Aria states comes from a live knowledge-base search — she says she's not sure rather than invent a number. A technical question goes to a second specialist agent that is required to state exactly what it doesn't know, not just what it does.

Benchmarked, not vendor-locked

The model behind the tool-calling loop is provider-agnostic on purpose — Groq, Anthropic, and Gemini all plug into the same interface. Which one serves a turn is picked by running real candidates against the real system prompt and the real tool schemas, and checking whether a fast model still made the right tool call, not just how fast it replied.

Architecture

Three layers. Agora owns the first two.

Not a diagram of ambition — this is the actual request path a single turn takes, start to finish.

1. Caller ↔ Agora

🎙️ Caller's mic & speaker⇄ RTC audio + RTM signaling
↓

2. Agora ↔ backend

Conversational AI Engine→POST /api/llm/… — one call per turn
↓

3. Backend fan-out

Tool-calling loop⇉EspoCRMCalendarRAG catalogDeal deskSlack handoffmem0 (off)

Every hard real-time problem — hearing the caller, catching barge-in, speaking back — stays inside rows 1 and 2, on Agora's infrastructure. Row 3 is the only part this team wrote: one tool-calling loop instead of a rigid flow chart, so a call can take any order a real conversation takes. Why that loop and not a script, and why the negotiation clamp underneath it is code rather than a prompt — see the brain.

Multilingual & memory

One call, and she never stops noticing.

Hindi, English, or both mid-sentence

One setting and Aria takes the call in Hinglish — Deepgram's multi ASR mode and MiniMax's language_boost: auto follow a buyer who switches languages mid-thought. Hindi renders in Devanagari, never romanised — “ek second” spelled in Latin letters gets read out as English words.

A different voice, because a different agent answered

When the deal desk or the solutions engineer genuinely takes a question, the customer hears a different voice — because a different agent actually did answer. Both run on Agora's own runtime update endpoint, dispatched in the background so it never blocks a reply.

Memory without a memory service

Change a number twenty turns into the call and she doesn't ask again — the qualification record a tool wrote earlier is re-rendered into her system prompt every turn, at zero network cost. That's what carries every call today. A longer-range layer, built on mem0 with Voyage AI embeddings, is coded and tested for recalling detail beyond that window — currently switched off pending a provider-SDK compatibility fix.

Not a mock

The CRM updates while she's still talking.

  • A customer corrects 25 devices to 50 mid-call, and it's the same Lead record with one field overwritten — not a second lead, not a restart.
  • Booking a meeting writes a real Meeting in EspoCRM and sends a real .ics calendar invite over SMTP — accept it and it lands in the customer's actual calendar.
  • A handoff posts a real Slack message with an AI-written brief — issue, blocker, sentiment, recommended action — not a row in a table nobody opens.
  • A rep can take an escalation on a real mobile app — a linked EAS project, not a placeholder — and join the live call from their phone.

Proven, not claimed

256 concurrent calls. Zero failed turns.

Concurrent calls
256
Turns handled
1,536 in 1.91s
p95 latency
0.30s
Failed turns
0

At 512 concurrent calls: 3,072 turns in 6.34s (485/s), p95 1.04s, still 0 failed. These numbers come from scripts/capacity_test.py running the real six-beat call script — CRM writes, deal-desk consult, RAG search, calendar lookup — through the real turn loop. Only the model itself is stubbed. It found a genuine concurrency bug on its first serious run, before that bug ever reached a live call.

Beyond the call

The work doesn't end when she hangs up.

A call is one turn loop. Everything below is what happens around it — before, during, and after — built this same sprint.

A dashboard for every call, not just this one

/dashboard lists every lead and session the backend has ever seen, live capacity stats, open escalations, and the product catalog — polling the same backend every five seconds. Open two tabs, start two calls, and both show up here together — proof concurrency is real, not a claim.

Buys for one person or a fleet

Aria reads the phrasing — “my team” versus “I need a new phone” — and skips the company, role, and headcount questions entirely for a solo buyer. Financing, AppleCare+, and trade-in work exactly the same either way.

A catalog a rep can extend live

POST /api/products writes new stock and appends it to the RAG corpus, then calls retriever.reset_index(). A product added mid-shift is answerable by Aria on the very next question asked — no restart, no redeploy.

Reschedule and cancel, not just book

calendar_reschedule_meeting and calendar_cancel_meeting sit alongside booking. A reschedule is cancel-then-rebook in one step, so two callers can never collide on the same slot.

When it isn't ready to be a meeting yet

schedule_followup writes a real Task into EspoCRM — not a line in a transcript — so a rep has something to work later, even when the call ends short of a booking.

Type it in, she never asks again

The console's lead card can edit a field by hand through PATCH /api/session/{id}/lead — the same crm_upsert_lead path the voice tools use. A typed correction is indistinguishable from a spoken one.

She does the currency math

₹, rupees, lakh, crore — Aria recognises all of them, converts at an approximate stated rate, and keeps negotiating in USD, since the deal engine and the catalog only ever speak one currency.

A face, not just a voice

An optional 3D avatar, built in plain Three.js rather than react-three-fiber — a deliberate call for React/Next version compatibility — lip-syncing off the live remote audio track via morph targets. Toggled per call; the 2D orb stays the proven default.

Engineering, not a demo script

Real bugs only a live call could find.

  • A CORS/error-handling bug that turned every backend failure into an opaque browser error — invisible until a real call actually hit it.
  • A missing RTM auth token that broke the live event panel in total silence while the voice call itself kept working — caught from Agora's own error code, not a stack trace.
  • Agora occasionally sends a turn with an empty transcript slot, which the model API flatly rejects — a shape no scripted test conversation would ever produce.

292 automated tests, zero network calls, about five seconds — enough to change code with confidence between two live calls, not instead of them.

Questions

Answered straight, same as she would.

Is any of this actually live, or is it a demo build?

Live. The console, the dashboard, and this page all run against the same real backend on a real Oracle Cloud VPS — no mock mode, no scripted call. The  “we found this by running it” section above is the honest evidence: bugs a scripted demo would never have surfaced.

What happens when Aria doesn't know something?

She says so. Every price or spec comes from a live knowledge-base search — no answer, no guess. Technical questions beyond that go to a specialist agent required to state what it doesn't know, and anything past pricing authority goes to a human without ending the call. See the brain.

Can I use my existing IT/MDM tooling, or does this need new software?

No new tooling required. Apple Business Manager integrates with Jamf, Kandji, and Microsoft Intune, so IT keeps whatever device-management stack it already runs.

What if I'm buying one device for myself, not a fleet?

Aria reads that from how you talk about it and skips the company/headcount questions entirely. Financing, AppleCare+, and trade-in credit all work the same for one device as for fifty.

Is there a security or compliance review before we'd sign anything?

Yes — that's a human step by design. Aria can walk through the standard documentation on the call, but a formal security/compliance review is routed to a specialist rather than closed out by an AI.

How is a live call different from a chatbot with a voice bolted on?

No script tree. Every turn re-decides, live, whether to search pricing, update the lead, check the calendar, or negotiate — and Agora's own barge-in detection means interrupting her mid-sentence actually stops her, not queues you.

Start a call. See what she does with it.

Try the live console

Live on a real Oracle Cloud VPS behind Caddy and real Let's Encrypt TLS — not a laptop and a tunnel.