Example: Answering an incoming call

View as MarkdownOpen in Claude

This example answers an inbound Voximplant call and bridges audio to Ultravox’s WebSocket API for real‑time speech‑to‑speech conversations.

⬇️ Jump to the Full VoxEngine scenario.

Prerequisites

Session setup

Ultravox uses a WebSocket API client created via Ultravox.createWebSocketAPIClient(...). The key inputs are:

  • endpoint: use Ultravox.HTTPEndpoint.CREATE_CALL (or CREATE_AGENT_CALL for an existing Ultravox agent).
  • authorizations: include X-API-Key with your Ultravox API key.
  • body: provide systemPrompt, model, and voice.

Connect call audio

Once the client is created, bridge audio both ways between the call and Ultravox:

Connect call audio
1VoxEngine.sendMediaBetween(call, voiceAIClient);

Barge-in

Ultravox supports barge-in by providing a PlaybackClearBuffer event. If you want to interrupt the agent speech, listen for this event and clear the media buffer with clearMediaBuffer():

Barge-in
1voiceAIClient.addEventListener(Ultravox.WebSocketAPIEvents.PlaybackClearBuffer, (event) => {
2 Logger.write("===PLAYBACK_CLEAR_BUFFER===");
3 voiceAIClient.clearMediaBuffer();
4});

The Ultravox server may also request a buffer clear via PlaybackClearBuffer — this example handles both cases.

Events

The client supports both WebSocket API events and media events. Key events used in the example:

  • Ultravox.WebSocketAPIEvents: Transcript, HTTPResponse, State, Debug, WebSocketError, ConnectorInformation, Unknown, PlaybackClearBuffer
  • Ultravox.Events: WebSocketMediaStarted, WebSocketMediaEnded

Full VoxEngine scenario

voxeengine-ultravox-answer-incoming-call.js
1/**
2 * Voximplant + Ultravox WebSocket API connector demo
3 * Scenario: answer an incoming call and bridge it to Ultravox.
4 */
5
6require(Modules.Ultravox);
7require(Modules.ApplicationStorage);
8
9const SYSTEM_PROMPT = `You are Voxi, a helpful voice assistant for phone callers.
10Keep responses short and telephony-friendly (usually 1-2 sentences).`;
11
12// -------------------- Ultravox WebSocket API settings --------------------
13const AGENT_CONFIG = {
14 systemPrompt: SYSTEM_PROMPT,
15 model: "ultravox-v0.7",
16 voice: "Mark",
17};
18
19VoxEngine.addEventListener(AppEvents.CallAlerting, async ({call}) => {
20 let voiceAIClient;
21
22 // Termination functions - add cleanup and logging as needed
23 call.addEventListener(CallEvents.Disconnected, ()=>VoxEngine.terminate());
24 call.addEventListener(CallEvents.Failed, ()=>VoxEngine.terminate());
25
26 try {
27 call.answer();
28 // call.record({ hd_audio: true, stereo: true }); // Optional: record the call
29
30 // Create client and wire media
31 voiceAIClient = await Ultravox.createWebSocketAPIClient(
32 {
33 endpoint: Ultravox.HTTPEndpoint.CREATE_CALL,
34 authorizations: {"X-API-Key": (await ApplicationStorage.get("ULTRAVOX_API_KEY")).value},
35 body: AGENT_CONFIG,
36 onWebSocketClose: (event) => {
37 Logger.write("===ULTRAVOX_WEBSOCKET_CLOSED===");
38 if (event) Logger.write(JSON.stringify(event));
39 VoxEngine.terminate();
40 },
41 },
42 );
43 VoxEngine.sendMediaBetween(call, voiceAIClient);
44
45 // ---------------------- Event handlers -----------------------
46 // Barge-in: keep conversation responsive and capture transcript
47 voiceAIClient.addEventListener(Ultravox.WebSocketAPIEvents.Transcript, (event) => {
48 const payload = event?.data?.payload || event?.data || {};
49 const role = payload.role;
50 const text = payload.text || payload.delta;
51
52 if (role && text) Logger.write(`===TRANSCRIPT=== ${role}: ${text}`);
53 });
54
55 voiceAIClient.addEventListener(Ultravox.WebSocketAPIEvents.PlaybackClearBuffer, (event) => {
56 Logger.write("===PLAYBACK_CLEAR_BUFFER===");
57 voiceAIClient.clearMediaBuffer();
58 });
59
60 // Consolidated "log-only" handlers - key Ultravox/VoxEngine debugging events
61 [
62 Ultravox.WebSocketAPIEvents.ConnectorInformation,
63 Ultravox.WebSocketAPIEvents.HTTPResponse,
64 Ultravox.WebSocketAPIEvents.State,
65 Ultravox.WebSocketAPIEvents.Debug,
66 Ultravox.WebSocketAPIEvents.WebSocketError,
67 Ultravox.WebSocketAPIEvents.Unknown,
68 Ultravox.Events.WebSocketMediaStarted,
69 Ultravox.Events.WebSocketMediaEnded,
70 ].forEach((eventName) => {
71 voiceAIClient.addEventListener(eventName, (event) => {
72 Logger.write(`===${event.name}===`);
73 Logger.write(JSON.stringify(event));
74 });
75 });
76 } catch (error) {
77 Logger.write("===SOMETHING_WENT_WRONG===");
78 Logger.write(error);
79 voiceAIClient?.close();
80 VoxEngine.terminate();
81 }
82});