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

# Example: Using Grok features

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

## Overview

This inbound example showcases Grok tools (function calling, file\_search, web\_search, x\_search) with barge-in for telephony use. The same tool configuration applies to outbound calls—reuse the tools and prompt in your outbound scenario and swap the call entrypoint.

**⬇️ 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 Grok API key in Voximplant [Secrets](/platform/voxengine/secrets) under `GROK_API_KEY`.
* If you use `file_search`, upload documents and set `COLLECTION_ID` accordingly.

## Usage highlights

* Create a `VoiceAgentAPIClient` with `Grok.createVoiceAgentAPIClient(...)`.
* Configure the session with `voice`, `turn_detection`, `instructions`, and tools.
* Bridge audio with `VoxEngine.sendMediaBetween(call, client)`.
* Handle function calls with `ResponseFunctionCallArgumentsDone`.

### Feature summary

* **Function calling**: Let Grok request server-side actions, then respond with structured outputs. See [Function calling](#function-calling). Also see Grok docs: [https://docs.x.ai/docs/guides/tools/overview#function-calling](https://docs.x.ai/docs/guides/tools/overview#function-calling)
* **RAG with file\_search**: Ground responses in your uploaded documents using vector search. See [RAG with file\_search](#rag-with-file_search). Also see Grok docs: [https://docs.x.ai/docs/guides/tools/overview#file-search](https://docs.x.ai/docs/guides/tools/overview#file-search)
* **Web search**: Allow Grok to fetch current public information when needed. See [Web search](#web-search). Also see Grok docs: [https://docs.x.ai/docs/guides/tools/overview#web-search](https://docs.x.ai/docs/guides/tools/overview#web-search)
* **X/Twitter search**: Constrain Grok to specific X handles for social lookups. See [X/Twitter search](#xtwitter-search). Also see Grok docs: [https://docs.x.ai/docs/guides/tools/overview#x-search](https://docs.x.ai/docs/guides/tools/overview#x-search)

### Turn detection & barge-in

When `InputAudioBufferSpeechStarted` fires, clear the media buffer so the caller can interrupt the agent:

```js
voiceAgentAPIClient.addEventListener(
  Grok.VoiceAgentAPIEvents.InputAudioBufferSpeechStarted,
  () => voiceAgentAPIClient.clearMediaBuffer()
);
```

## Function calling

Function calling lets Grok request actions from VoxEngine (transfer, hang up, fetch data) and receive a structured response. For official Grok tool guidance, see [https://docs.x.ai/docs/guides/tools/overview#function-calling](https://docs.x.ai/docs/guides/tools/overview#function-calling).

```js
{
  type: "function",
  name: "forward_to_agent",
  description: "Forward the user to a live agent",
  parameters: {
    type: "object",
    properties: {},
    required: [],
  },
}
```

Handle tool calls and return outputs to the agent:

```js
voiceAgentAPIClient.addEventListener(
  Grok.VoiceAgentAPIEvents.ResponseFunctionCallArgumentsDone,
  (event) => {
    const { name, call_id } = event?.data?.payload || {};
    if (name !== "forward_to_agent" && name !== "hangup_call") return;

    const output =
      name === "forward_to_agent"
        ? { result: "Forwarding your call to a live agent. Please hold on." }
        : { result: "Have a great day, goodbye!" };

    voiceAgentAPIClient.conversationItemCreate({
      item: {
        type: "function_call_output",
        call_id,
        output: JSON.stringify(output),
      },
    });
    voiceAgentAPIClient.responseCreate({});
  }
);
```

## RAG with file\_search

Use `file_search` to ground responses in your documents. Upload files to Grok, then reference the collection (vector store) ID in your session tools. For official Grok tool guidance, see [https://docs.x.ai/docs/guides/tools/overview#file-search](https://docs.x.ai/docs/guides/tools/overview#file-search).

```js
{
  type: "file_search",
  vector_store_ids: [COLLECTION_ID],
  max_num_results: 5,
}
```

* Keep your collection focused on the topics the agent should answer.
* Tune `max_num_results` to balance relevance and speed.

## Web search

Enable `web_search` when you want Grok to fetch public web information at runtime. For official Grok tool guidance, see [https://docs.x.ai/docs/guides/tools/overview#web-search](https://docs.x.ai/docs/guides/tools/overview#web-search).

```js
{ type: "web_search" }
```

## X/Twitter search

Use `x_search` to limit Grok's social search to specific X handles. For official Grok tool guidance, see [https://docs.x.ai/docs/guides/tools/overview#x-search](https://docs.x.ai/docs/guides/tools/overview#x-search).

```js
{
  type: "x_search",
  allowed_x_handles: ["voximplant", "aylarov"],
}
```

## Configure before you run

* Set `GROK_API_KEY` in Voximplant [Secrets](/platform/voxengine/secrets).
* Update `COLLECTION_ID` to point at your uploaded documents (or remove `file_search`).
* Adjust the `SYSTEM_PROMPT` to match your brand voice and escalation rules.

## Try it

## Notes

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

## Full VoxEngine scenario

This scenario includes barge-in handling, function calling, file search, web search, and X search.

```javascript title={"voxeengine-grok-features.js"} maxLines={0}
require(Modules.Grok);
const SYSTEM_PROMPT = `
  Your name is Voxi. You are a helpful voice assistant for phone callers representing the company Voximplant (pronounced VOX-im-plant).
  You can answer questions about the company, its voice AI integrations, and X/Twitter posts from the "voximplant" and "aylarov" handles.
  "aylarov" is the X handle for Alexey Aylarov, Voximplant's CEO.

  Keep responses short and telephony-friendly (usually 1-2 sentences).
  If the user asks for a live agent or an operator, call the "forward_to_agent" function.
  If the user says goodbye, call the "hangup_call" function.

  When answering a company/product question, prefer searching the knowledge base first.
  `;
const COLLECTION_ID = "collection_4c5a63ab-f739-4c13-93d2-05b74095c34a"; // uploaded documents to show RAG

// -------------------- Grok Voice Agent settings --------------------
const SESSION_PARAMETERS = {
    session: {
        voice: "Ara",
        turn_detection: {type: "server_vad"},
        instructions: SYSTEM_PROMPT,
        tools: [
            {type: "web_search"},
            {
                type: "file_search",
                vector_store_ids: [COLLECTION_ID],
                max_num_results: 5,
            },
            {
                type: "x_search",
                allowed_x_handles: ["voximplant", "aylarov"],
            },
            {
                type: "function",
                name: "forward_to_agent",
                description: "Forward the user to a live agent",
                parameters: {
                    type: "object",
                    properties: {},
                    required: [],
                },
            },
            {
                type: "function",
                name: "hangup_call",
                description: "Hangup the call",
                parameters: {
                    type: "object",
                    properties: {},
                    required: [],
                },
            },
        ],
    },
};

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

    call.answer();
    call.record({hd_audio: true, stereo: true}); // optional: call recording

    const callCloseHandler = () => {
        voiceAIClient?.close();
        VoxEngine.terminate();
    };
    call.addEventListener(CallEvents.Disconnected, callCloseHandler);
    call.addEventListener(CallEvents.Failed, callCloseHandler);

    try {
        voiceAIClient = await Grok.createVoiceAgentAPIClient({
            xAIApiKey: VoxEngine.getSecretValue('GROK_API_KEY'),
            onWebSocketClose: (event) => {
                Logger.write(`===${event.name}===>${JSON.stringify(event.data)}`);
                VoxEngine.terminate();
            },
        });

        voiceAIClient.addEventListener(Grok.VoiceAgentAPIEvents.ConversationCreated, (event) => {
            Logger.write(`===${event.name}===>${JSON.stringify(event.data)}`);


            voiceAIClient.sessionUpdate(SESSION_PARAMETERS);
        });

        voiceAIClient.addEventListener(Grok.VoiceAgentAPIEvents.SessionUpdated, (event) => {
            Logger.write(`===${event.name}===>${JSON.stringify(event.data)}`);
            VoxEngine.sendMediaBetween(call, voiceAIClient);
            voiceAIClient.responseCreate({instructions: "Hello."});
        });

        // -------------------- Barge-in (keep it interruption-friendly) --------------------
        voiceAIClient.addEventListener(Grok.VoiceAgentAPIEvents.InputAudioBufferSpeechStarted, (event) => {
            Logger.write(`===${event.name}===>${JSON.stringify(event.data)}`);
            voiceAIClient.clearMediaBuffer();
        });

        // -------------------- Function calling --------------------
        voiceAIClient.addEventListener(Grok.VoiceAgentAPIEvents.ResponseFunctionCallArgumentsDone, (event) => {
            Logger.write(`===${event.name}===>${JSON.stringify(event.data)}`);

            const {name, call_id} = event?.data?.payload || {};
            let output;

            // Ignore server-side tools like collections_search / web_search / x_search
            if (name !== "forward_to_agent" && name !== "hangup_call") {
                Logger.write(`===Ignoring unhandled function call: ${name}===`);
                return;
            }

            if (name === "forward_to_agent") {
                forwardToLiveAgent = true;
                output = {result: "Forwarding your call to a live agent. Please hold on."};
            } else if (name === "hangup_call") {
                hangupCall = true;
                output = {result: "Have a great day, goodbye!"};
            }

            // Create a conversationItem and send it
            voiceAIClient.conversationItemCreate({
                item: {
                    type: "function_call_output",
                    call_id,
                    output: JSON.stringify(output),
                },
            });
            voiceAIClient.responseCreate({});
        });

        // -------------------- Log Other Events --------------------
        [
            CallEvents.FirstAudioPacketReceived,
            Grok.Events.WebSocketMediaStarted,
            Grok.VoiceAgentAPIEvents.InputAudioBufferSpeechStopped,
            Grok.VoiceAgentAPIEvents.ConversationItemInputAudioTranscriptionCompleted,
            Grok.VoiceAgentAPIEvents.ConversationItemAdded,
            Grok.VoiceAgentAPIEvents.ResponseCreated,
            Grok.VoiceAgentAPIEvents.ResponseOutputItemAdded,
            Grok.VoiceAgentAPIEvents.ResponseDone,
            Grok.VoiceAgentAPIEvents.ResponseOutputAudioTranscriptDelta,
            Grok.VoiceAgentAPIEvents.ResponseOutputAudioTranscriptDone,
            Grok.VoiceAgentAPIEvents.ResponseOutputAudioDelta, // Not in enum
            Grok.VoiceAgentAPIEvents.ResponseOutputAudioDone,
            Grok.VoiceAgentAPIEvents.ResponseOutputItemDone,
            Grok.VoiceAgentAPIEvents.ConnectorInformation,
            Grok.VoiceAgentAPIEvents.InputAudioBufferCommitted,
            Grok.VoiceAgentAPIEvents.WebSocketError,
            Grok.VoiceAgentAPIEvents.Unknown,
        ].forEach((evtName) => {
            voiceAIClient.addEventListener(evtName, (e) => {
                Logger.write(`===${e.name}===>${JSON.stringify(e)}`);
            });
        });

        voiceAIClient.addEventListener(Grok.Events.WebSocketMediaEnded, (event) => {
            Logger.write(`===${event.name}===>${JSON.stringify(event.data)}`);
            if (hangupCall) callCloseHandler();
            else if (forwardToLiveAgent) {
                call.say("Here is where I would forward the call via the phone network, SIP, or WhatsApp.");
                // See the forwardCallToPSTN, forwardCallToSIP, forwardCallToUser, and  handleBlindTransfer call methods
                // For this simple demo, we will just close and hang-up
                call.addEventListener(CallEvents.PlaybackFinished, callCloseHandler);
            }
        });
    } catch (error) {
        Logger.write("===SOMETHING_WENT_WRONG===");
        Logger.write(error);
        VoxEngine.terminate();
    }
});

```