***
## 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();
}
});
```