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:

  1. Your server asks Glytos for a short-lived web-call token, naming the agent.
  2. 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, or
  • agent - an inline agent definition (mode, config, and optionally graph) used for this call without you saving it first.
const { token, ws_url } = await glytos.calls.webToken({ workflow_uuid: agentUuid });

The response:

FieldWhat it is
tokenThe short-lived token to hand to the browser.
workflow_uuidThe agent the call will run. For an inline agent, the id it was given.
ws_urlThe address the browser SDK connects to. Pass it through unchanged.
expires_inSeconds 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:

MethodWhat 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 iceServers option, new GlytosWebCall({ token, wsUrl, iceServers }).