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

# 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.

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

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](inbound).

**⬇️ 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 in Voximplant [Secrets](/platform/voxengine/secrets) 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`.

<Info title="Caller ID is not always a stable user ID">
  Caller ID can be missing, blocked, spoofed, or shared (for example, a PBX).
</Info>

### 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.

<Info title="Keep history small">
  `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).
</Info>

## 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: VoxEngine.getSecretValue('DEEPGRAM_API_KEY'),
            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();
    }
});

```