Example: Function calling

View as Markdown

For the complete documentation index, see llms.txt.

This example answers an inbound Voximplant call, connects it to Deepgram Voice Agent, and handles function calls (tool requests) from the agent inside VoxEngine.

⬇️ Jump to the Full VoxEngine scenario.

Prerequisites

Session setup

The Voice Agent session is configured via a settingsOptions object passed to Deepgram.createVoiceAgentClient(...).

For function calling, the key part is SETTINGS_OPTIONS.agent.think.functions:

  • name, description, parameters: define the tool schema the LLM can call
  • client_side: true: ensures VoxEngine receives FunctionCallRequest and can respond

Connect call audio

Once the Deepgram.VoiceAgentClient is created, bridge audio both ways:

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

Function calling

In the scenario, Deepgram.VoiceAgentEvents.FunctionCallRequest delivers one or more function calls requested by the agent.

Each call includes an id, a name, and JSON string arguments. Respond using voiceAgentClient.sendFunctionCallResponse(...) with a FunctionCallResponse message containing the same id:

Handle FunctionCallRequest and respond
1voiceAgentClient.addEventListener(Deepgram.VoiceAgentEvents.FunctionCallRequest, (event) => {
2 const { functions } = event?.data?.payload || {};
3 if (!Array.isArray(functions)) return;
4
5 functions.forEach(({ id, name, arguments: rawArguments }) => {
6 // ...perform the function...
7 voiceAgentClient.sendFunctionCallResponse({
8 type: "FunctionCallResponse",
9 id,
10 name,
11 content: JSON.stringify({ ok: true }),
12 });
13 });
14});

Barge-in

As in the other examples, keep the experience interruption-friendly by clearing buffered audio on UserStartedSpeaking:

Barge-in
1voiceAgentClient.addEventListener(Deepgram.VoiceAgentEvents.UserStartedSpeaking, () => {
2 voiceAgentClient.clearMediaBuffer();
3});

Events

The function calling flow is driven by:

  • Deepgram.VoiceAgentEvents.FunctionCallRequest: agent requests a client-side function execution
  • Deepgram.VoiceAgentEvents.FunctionCallResponse: emitted when a function call response is processed

For the complete list of supported events:

Notes

See the VoxEngine API Reference for more details.

Full VoxEngine scenario

voxeengine-deepgram-function-calling.js
1/**
2 * Voximplant + Deepgram Voice Agent connector demo
3 * Scenario: answer an incoming call and handle Deepgram function calling.
4 */
5
6require(Modules.Deepgram);
7const SYSTEM_PROMPT = `
8You are a helpful English-speaking voice assistant for phone callers.
9Keep your turns short and telephony-friendly (usually 1–2 sentences).
10
11If the caller asks about the weather, call the "get_weather" function.
12`;
13
14// -------------------- Deepgram Voice Agent settings --------------------
15const SETTINGS_OPTIONS = {
16 tags: ["voximplant", "deepgram", "voice_agent_connector", "function_calling_demo"],
17 agent: {
18 language: "en",
19 greeting: "Hi! I'm Voxi. How can I help today?",
20 listen: {
21 provider: {
22 type: "deepgram",
23 model: "flux-general-en",
24 },
25 },
26 think: {
27 provider: {
28 type: "open_ai",
29 model: "gpt-4o-mini",
30 },
31 prompt: SYSTEM_PROMPT,
32 functions: [
33 {
34 name: "get_weather",
35 description: "Get current weather for a location (demo stub)",
36 parameters: {
37 type: "object",
38 properties: {
39 location: {
40 type: "string",
41 description: "City name, for example: San Francisco",
42 },
43 },
44 required: ["location"],
45 },
46 // Mark as client-side so VoxEngine receives FunctionCallRequest and can respond.
47 client_side: true,
48 },
49 ],
50 },
51 speak: {
52 provider: {
53 type: "deepgram",
54 model: "aura-2-cordelia-en",
55 },
56 },
57 },
58};
59
60VoxEngine.addEventListener(AppEvents.CallAlerting, async ({call}) => {
61 let voiceAIClient;
62
63 // Termination functions - add cleanup and logging as needed
64 call.addEventListener(CallEvents.Disconnected, ()=>VoxEngine.terminate());
65 call.addEventListener(CallEvents.Failed, ()=>VoxEngine.terminate());
66
67 try {
68 call.answer();
69 // call.record({hd_audio: true, stereo: true}); // optional: call recording
70
71 // Create client and wire media
72 voiceAIClient = await Deepgram.createVoiceAgentClient({
73 apiKey: VoxEngine.getSecretValue('DEEPGRAM_API_KEY'),
74 settingsOptions: SETTINGS_OPTIONS,
75 });
76 VoxEngine.sendMediaBetween(call, voiceAIClient);
77
78 // ---------------------- Event handlers -----------------------
79 // Barge-in: keep conversation responsive
80 voiceAIClient.addEventListener(Deepgram.VoiceAgentEvents.UserStartedSpeaking, () => {
81 Logger.write("===BARGE-IN: Deepgram.VoiceAgentEvents.UserStartedSpeaking===");
82 voiceAIClient.clearMediaBuffer();
83 });
84
85 // Function calling: handle tool requests and send back responses
86 voiceAIClient.addEventListener(Deepgram.VoiceAgentEvents.FunctionCallRequest, (event) => {
87 const {functions} = event?.data?.payload || {};
88 if (!Array.isArray(functions) || functions.length === 0) return;
89
90 functions.forEach((fn) => {
91 const {id, name, arguments: rawArguments} = fn || {};
92 if (!id || !name) return;
93
94 if (name !== "get_weather") {
95 voiceAIClient.sendFunctionCallResponse({
96 type: "FunctionCallResponse",
97 id,
98 name,
99 content: JSON.stringify({error: `Unhandled function: ${name}`}),
100 });
101 return;
102 }
103
104 let args = {};
105 try {
106 args = rawArguments ? JSON.parse(rawArguments) : {};
107 } catch (error) {
108 Logger.write(`===FUNCTION_ARGS_PARSE_ERROR=== ${rawArguments}`);
109 Logger.write(error);
110 }
111
112 const location = args.location || "Unknown";
113
114 // Demo response (no external API call)
115 const result = {
116 location,
117 temperature_f: 72,
118 condition: "sunny",
119 };
120
121 voiceAIClient.sendFunctionCallResponse({
122 type: "FunctionCallResponse",
123 id,
124 name,
125 content: JSON.stringify(result),
126 });
127 });
128 });
129
130 } catch (error) {
131 Logger.write("===UNHANDLED_ERROR===");
132 Logger.write(error);
133 VoxEngine.terminate();
134 }
135});