*** ## title: 'Example: Context history with ApplicationStorage' This example answers an inbound call and uses `ApplicationStorage` to persist a small “memory” per caller across calls, then injects it into the next Deepgram Voice Agent session via `agent.context.messages`. For a full breakdown of session setup, media bridging, barge-in, and event handling, see [Example: Answering an incoming call](deepgram-voice-ai-example-answering-incoming-call). **⬇️ 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 Deepgram API key secret value in Voximplant `ApplicationStorage` under `DEEPGRAM_API_KEY`. ## How cross-call history works ### 1) Pick a user identity and storage key The example uses the inbound caller ID (`call.callerid()`) as a simple “user identity”, and stores history under a key like `dgva_history:+15550123456`. Caller ID can be missing, blocked, spoofed, or shared (for example, a PBX). ### 2) Load stored history and pass it to Deepgram On call start, the scenario reads the stored JSON array from `ApplicationStorage` and passes it directly to the agent: * `SETTINGS_OPTIONS.agent.context.messages`: prior turns to preload into the session ### 3) Append new turns and persist on hangup During the call, Deepgram emits `Deepgram.VoiceAgentEvents.History` events containing history items suitable for `context.messages`. The example appends those items to a `rollingHistory` array, trims it to a max size, and then saves it back to `ApplicationStorage` when the call ends. `ApplicationStorage` values are size-limited (up to 2000 characters per key), so store only what you need (for example last 10–20 items) and enforce a TTL to avoid unbounded growth. See [https://voximplant.com/docs/references/voxengine/applicationstorage#put](https://voximplant.com/docs/references/voxengine/applicationstorage#put). ## Notes [See the VoxEngine API Reference for more details](https://voximplant.com/docs/references/voxengine/deepgram). ## Full VoxEngine scenario ```javascript title={"voxeengine-deepgram-ctx-history.js"} maxLines={0} /** * Voximplant + Deepgram Voice Agent connector demo * Feature highlighted: CROSS-CALL CONTEXT HISTORY using ApplicationStorage + agent.context.messages */ require(Modules.Deepgram); require(Modules.ApplicationStorage); const HISTORY_TTL_SECONDS = 14 * 24 * 3600; // 2 weeks const MAX_HISTORY_ITEMS = 10; const SYSTEM_PROMPT = ` You are a helpful English-speaking voice assistant for phone callers. Keep your turns short and telephony-friendly (usually 1–2 sentences). If conversation history is present, start by briefly summarizing what the caller asked last time in 1 sentence, then ask how you can help. `; function safeParseJsonArray(value) { if (!value) return []; try { const parsed = JSON.parse(value); return Array.isArray(parsed) ? parsed : []; } catch (error) { void error; return []; } } VoxEngine.addEventListener(AppEvents.CallAlerting, async ({call}) => { let voiceAIClient; // Caller ID is used as a simple "user identity" for the demo. const callerId = call.callerid() || null; const historyKey = callerId ? `dgva_history:${callerId}` : null; let rollingHistory = []; async function saveHistory() { if (!historyKey) return; await ApplicationStorage.put(historyKey, JSON.stringify(rollingHistory), HISTORY_TTL_SECONDS); Logger.write("===CROSS_CALL_HISTORY_SAVED==="); Logger.write(JSON.stringify({callerId, messages: rollingHistory.length})); } async function terminate() { try { await saveHistory(); voiceAIClient?.close(); } catch (error) { Logger.write(`===CROSS_CALL_HISTORY_SAVE_ERROR===> ${JSON.stringify(error)}`); } VoxEngine.terminate(); } try { call.answer(); // -------------------- Load cross-call history -------------------- if (historyKey) { const stored = await ApplicationStorage.get(historyKey); rollingHistory = safeParseJsonArray(stored?.value); Logger.write("===CROSS_CALL_HISTORY_LOADED==="); Logger.write(JSON.stringify({callerId, messages: rollingHistory.length})); } else { Logger.write("===CROSS_CALL_HISTORY_DISABLED=== Missing caller ID"); } // -------------------- Deepgram Voice Agent settings -------------------- const SETTINGS_OPTIONS = { tags: ["voximplant", "deepgram", "voice_agent_connector", "cross_call_history_demo"], agent: { language: "en", greeting: "Hi! I'm Voxi. How can I help today?", context: { messages: rollingHistory, }, listen: { provider: { type: "deepgram", model: "flux-general-en", }, }, think: { provider: { type: "open_ai", model: "gpt-4o-mini", temperature: 0.6, }, prompt: SYSTEM_PROMPT, }, speak: { provider: { type: "deepgram", model: "aura-2-cordelia-en", }, }, }, }; // Create client and wire media voiceAIClient = await Deepgram.createVoiceAgentClient({ apiKey: (await ApplicationStorage.get("DEEPGRAM_API_KEY")).value, settingsOptions: SETTINGS_OPTIONS, }); VoxEngine.sendMediaBetween(call, voiceAIClient); call.addEventListener(CallEvents.Disconnected, () => { terminate(); }); call.addEventListener(CallEvents.Failed, () => { terminate(); }); // -------------------- Update rolling history -------------------- // Deepgram emits history items suitable for agent.context.messages. voiceAIClient.addEventListener(Deepgram.VoiceAgentEvents.History, (event) => { const item = event?.data?.payload; if (!item) return; rollingHistory.push(item); rollingHistory = rollingHistory.slice(-MAX_HISTORY_ITEMS); }); // Optional: log transcript voiceAIClient.addEventListener(Deepgram.VoiceAgentEvents.ConversationText, (event) => { const {role, text} = event?.data?.payload || {}; if (role && text) Logger.write(`===TRANSCRIPT=== ${role}: ${text}`); }); } catch (error) { Logger.write("===UNHANDLED_ERROR==="); Logger.write(error); terminate(); } }); ```