Skip to main content

Overview

By the end of this guide you’ll have a voice agent you can talk to right in your browser. You create it with one command, then drop it into a small web page. Browsers handle echo cancellation, so you don’t need headphones, and there’s nothing to install. Prefer to try it first? Talk to an agent without writing any code in the Voice Agent playground.
Voice agents are billed per session. Always end with session.end.Billing runs for as long as the WebSocket stays open. If the client just calls ws.close(), the server keeps the session alive for a 30-second session.resume grace window, and that window is billable. See Step 5: End the session cleanly below.New accounts get $50 in free credits. See Billing and pricing.

Before you begin

You’ll need:
  • An API key. Grab one from your dashboard. The curl below reads it from an environment variable:
  • A modern browser (Chrome or Edge recommended). That’s the whole client: echo cancellation for free, nothing else to install.

Build your agent

Create an agent, then talk to it in a tiny web page. Four steps, no dependencies.
Prefer to build with an AI coding tool? Claude Code, Cursor, Windsurf, and prompt-based builders like Lovable and v0 can write this for you against AssemblyAI’s live docs. See Build with AI coding tools.

Step 1: Create an agent

Copy the id from the response. This is your agent ID:

Step 2: Save the web page

Save this as voice-agent.html. It’s the whole client: it captures the mic, streams it to your agent, plays the reply, and barges in when you start talking:
For simplicity this passes your API key straight to the browser. Never do that in production. Mint a temporary token on your server instead.

Step 3: Open it and talk

Browsers need a secure context for the microphone, so serve the file locally:
Open http://localhost:3000/voice-agent.html, paste your API key and the agent ID from step 1, and click Connect, then start talking. The agent greets you, listens, and replies.

Step 4: Add a tool (optional)

Give the agent the ability to do something. Here it books a meeting with the real Cal.com bookings API. Update the agent with an HTTP tool: you provide the endpoint and a JSON-Schema parameter spec, and AssemblyAI calls it for you whenever the model decides to. Nothing changes in your web page. Replace <YOUR_CAL_API_KEY> with a Cal.com API key and 123 with your event type ID:
Reload the page, connect again, and ask to book a meeting. The agent collects the details and POSTs them to Cal.com; your page never handles the request. The model’s arguments become the JSON body, and the header values are encrypted at rest (reads return only the header name, never the value). See Add tools for the full tool model.

Step 5: End the session cleanly

The Stop button in step 2 calls ws.close() directly. That leaves the session in a 30-second session.resume grace window on the server, and that window is billable. Send session.end first, wait for session.ended, then close. Update stop() in voice-agent.html:
Then handle session.ended inside your existing ws.onmessage:
Also cover tab close and navigation. pagehide fires on both and is more reliable than beforeunload on mobile Safari:
Send session.end synchronously inside the pagehide handler. Anything async (like await fetch) will not finish before the socket is torn down.
Server and native clients follow the same pattern: send session.end on your shutdown signal (SIGINT, SIGTERM, or your own hangup handler), wait briefly for session.ended, then close the socket. There’s a complete example in the Deploy your agent quickstart. See Unexpected billing after the call ended if your sessions look about 30 seconds longer than the call itself.

Next steps

You just did all three phases at once. Here’s where to go deeper on each:

1. Create

Create a reusable agent with one REST call, then update, list, and delete it.

2. Configure

Shape how it sounds and behaves: prompt, voice, greeting, audio, turn detection, keyterms, tools.

3. Deploy

Connect by agent_id over the API, from a browser, or to a phone number with Twilio.
Or jump straight to a topic: