Provider-independent realtime voice agents

Ship the voice agent once. Change the models underneath it without touching your app

Your backend creates a session, the browser joins a room. Speech-to-text, the language model, the voice, or a full realtime engine all live in a published profile. Swap vendors there and your shipped code keeps working.

One session contract, protocol v1 · STT, LLM, TTS and realtime engines from 10 providers · SDKs for the browser, Node and Python, all optional

Pick a provider per stage. Connect your own keys.

Anthropic LLM OpenAI LLM · STT · TTS · Realtime Google LLM · STT · Gemini Live xAI Grok LLM Groq LLM Sarvam STT · LLM · TTS · Indian languages Smallest AI TTS · LLM ElevenLabs TTS Deepgram STT Cartesia TTS

How a session runs

Publish once. Create from the backend. Connect from the browser. Read everything back.

A profile is the only place vendors appear. Your application only ever sees the session contract: one POST to create, one room to join, one document to read when the call ends.

  1. 1

    Publish a profile

    Choose the STT, LLM and TTS stages, or a realtime engine. Attach tools, set turn detection and interruption rules. Publishing freezes an immutable revision.

    rev 12
  2. 2

    Issue a key

    An organisation API key with only the scopes it needs. Test keys for staging, live keys for production. It stays on your server.

    sk_live_…
  3. 3

    Backend creates the session

    One POST with the profile name, your record id and an idempotency key. You get a session id, short-lived room credentials and a browser-safe access token.

    POST /v1/sessions
  4. 4

    Browser joins the room

    The client SDK publishes the microphone, plays the agent, orders events, replays gaps and rejoins after a network drop. Browser tools run right there.

    connect()
  5. 5

    Read the session back

    Transcript, audio duration, usage per vendor, interruptions and tool calls in one bounded document, and a signed lifecycle webhook when the call ends.

    GET …/data
Change a vendor, publish revision 13. Steps 2 to 5 do not change. Sessions already running finish on revision 12.

Features

The session contract stays still. The stack underneath it moves.

Voice quality, latency and price change every quarter as providers ship new models. VoxEvolv keeps that churn inside the profile, so evaluating a new model is a publish, not a migration.

Profiles hold every vendor decision, and every published revision is immutable

A profile names the engine for each stage, the voice, the language, turn detection, interruption behaviour, and the tools the model may call. Publishing produces a numbered revision that never changes. Sessions record the revision they ran on, so a transcript from March is explained by the exact configuration that produced it.

  • Cascaded or realtime. Run Sarvam STT into Claude into ElevenLabs, or switch the whole profile to OpenAI Realtime or Gemini Live. The session contract is the same either way.
  • Your provider keys. Connect each vendor once, encrypted at rest. Profiles reference the connection, never the secret.
  • Conversation controls per profile. Voice activity detection, endpointing, barge-in, greeting, and how long silence may run before the agent speaks.
  • Test before publishing. A secure test link opens the draft in a browser. When it sounds right, publish.

Agent profile · support-agent

Draft on top of revision 12 · 1 stage changed
Barge-in onuser may interrupt
1.2 ssilence before greeting
4 tools2 always on · 2 on demand
Publish revision 13 · 3 live sessions stay on 12Publish
Nothing in your application changes. The next session created against support-agent runs on revision 13.

One session contract from your backend, one connect call from the browser

The organisation key never leaves your server. Your backend posts the profile name, your own record id, and the participant. The response carries everything the browser needs and nothing it should not have: short-lived room credentials and a scoped access token that can rejoin, replay and end only its own session.

  • Idempotent by design. One Idempotency-Key per intended call. Retry safely; a replay returns the same session.
  • SDKs are optional. @voxevolv/server, @voxevolv/client and the Python package wrap a documented HTTP and protocol v1 surface you may call directly.
  • Recovery is built in. The client distinguishes transport reconnects from a full session resume, replays missed events, and preserves mute state across a rejoin.
  • Migrating from OpenAI Realtime or Gemini Live? A machine-readable guide at /realtime-migration.txt walks a coding agent through the swap.

Create a session, then connect

Backend · then browser
# trusted backend only
curl -X POST "$VOXEVOLV_API_BASE/sessions/" \
  -H "Authorization: Bearer $VOXEVOLV_API_KEY" \
  -H "Idempotency-Key: order-4412-call-1" \
  -d '{
    "protocol_version": 1,
    "client_reference_id": "order-4412",
    "profile": "support-agent",
    "participant": { "identity": "user-4412" },
    "media": { "input": ["audio"], "output": ["audio", "text"] }
  }'

# 201 Created
{ "id": "9f2c…", "profile_revision": 12,
  "connection": { "url", "token", "room_name" },
  "access_token": "vsa_…" }
// browser
const session = await RealtimeSession.create({
  endpoint: "/api/voice-session", autoRejoin: true,
  tools: { show_order: async ({ order_id }) => fetchOrder(order_id) },
});
session.onAgentTranscript(({ text, final }) => final && log(text));
await session.connect({ microphone: true });
The browser never sees the organisation key. It gets a room credential and a vsa_… token scoped to this one session.

Tools the model can call, in the browser or on your server, discovered on demand

