Example: Function calling

View as Markdown

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