> For a complete documentation index, fetch https://docs.voximplant.ai/llms.txt

# Example: Function calling

> This example answers an inbound Voximplant call, connects it to ElevenLabs Agents, and handles client-side tool calls inside VoxEngine.

<blockquote>
  For the complete documentation index, see <a href="/llms.txt">llms.txt</a>.
</blockquote>

This example answers an inbound Voximplant call, connects it to ElevenLabs Agents, and handles client-side tool calls inside VoxEngine.

**Jump to the [Full VoxEngine scenario](#full-voxengine-scenario).**

## Prerequisites

* Set up an inbound entrypoint for the caller:
  * Phone number: [https://voximplant.com/docs/getting-started/basic-concepts/phone-numbers](https://voximplant.com/docs/getting-started/basic-concepts/phone-numbers)
  * WhatsApp: [https://voximplant.com/docs/guides/integrations/whatsapp](https://voximplant.com/docs/guides/integrations/whatsapp)
  * SIP user / SIP registration: [https://voximplant.com/docs/guides/calls/sip](https://voximplant.com/docs/guides/calls/sip)
  * App user: [https://voximplant.com/docs/getting-started/basic-concepts/users](https://voximplant.com/docs/getting-started/basic-concepts/users) (see also [https://voximplant.com/docs/guides/calls/scenarios#how-to-call-a-voximplant-user](https://voximplant.com/docs/guides/calls/scenarios#how-to-call-a-voximplant-user))
* Create a routing rule that points the destination (phone number / WhatsApp / SIP username / app user alias) to this scenario: [https://voximplant.com/docs/getting-started/basic-concepts/routing-rules](https://voximplant.com/docs/getting-started/basic-concepts/routing-rules)
* Store your ElevenLabs API key in Voximplant [Secrets](/platform/voxengine/secrets) under `ELEVENLABS_API_KEY`.
* Store your ElevenLabs Agent ID in Voximplant `ApplicationStorage` under `ELEVENLABS_AGENT_ID` (the agent ID is not sensitive, so it can live in key-value storage).
* Configure a client tool in your ElevenLabs Agent named `get_weather` that expects a `location` parameter.

## Tool handling

ElevenLabs Agents send tool requests via `ElevenLabs.AgentsEvents.ClientToolCall`. The example extracts the tool name and parameters, runs a stub implementation, and sends the result back using `clientToolResult`:

```js title="Tool handling"
agentsClient.addEventListener(ElevenLabs.AgentsEvents.ClientToolCall, (event) => {
  const payload = event?.data?.payload || event?.data || {};
  const toolName = payload.tool_name || payload.toolName || payload.name;
  const toolCallId = payload.tool_call_id || payload.toolCallId || payload.id;

  if (toolName !== "get_weather") return;

  const result = { location: "San Francisco", temperature_f: 72, condition: "sunny" };

  agentsClient.clientToolResult({
    tool_call_id: toolCallId,
    tool_name: toolName,
    result,
  });
});
```

## Barge-in

```js title="Barge-in"
agentsClient.addEventListener(ElevenLabs.AgentsEvents.Interruption, () => {
  agentsClient.clearMediaBuffer();
});
```

## Notes

[See the VoxEngine API Reference for more details](https://voximplant.com/docs/references/voxengine/elevenlabs).

## Full VoxEngine scenario

```javascript title={"voxeengine-elevenlabs-tool-call.js"} maxLines={0}
/**
 * Voximplant + ElevenLabs Agents connector demo
 * Scenario: answer an incoming call and handle ElevenLabs tool calls.
 */

require(Modules.ElevenLabs);
require(Modules.ApplicationStorage);

const TOOL_NAME = "get_weather";

VoxEngine.addEventListener(AppEvents.CallAlerting, async ({call}) => {
    let voiceAIClient;

    call.addEventListener(CallEvents.Disconnected, () => VoxEngine.terminate());
    call.addEventListener(CallEvents.Failed, () => VoxEngine.terminate());

    try {
        call.answer();

        // Create client and connect to ElevenLabs Agents
        voiceAIClient = await ElevenLabs.createAgentsClient({
            xiApiKey: VoxEngine.getSecretValue('ELEVENLABS_API_KEY'),
            agentId: (await ApplicationStorage.get("ELEVENLABS_AGENT_ID")).value,
            onWebSocketClose: (event) => {
                Logger.write("===ElevenLabs.WebSocket.Close===");
                if (event) Logger.write(JSON.stringify(event));
                VoxEngine.terminate();
            },
        });

        // Bridge media between the call and ElevenLabs Agents
        VoxEngine.sendMediaBetween(call, voiceAIClient);

        // ---------------------- Event handlers -----------------------
        // Barge-in: keep conversation responsive
        voiceAIClient.addEventListener(ElevenLabs.AgentsEvents.Interruption, () => {
            Logger.write("===BARGE-IN: ElevenLabs.AgentsEvents.Interruption===");
            voiceAIClient.clearMediaBuffer();
        });

        // Handle user transcripts
        voiceAIClient.addEventListener(ElevenLabs.AgentsEvents.UserTranscript, (event) => {
            const payload = event?.data?.payload || event?.data || {};
            const text = payload.text || payload.transcript || payload.user_transcript;
            if (text) {
                Logger.write(`===USER=== ${text}`);
            } else {
                Logger.write("===USER_TRANSCRIPT===");
                Logger.write(JSON.stringify(payload));
            }
        });

        // Handle tool calls
        voiceAIClient.addEventListener(ElevenLabs.AgentsEvents.ClientToolCall, (event) => {
            const payload = event?.data?.payload || event?.data || {};
            const toolName = payload.tool_name || payload.toolName || payload.name;
            const toolCallId = payload.tool_call_id || payload.toolCallId || payload.id;

            if (!toolName || !toolCallId) {
                Logger.write("===TOOL_CALL_MISSING_FIELDS===");
                Logger.write(JSON.stringify(payload));
                return;
            }

            let args = {};
            const rawArgs = payload.parameters || payload.args || payload.arguments;
            if (typeof rawArgs === "string") {
                try {
                    args = JSON.parse(rawArgs);
                } catch (error) {
                    Logger.write("===TOOL_ARGS_PARSE_ERROR===");
                    Logger.write(rawArgs);
                    Logger.write(error);
                }
            } else if (rawArgs && typeof rawArgs === "object") {
                args = rawArgs;
            }

            if (toolName !== TOOL_NAME) {
                voiceAIClient.clientToolResult({
                    tool_call_id: toolCallId,
                    tool_name: toolName,
                    result: {error: `Unhandled tool: ${toolName}`},
                });
                return;
            }

            const location = args.location || "Unknown";
            const result = {
                location,
                temperature_f: 72,
                condition: "sunny",
            };

            voiceAIClient.clientToolResult({
                tool_call_id: toolCallId,
                tool_name: toolName,
                result,
            });
        });

        voiceAIClient.addEventListener(ElevenLabs.AgentsEvents.AgentResponse, (event) => {
            const payload = event?.data?.payload || event?.data || {};
            const text = payload.text || payload.response || payload.agent_response;
            if (text) {
                Logger.write(`===AGENT=== ${text}`);
            } else {
                Logger.write("===AGENT_RESPONSE===");
                Logger.write(JSON.stringify(payload));
            }
        });

        // Consolidated "log-only" handlers - key ElevenLabs/VoxEngine debugging events
        [
            ElevenLabs.AgentsEvents.ConversationInitiationMetadata,
            ElevenLabs.AgentsEvents.AgentResponseCorrection,
            ElevenLabs.AgentsEvents.ContextualUpdate,
            ElevenLabs.AgentsEvents.AgentToolResponse,
            ElevenLabs.AgentsEvents.VadScore,
            ElevenLabs.AgentsEvents.Ping,
            ElevenLabs.AgentsEvents.HTTPResponse,
            ElevenLabs.AgentsEvents.WebSocketError,
            ElevenLabs.AgentsEvents.ConnectorInformation,
            ElevenLabs.AgentsEvents.Unknown,
            ElevenLabs.Events.WebSocketMediaStarted,
            ElevenLabs.Events.WebSocketMediaEnded,
        ].forEach((eventName) => {
            voiceAIClient.addEventListener(eventName, (event) => {
                Logger.write(`===${event.name}===`);
                if (event?.data) Logger.write(JSON.stringify(event.data));
            });
        });
    } catch (error) {
        Logger.write("===UNHANDLED_ERROR===");
        Logger.write(error);
        voiceAIClient?.close();
        VoxEngine.terminate();
    }
});

```