Web calls
A web call is a real-time voice conversation from a browser - the same agent that answers your phone number, reachable from a page.
Trying one
The Playground starts a web call against any agent. That is the fastest way to hear an agent without shipping anything.
Putting one in your own product
Use the browser SDK, @glytos/web. See the Web SDK.
The flow is deliberately split in two so your API key never reaches a browser:
- Your server asks Glytos for a short-lived web-call token, naming the agent.
- Your page hands that token to the SDK, which connects and starts talking.
Never put an API key in front-end code. Mint a token on your server. A key in a browser is a key anyone can read and use against your credit.
1. Mint a token on your server
POST /calls/web-token with exactly one of:
workflow_uuid- a saved agent, oragent- an inline agent definition (mode,config, and optionallygraph) used for this call without you saving it first.
const { token, ws_url } = await glytos.calls.webToken({ workflow_uuid: agentUuid });minted = glytos.calls.web_token(workflow_uuid=agent_uuid)curl -X POST https://api.glytos.com/api/v1/calls/web-token \
-H "X-API-Key: $GLYTOS_API_KEY" -H 'Content-Type: application/json' \
-d '{"workflow_uuid":"'$AGENT'"}'The response:
| Field | What it is |
|---|---|
token | The short-lived token to hand to the browser. |
workflow_uuid | The agent the call will run. For an inline agent, the id it was given. |
ws_url | The address the browser SDK connects to. Pass it through unchanged. |
expires_in | Seconds the token stays valid: 600 (ten minutes). Mint one per call, just before connecting. |
The key needs permission to run agents.
2. Start the call in the page
import { GlytosWebCall } from '@glytos/web';
const call = new GlytosWebCall({ token, wsUrl: ws_url });
call.on('status', s => setStatus(s));
call.on('transcript', m => { if (m.final) append(m.role, m.text); });
call.on('ended', () => cleanup());
await call.start();
// later
call.stop();Talking to the call from the page
While the call is running, the page can steer it:
| Method | What it does |
|---|---|
call.say(text) | The agent speaks exactly this line. Not available on the Gemini and Grok speech-to-speech engines, which cannot speak a fixed line; there it is dropped. |
call.send(text) | Adds text to the conversation as if the user had said it, and the agent answers. |
call.send(text, 'system') | Adds text as a system note, and the agent answers. |
call.setMicMuted(muted) | Mutes the microphone; the call keeps running. |
call.setAssistantMuted(muted) | Silences the agent's audio on this page only. |
Treat these like any input from a browser: whoever is on the page can call them.
Client tools
A tool of kind Client is answered by your page instead of the server, for anything
only the browser knows - the signed-in user, what is on screen. When the model calls
it, the SDK emits function-call with an id; answer with respondToTool:
call.on('function-call', async ({ name, args, id }) => {
if (!id) return; // a server-side tool, reported for your information
if (name === 'current_cart') {
call.respondToTool(id, { items: cart.items, total: cart.total });
}
});The page has 30 seconds to answer; after that the model is told the tool failed.
function-call also fires, without an id, when the agent runs one of its server-side
tools, so you can show what it is doing. Client tools work only in a web call - see
Tools.
Requirements
- The page must be served over HTTPS - browsers only grant microphone access on a secure origin.
- The user must grant microphone permission.
- The SDK connects peer to peer using a public STUN server by default. Users behind
strict corporate firewalls or carrier-grade NAT (common on mobile networks) may need
a TURN relay: pass your own with the
iceServersoption,new GlytosWebCall({ token, wsUrl, iceServers }).