*** ## title: 'Example: Using Vertex AI' This example answers an inbound Voximplant call and connects Gemini Live API through Vertex AI. It separates the Vertex service account credentials into a dedicated scenario so you can keep them isolated and reuse them across routes. **⬇️ 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 Vertex parameters in Voximplant `ApplicationStorage`: * `GCP_PROJECT_ID` * `GCP_REGION` For full Vertex setup details, see: [https://voximplant.com/docs/voice-ai/google/vertex](https://voximplant.com/docs/voice-ai/google/vertex) To create a service account key (JSON), see: [https://docs.cloud.google.com/iam/docs/keys-create-delete](https://docs.cloud.google.com/iam/docs/keys-create-delete) ## Credentials scenario (separate route entry) Store the Vertex service account JSON in a **separate scenario** and include it **before** the main scenario in your routing rule. Routing rule scenario order: ``` gemini-vertex-credentials → gemini-using-vertex-ai ``` Vertex credentials JSON is typically too large for ApplicationStorage. VoxEngine shares global scope across scenarios in the same routing rule, so a credentials scenario can set a global variable for the main scenario to read. Example credentials scenario: ```javascript title={"voxeengine-gemini-vertex-credentials.js"} maxLines={0} /** * Voximplant + Gemini Live API connector demo * Scenario: load Vertex AI credentials for Gemini Live API (example only). * * Include this scenario BEFORE the main Vertex AI scenario in your routing rule. */ // eslint-disable-next-line no-unused-vars var GEMINI_VERTEX_CREDENTIALS = { type: "service_account", project_id: "your-gcp-project-id", private_key_id: "example-private-key-id", private_key: "-----BEGIN PRIVATE KEY-----\nREDACTED\n-----END PRIVATE KEY-----\n", client_email: "vertex-express@your-gcp-project-id.iam.gserviceaccount.com", client_id: "123456789012345678901", auth_uri: "https://accounts.google.com/o/oauth2/auth", token_uri: "https://oauth2.googleapis.com/token", auth_provider_x509_cert_url: "https://www.googleapis.com/oauth2/v1/certs", client_x509_cert_url: "https://www.googleapis.com/robot/v1/metadata/x509/vertex-express%40your-gcp-project-id.iam.gserviceaccount.com", universe_domain: "googleapis.com", }; // This will be global to the next scenarios in the routing rule sequence. ``` The example credentials are intentionally obfuscated and will not work. Create your own credentials scenario with your real service account JSON. ## Session setup The Gemini Live API session is configured via `connectConfig`, passed into `Gemini.createLiveAPIClient(...)`. In the full scenario, see `GEMINI_CONNECT_CONFIG`: * `responseModalities: ["AUDIO"]` asks Gemini to speak back in real time. * `apiVersion: "v1alpha"` matches the Vertex Live API endpoint. * `speechConfig` selects a prebuilt voice. * `systemInstruction` defines the assistant behavior. * `tools` and `toolConfig` enable function calling. The Vertex-specific parameters are passed directly to `Gemini.createLiveAPIClient(...)`: * `backend: Gemini.Backend.VERTEX_AI` * `project` → `GCP_PROJECT_ID` * `location` → `GCP_REGION` * `credentials` → the JSON string set by the credentials scenario ## Connect call audio After `Gemini.LiveAPIEvents.SetupComplete`, bridge audio between the call and Gemini: ```js title="Connect call audio" VoxEngine.sendMediaBetween(call, geminiLiveAPIClient); ``` The same handler sends a starter message to trigger the greeting: ```js title="Trigger the greeting" geminiLiveAPIClient.sendClientContent({ turns: [{ role: "user", parts: [{ text: "Say hello and ask how you can help." }] }], turnComplete: true, }); ``` ## Events The scenario logs Gemini events for debugging: * `Gemini.LiveAPIEvents`: `SetupComplete`, `ServerContent`, `ToolCall`, `ToolCallCancellation`, `ConnectorInformation`, `Unknown` * `Gemini.Events`: `WebSocketMediaStarted`, `WebSocketMediaEnded` ## Notes * This example uses the Vertex AI backend (`Gemini.Backend.VERTEX_AI`). * The credentials scenario only sets `GEMINI_VERTEX_CREDENTIALS` in the shared global scope and does not start any calls. [See the VoxEngine API Reference for more details](https://voximplant.com/docs/references/voxengine/gemini). ## Full VoxEngine scenario ```javascript title={"voxeengine-gemini-using-vertex-ai.js"} maxLines={0} /** * Voximplant + Gemini Live API connector demo * Scenario: answer an incoming call using Gemini Live API via Vertex AI. */ require(Modules.Gemini); require(Modules.ApplicationStorage); const SYSTEM_PROMPT = `You are Voxi, a helpful voice assistant for phone callers. Keep responses short and telephony-friendly (usually 1-2 sentences).`; // -------------------- Gemini Live API settings -------------------- const CONNECT_CONFIG = { responseModalities: ["AUDIO"], speechConfig: { voiceConfig: { prebuiltVoiceConfig: {voiceName: "Aoede"}, }, }, systemInstruction: { parts: [{text: SYSTEM_PROMPT}], }, inputAudioTranscription: {}, outputAudioTranscription: {}, }; VoxEngine.addEventListener(AppEvents.CallAlerting, async ({call}) => { let voiceAIClient; // Termination functions - add cleanup and logging as needed call.addEventListener(CallEvents.Disconnected, ()=>VoxEngine.terminate()); call.addEventListener(CallEvents.Failed, ()=>VoxEngine.terminate()); try { call.answer(); // call.record({hd_audio: true, stereo: true}); // optional: call recording voiceAIClient = await Gemini.createLiveAPIClient({ credentials: GEMINI_VERTEX_CREDENTIALS, // stored in a different scenario model: "gemini-live-2.5-flash-preview-native-audio-09-17", backend: Gemini.Backend.VERTEX_AI, // Set the Vertex back-end project: (await ApplicationStorage.get("GCP_PROJECT_ID")).value, // required for Vertex location: (await ApplicationStorage.get("GCP_REGION")).value, // required for Vertex connectConfig: CONNECT_CONFIG, onWebSocketClose: (event) => { Logger.write("===Gemini.WebSocket.Close==="); if (event) Logger.write(JSON.stringify(event)); VoxEngine.terminate(); }, }); // ---------------------- Event handlers ----------------------- // Wait for Gemini setup, then bridge audio and trigger the greeting voiceAIClient.addEventListener(Gemini.LiveAPIEvents.SetupComplete, () => { VoxEngine.sendMediaBetween(call, voiceAIClient); voiceAIClient.sendClientContent({ turns: [{role: "user", parts: [{text: "Say hello and ask how you can help."}]}], turnComplete: true, }); }); // Capture transcripts + handle barge-in voiceAIClient.addEventListener(Gemini.LiveAPIEvents.ServerContent, (event) => { const payload = event?.data?.payload || {}; if (payload.inputTranscription?.text) { Logger.write(`===USER=== ${payload.inputTranscription.text}`); } if (payload.outputTranscription?.text) { Logger.write(`===AGENT=== ${payload.outputTranscription.text}`); } if (payload.interrupted) { Logger.write("===BARGE-IN=== Gemini.LiveAPIEvents.ServerContent"); voiceAIClient.clearMediaBuffer(); } }); // Log all Gemini events for illustration/debugging [ Gemini.LiveAPIEvents.SetupComplete, Gemini.LiveAPIEvents.ServerContent, Gemini.LiveAPIEvents.ToolCall, Gemini.LiveAPIEvents.ToolCallCancellation, Gemini.LiveAPIEvents.ConnectorInformation, Gemini.LiveAPIEvents.Unknown, Gemini.Events.WebSocketMediaStarted, Gemini.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("===SOMETHING_WENT_WRONG==="); Logger.write(error); VoxEngine.terminate(); } }); ```