Skip to content

Add a Voice Agent to Your Website in 5 Minutes

April 21, 2026 · Tutorial · 8 min read


What if every visitor to your website could ask a question — out loud — and get an instant, accurate answer from an AI that actually knows your product?

Not a canned chatbot. Not a "sorry, I don't understand" dead end. A real voice conversation, powered by your own documentation, that handles questions like:

  • "How does pricing work?" — Answers from your pricing page, in natural speech
  • "Can I integrate with Salesforce?" — Pulls from your integration docs
  • "Walk me through the setup process" — Explains your getting-started guide step by step
  • "What's the difference between the Starter and Pro plans?" — Compares features conversationally

The best part: it's a single <script> tag. No React components to install, no WebSocket code to write, no audio pipelines to configure. Just HTML.

In this tutorial, you'll go from zero to a working voice agent on your website in about 5 minutes.

What You'll Build

By the end of this tutorial, your website will have a small microphone button in the bottom-right corner. When visitors click it, they'll be in a real-time voice conversation with an AI agent that knows your product inside and out.

Under the hood, this uses:

  • Amazon Nova Sonic — A real-time bidirectional voice model (not text-to-speech bolted onto a chatbot)
  • Strands Agents — AWS's open-source agent framework for tool use and multi-turn conversations
  • Universal API — Handles hosting, billing, authentication, and the embed widget

You don't need to know any of that. You need to know three things: upload docs, create agent, paste snippet.

What You'll Need

  • A Universal API account (free tier works — you get 100 credits)
  • Your product documentation (PDF, Markdown, or text files)
  • A website where you can add a <script> tag (any static site, WordPress, Squarespace, Webflow, etc.)

Total cost: ~5 credits per minute of voice conversation (~$0.005/min). A 100-credit free tier gives you about 20 minutes of voice conversations to test with.

Step 1: Upload Your Documentation (2 minutes)

Your voice agent needs to know about your product. The fastest way is to upload your docs to Universal API's Knowledge storage.

Option A: Via the Dashboard

  1. Sign in at universalapi.co
  2. Go to Knowledge in the sidebar
  3. Click Upload and drop in your files (PDF, Markdown, plain text)
  4. Files are automatically chunked, embedded, and indexed for semantic search

Option B: Via the API

If you prefer the command line:

bash
# Upload a file directly
curl -X POST https://api.universalapi.co/knowledge/upload \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "fileName": "product-docs.md",
    "content": "# Your Product\n\nYour documentation content here...",
    "contentType": "text/markdown"
  }'

Or upload from your local filesystem:

bash
# Get a presigned upload URL
curl -X POST https://api.universalapi.co/knowledge/upload-url \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"fileName": "guide.pdf", "contentType": "application/pdf"}'

# Upload the file to the presigned URL
curl -X PUT -H "Content-Type: application/pdf" \
  --data-binary @guide.pdf "PRESIGNED_URL_FROM_ABOVE"

TIP

Upload everything that could answer a visitor's question: your FAQ, pricing page, feature list, getting-started guide, API reference, changelog. The more context the agent has, the better it answers.

Step 2: Create a Voice Agent (2 minutes)

Now create a voice agent that uses your uploaded knowledge.

Via the Dashboard

  1. Go to Agents in the sidebar
  2. Click Create Agent
  3. Set the Agent Type to Voice (Bidi)
  4. Give it a name like my-product-assistant
  5. Paste this source code:
python
from strands.experimental.bidi.agent import BidiAgent
from strands.experimental.bidi.models.nova_sonic import BidiNovaSonicModel

def create_bidi_agent():
    model = BidiNovaSonicModel(
        region="us-east-1",
        model_id="amazon.nova-sonic-v1:0",
        provider_config={
            "audio": {
                "input_sample_rate": 16000,
                "output_sample_rate": 24000,
                "voice": "tiffany"
            }
        }
    )

    system_prompt = """You are a friendly, knowledgeable assistant for [Your Product Name].

You help website visitors understand the product, answer questions about features
and pricing, and guide them through getting started.

Key guidelines:
- Be conversational and warm — you're talking, not writing
- Keep answers concise (2-3 sentences for simple questions)
- If you don't know something, say so honestly
- Suggest they contact support for account-specific issues
- When relevant, mention the free trial or getting-started guide
"""

    return BidiAgent(model=model, system_prompt=system_prompt)
  1. Set visibility to Private (or Public if you want others to discover it)
  2. Click Create

Via the API

bash
curl -X POST https://api.universalapi.co/agent/create \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "agentName": "my-product-assistant",
    "agentType": "bidi",
    "description": "Voice assistant that answers questions about my product",
    "sourceCode": "from strands.experimental.bidi.agent import BidiAgent\nfrom strands.experimental.bidi.models.nova_sonic import BidiNovaSonicModel\n\ndef create_bidi_agent():\n    model = BidiNovaSonicModel(\n        region=\"us-east-1\",\n        model_id=\"amazon.nova-sonic-v1:0\",\n        provider_config={\"audio\": {\"input_sample_rate\": 16000, \"output_sample_rate\": 24000, \"voice\": \"tiffany\"}}\n    )\n    system_prompt = \"You are a helpful voice assistant for my product.\"\n    return BidiAgent(model=model, system_prompt=system_prompt)",
    "visibility": "private"
  }'

