Skip to content

Realtime Voice Call

Connect to the Ultravox real-time voice call WebSocket API for bidirectional voice/text communication.

This example assumes using Ultravox; is in scope and apiKey contains your Ultravox API key.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
using var client = new UltravoxClient(apiKey);

// Create a call using the REST API to get a joinUrl.
var call = await client.Calls.CallsCreateAsync(new UltravoxV1StartCallRequest
{
    SystemPrompt = "You are a helpful assistant. Respond briefly.",
});

Console.WriteLine($"Call ID: {call.CallId}");

// Connect to the WebSocket using the joinUrl from the REST call.
using var realtimeClient = new UltravoxRealtimeClient();
await realtimeClient.ConnectAsync(new Uri(call.JoinUrl!));

// Send a text message to the agent.
await realtimeClient.SendUserTextMessageAsync(new UserTextMessagePayload
{
    Text = "Hello, how are you?",
});

// Receive server events: state changes, transcripts, and tool invocations.
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30));
var receivedCallStarted = false;
var receivedTranscript = false;

await foreach (var serverEvent in realtimeClient.ReceiveUpdatesAsync(cts.Token))
{
    if (serverEvent.IsCallStarted)
    {
        receivedCallStarted = true;
        Console.WriteLine($"Call started: {serverEvent.CallStarted?.CallId}");
    }
    else if (serverEvent.IsState)
    {
        Console.WriteLine($"Agent state: {serverEvent.State?.State}");
    }
    else if (serverEvent.IsTranscript)
    {
        var transcript = serverEvent.Transcript!;
        Console.Write(transcript.Delta ?? transcript.Text);

        if (transcript.Final == true && transcript.Role == TranscriptPayloadRole.Agent)
        {
            receivedTranscript = true;
            Console.WriteLine();
            break;
        }
    }
    else if (serverEvent.IsClientToolInvocation)
    {
        // Respond to client tool invocations.
        var invocation = serverEvent.ClientToolInvocation!;
        await realtimeClient.SendClientToolResultAsync(new ClientToolResultPayload
        {
            InvocationId = invocation.InvocationId,
            Result = "Tool executed successfully.",
        });
    }
    else if (serverEvent.IsDebug)
    {
        Console.WriteLine($"Debug: {serverEvent.Debug?.Message}");
    }
}

// Hang up the call.
await realtimeClient.SendHangUpAsync(new HangUpPayload
{
    Message = "Goodbye!",
});