Register a tool once, attach it to a profile, publish. Browser tools run as RPC inside the page the user is looking at. Webhook tools call your server with a signed request. Groups of tools can stay dormant until the model searches for them, so a 40-tool agent starts with 6 in context.

  • Browser tools. session.registerTool(name, handler). The model's validated arguments arrive in the page; whatever you return goes back to the model.
  • Webhook tools. A JSON POST with session id, call id and arguments, signed with HMAC-SHA256 and deduplicated with an idempotency key.
  • Inline tools per session. Pass up to 32 client tool definitions at creation time when a profile allows it, for tools that only exist on one screen.
  • Platform tools. Attach voxevolv.end_call and the model can close the conversation itself, draining its farewell before the room closes.

Tool manifest · support-agent rev 12

Captured at session start · 2 active · 2 on demand
  1. 00:41✓show_order("4412")Browser returned the order in 80 ms · agent read out the delivery date
  2. 02:14?search_tools("refund")Activated group "payments" · persisted so a worker restart keeps it
  3. 02:31✓initiate_refund(order: "4412", amount: 1499)Webhook 200 in 410 ms · signature verified by your server
  4. 03:05✓voxevolv.end_callFarewell drained, room closed, lifecycle webhook queued
Every call is recorded with redacted arguments in the session history, so you can see what the model did and when.

See where the milliseconds went, and what each vendor billed, per session

A voice agent lives or dies on the gap between the user stopping and the agent starting. VoxEvolv records that gap for every turn and splits it by stage, so when a provider slows down you see which one. Usage is metered per vendor and per model, in the units each one bills, tokens or speech seconds.

  • Stage timeline per turn. Speech end, transcript final, first token, first audio byte, all timestamped.
  • One bounded session document. GET /v1/sessions/{id}/data returns the conversation, audio duration, usage, interruptions, tool calls and health in one response, with a paginated link for long transcripts.
  • Lifecycle webhooks. The same document is delivered to your endpoint when the session ends, signed, with an event id for deduplication.
  • Debug capture, opt in. Keep the exact model inputs and outputs, including images sent as context, for a bounded window when you are chasing a bad answer.

Session order-4412 · turn 3 of 9

support-agent rev 12 · Hindi · Sarvam → Claude → ElevenLabs
1,240Claude tokens in · 86 out
4.1 sElevenLabs audio billed
0interruptions this turn
User · Hindi · 00:00 → 00:03"मेरा ऑर्डर कब आएगा? 4412 वाला।"
Agent · 00:03.61"आपका ऑर्डर 4412 कल शाम 6 बजे तक पहुँच जाएगा। स्क्रीन पर ट्रैकिंग दिखा रहा हूँ।"
session.ended · X-VoxEvolv-Signature v1=…Delivered to https://api.yourapp.com/voxevolv in 220 ms · 9 messages · 3 tool calls · usage attached
Switch the LLM stage and compare the same turn on revision 13. Same transcript shape, different middle bar.

Who uses it

Teams that want voice in the product without marrying a model vendor

Product teams adding voice

Support, ordering, onboarding, in-app assistants

Ship the voice feature against the session contract and keep shipping. When a faster or cheaper model appears, the change is a profile revision that the product team never has to schedule.

Training and assessment platforms

Role plays, interviews, coaching, certification

Run thousands of concurrent spoken conversations in Indian languages and English, with interruption handling that survives a noisy shop floor, and read every transcript back for scoring.

Contact centre and CX builders

Inbound, outbound, verification, collections

Choose Sarvam for Hindi and Kannada speech, a frontier model for reasoning and a low-latency voice for the reply, and keep per-vendor usage separated for the finance team.

Coding agents and integrators

Build from llms.txt and the live OpenAPI document

Machine-readable instructions at /llms.txt, a migration guide from OpenAI Realtime and Gemini Live, and a live Swagger reference mean an agent can build a working integration from an API key and a profile name.

Trust

Secrets stay on the server. Credentials are short-lived and scoped.

Organisation API keys carry only the scopes you grant. Provider keys are encrypted at rest and never leave the worker. The browser gets a single-room credential and a token that can act on one session. Published revisions are immutable, and nothing is deleted, only disabled, so the record stays whole.

Scoped keys: sessions:create, read, end Test and live keys, separately Provider secrets encrypted at rest Short-lived room tokens HMAC-SHA256 signed webhooks Roles per organisation Immutable profile revisions Disabled, never deleted

Bring one system prompt and one provider key

Create an account, connect a provider you already pay for, publish a profile and talk to it from a test link. Then change the model and publish again. The whole loop is self-serve and takes less time than reading a vendor's migration guide.

Self-serveaccount, providers, profile, key
Your keysyou pay vendors directly
Protocol v1a contract, not a proxy

Your first half hour

  • 1Create an account and organisation/signup
  • 2Connect a providerAnthropic, OpenAI, Google, Sarvam, ElevenLabs or another
  • 3Publish an agent profilepick the stages, set the voice, attach a tool
  • 4Talk to it from a test linkthen swap the LLM stage and publish revision 2
  • 5Create a key and call the APIPOST /v1/sessions/ from your backend