Save the agentId from the response — you'll need it in the next step.

Choose a Voice

Nova Sonic supports several voice personalities. Replace "tiffany" in the source code with any of these:

VoiceStyle
tiffanyWarm, professional (default)
matthewClear, authoritative
amyFriendly, approachable

Step 3: Create an Embed Token (30 seconds)

Embed tokens are publishable keys (like Stripe's pk_live_ keys) that are safe to put in client-side HTML. They restrict which domains can use your voice agent.

Via the Dashboard

  1. Go to your agent's detail page
  2. Click the Embed tab
  3. Click Create Embed Token
  4. Add your domain(s) to the allowlist (e.g., yourdomain.com, localhost for testing)
  5. Copy the token — it starts with emb_pk_live_

Via the API

bash
curl -X POST https://api.universalapi.co/voice/embed/create \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "agentId": "YOUR_AGENT_ID",
    "allowedDomains": ["yourdomain.com", "localhost"],
    "brandColor": "#6366f1",
    "greeting": "Hi! Ask me anything about our product.",
    "position": "bottom-right"
  }'

Step 4: Add the Script Tag to Your Website (30 seconds)

This is the entire embed. One <script> tag:

html
<script src="https://cdn.universalapi.co/voice/v1.js"
  data-agent="YOUR_AGENT_ID"
  data-token="emb_pk_live_YOUR_TOKEN"
  data-color="#6366f1"
  data-greeting="Hi! Ask me anything about our product."
  data-position="bottom-right"
  async>
</script>

Paste this before the closing </body> tag on any page where you want the voice agent to appear.

That's it. Refresh the page and you'll see a microphone button in the bottom-right corner.

Customization Options

AttributeDescriptionDefault
data-agentYour voice agent's ID (required)
data-tokenYour embed token (required)
data-colorBrand color for the widget button#6366f1
data-greetingMessage shown when widget opens"Hi! How can I help?"
data-positionWidget position: bottom-right or bottom-leftbottom-right

Platform-Specific Instructions

WordPress: Add the script tag via Appearance → Theme Editor → footer.php, or use a plugin like "Insert Headers and Footers."

Squarespace: Go to Settings → Advanced → Code Injection → Footer, and paste the script tag.

Webflow: Open your project settings → Custom Code → Footer Code.

Next.js / React: Add to your root layout or use a <Script> component:

jsx
import Script from 'next/script'

export default function Layout({ children }) {
  return (
    <>
      {children}
      <Script
        src="https://cdn.universalapi.co/voice/v1.js"
        data-agent="YOUR_AGENT_ID"
        data-token="emb_pk_live_YOUR_TOKEN"
        data-color="#6366f1"
        data-greeting="Hi! Ask me anything."
        data-position="bottom-right"
        strategy="lazyOnload"
      />
    </>
  )
}

How It Works Under the Hood

When a visitor clicks the microphone button:

  1. Widget loads — The v1.js script renders a floating button in a Shadow DOM (no CSS conflicts with your site)
  2. WebSocket connects — Opens a bidirectional WebSocket to wss://voice.api.universalapi.co/ws/{agentId}
  3. Audio streams — Visitor's microphone audio streams in real-time (PCM 16kHz) to the server
  4. Nova Sonic processes — Amazon Nova Sonic handles speech recognition, reasoning, and speech synthesis simultaneously — no separate STT→LLM→TTS pipeline
  5. Agent responds — Audio streams back to the browser and plays through the speaker in real time
  6. Knowledge retrieval — If the agent needs to reference your docs, it queries your Knowledge storage via semantic search

The entire round trip is sub-second. It feels like talking to a real person.

Security

A few things to know about the security model:

  • Embed tokens are domain-restricted. The token only works on domains you've allowlisted. Someone can't copy your snippet and use it on their site.
  • Rate limits are enforced. Default: 10 calls per IP per day, 1000 total calls per day across all users. You can customize these when creating the token.
  • No credentials exposed. The emb_pk_live_ token is a publishable key — it can't be used to access your account, modify agents, or read your data.
  • Billing is on your account. Voice minutes are charged to your Universal API account at ~5 credits/minute.

What's Next?

Once your voice agent is live, here are some ways to make it even better:

Upload More Knowledge

The agent gets smarter as you add more content. Upload your changelog, case studies, comparison pages, and internal FAQs.

Connect MCP Tools

Want the agent to do more than answer questions? Connect it to MCP servers to give it tools:

  • Calendar booking — Let visitors schedule a demo during the conversation
  • CRM integration — Log the conversation as a lead
  • Ticket creation — If the visitor has a bug, create a support ticket automatically

Add Phone Support

Already have a Twilio account? You can connect the same voice agent to a phone number via Channels. Same agent, same knowledge, accessible by phone call.

Monitor Conversations

Check your Logs page to see conversation transcripts, duration, and credit usage. This helps you identify gaps in your documentation — if the agent keeps saying "I don't know" about a topic, upload content about it.


Quick Reference

StepWhatTime
1Upload your docs to Knowledge2 min
2Create a bidi voice agent2 min
3Create an embed token30 sec
4Paste the <script> tag30 sec

Total: ~5 minutes.

Your website visitors can now talk to your product. 🎙️


Have questions? Check the Voice Agents documentation or sign up free and try it yourself.

Universal API — The agentic entry point to the universe of APIs