Build a Voice Agent with C#

Create a real-time voice agent using the Deepgram .NET SDK.

This tutorial walks you through building a basic voice agent using C# and the Deepgram .NET SDK. You will learn how to connect to the Agent API, configure its behavior, and stream audio for processing.

Prerequisites

Before you begin, ensure you have the following:

  • A Deepgram API key. You can get one in the Deepgram Console.
  • The .NET SDK installed on your machine.

1. Set up your environment

Create a new console project and navigate into it.

mkdir deepgram-agent-demo
cd deepgram-agent-demo
dotnet new console

Export your Deepgram API key as an environment variable.

# macOS/Linux
export DEEPGRAM_API_KEY="your_api_key"
# Windows PowerShell
$env:DEEPGRAM_API_KEY = "your_api_key"

2. Install the Deepgram SDK

Add the Deepgram .NET SDK to your project.

dotnet add package Deepgram

3. Create the Voice Agent

Open Program.cs and replace its content with the following code. This script connects to Deepgram, configures the agent, and streams a sample audio file.

using Deepgram;
using Deepgram.Logger;
using Deepgram.Models.Authenticate.v1;
using Deepgram.Models.Agent.v2.WebSocket;
using System.Collections.Generic;
using System.Net.Http;
namespace SampleApp
{
class Program
{
static async Task Main(string[] args)
{
try
{
Deepgram.Library.Initialize(LogLevel.Debug);
var apiKey = Environment.GetEnvironmentVariable("DEEPGRAM_API_KEY");
DeepgramWsClientOptions options = new DeepgramWsClientOptions(null, null, true);
var agentClient = ClientFactory.CreateAgentWebSocketClient(apiKey, options);
var lastAudioTime = DateTime.Now;
var audioFileCount = 0;
var settingsConfiguration = new SettingsSchema();
settingsConfiguration.Agent.Think.Provider.Type = "open_ai";
settingsConfiguration.Agent.Think.Provider.Model = "gpt-4o-mini";
settingsConfiguration.Audio.Output.SampleRate = 24000;
settingsConfiguration.Audio.Output.Container = "wav";
settingsConfiguration.Audio.Input.SampleRate = 24000;
settingsConfiguration.Agent.Greeting = "Hello, how can I help you today?";
settingsConfiguration.Agent.Listen.Provider.Type = "deepgram";
settingsConfiguration.Agent.Listen.Provider.Model = "nova-3";
settingsConfiguration.Agent.Speak.Provider.Type = "deepgram";
settingsConfiguration.Agent.Speak.Provider.Model = "aura-2-thalia-en";
bool connected = await agentClient.Connect(settingsConfiguration);
if (!connected)
{
Console.WriteLine("Failed to connect to Deepgram WebSocket server.");
return;
}
await agentClient.Subscribe(new EventHandler<AudioResponse>((sender, e) =>
{
if (DateTime.Now.Subtract(lastAudioTime).TotalSeconds > 7)
{
audioFileCount++;
using (BinaryWriter writer = new BinaryWriter(File.Open($"output_{audioFileCount}.wav", FileMode.Create)))
{
writer.Write(CreateWavHeader(24000, 16, 1));
}
}
if (e.Stream != null)
{
using (BinaryWriter writer = new BinaryWriter(File.Open($"output_{audioFileCount}.wav", FileMode.Append)))
{
writer.Write(e.Stream.ToArray());
}
}
lastAudioTime = DateTime.Now;
}));
string url = "https://dpgr.am/spacewalk.wav";
using (var httpClient = new HttpClient())
{
var response = await httpClient.GetAsync(url);
var stream = await response.Content.ReadAsStreamAsync();
var buffer = new byte[8192];
int bytesRead;
while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length)) > 0)
{
var chunk = new byte[bytesRead];
Array.Copy(buffer, chunk, bytesRead);
await agentClient.SendBinaryImmediately(chunk);
}
}
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
await agentClient.Stop();
Deepgram.Library.Terminate();
}
catch (Exception ex)
{
Console.WriteLine($"Exception: {ex.Message}");
}
}
static byte[] CreateWavHeader(int sampleRate, short bitsPerSample, short channels)
{
int byteRate = sampleRate * channels * (bitsPerSample / 8);
short blockAlign = (short)(channels * (bitsPerSample / 8));
byte[] header = new byte[44];
header[0] = 0x52; // R
header[1] = 0x49; // I
header[2] = 0x46; // F
header[3] = 0x46; // F
header[8] = 0x57; // W
header[9] = 0x41; // A
header[10] = 0x56; // V
header[11] = 0x45; // E
header[12] = 0x66; // f
header[13] = 0x6D; // m
header[14] = 0x74; // t
header[15] = 0x20; // Space
header[16] = 0x10; // Subchunk1Size
header[20] = 0x01; // AudioFormat
header[22] = (byte)channels;
header[24] = (byte)(sampleRate & 0xFF);
header[25] = (byte)((sampleRate >> 8) & 0xFF);
header[26] = (byte)((sampleRate >> 16) & 0xFF);
header[27] = (byte)((sampleRate >> 24) & 0xFF);
header[28] = (byte)(byteRate & 0xFF);
header[29] = (byte)((byteRate >> 8) & 0xFF);
header[30] = (byte)((byteRate >> 16) & 0xFF);
header[31] = (byte)((byteRate >> 24) & 0xFF);
header[32] = (byte)blockAlign;
header[34] = (byte)bitsPerSample;
header[36] = 0x64; // d
header[37] = 0x61; // t
header[38] = 0x74; // t
header[39] = 0x61; // a
return header;
}
}
}

4. Run the Voice Agent

Run your project using the .NET CLI.

dotnet run

The agent will process the audio and generate responses. You can find the agent’s audio responses in output_*.wav files in your project directory.

Next steps

Now that you have built a basic agent, you can customize its behavior: