Example: Context history with ApplicationStorage

View as MarkdownOpen in Claude

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.

⬇️ Jump to the Full VoxEngine scenario.

Prerequisites

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 is not always a stable user ID

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.

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.

Notes

See the VoxEngine API Reference for more details.

Full VoxEngine scenario

voxeengine-deepgram-ctx-history.js
1/**
2 * Voximplant + Deepgram Voice Agent connector demo
3 * Feature highlighted: CROSS-CALL CONTEXT HISTORY using ApplicationStorage + agent.context.messages
4 */
5
6require(Modules.Deepgram);
7require(Modules.ApplicationStorage);
8
9const HISTORY_TTL_SECONDS = 14 * 24 * 3600; // 2 weeks
10const MAX_HISTORY_ITEMS = 10;
11
12const SYSTEM_PROMPT = `
13You are a helpful English-speaking voice assistant for phone callers.
14Keep your turns short and telephony-friendly (usually 1–2 sentences).
15
16If conversation history is present, start by briefly summarizing what the caller asked last time in 1 sentence, then ask how you can help.
17`;
18
19function safeParseJsonArray(value) {
20 if (!value) return [];
21 try {
22 const parsed = JSON.parse(value);
23 return Array.isArray(parsed) ? parsed : [];
24 } catch (error) {
25 void error;
26 return [];
27 }
28}
29
30VoxEngine.addEventListener(AppEvents.CallAlerting, async ({call}) => {
31 let voiceAIClient;
32
33 // Caller ID is used as a simple "user identity" for the demo.
34 const callerId = call.callerid() || null;
35 const historyKey = callerId ? `dgva_history:${callerId}` : null;
36 let rollingHistory = [];
37
38 async function saveHistory() {
39 if (!historyKey) return;
40 await ApplicationStorage.put(historyKey, JSON.stringify(rollingHistory), HISTORY_TTL_SECONDS);
41 Logger.write("===CROSS_CALL_HISTORY_SAVED===");
42 Logger.write(JSON.stringify({callerId, messages: rollingHistory.length}));
43 }
44
45 async function terminate() {
46 try {
47 await saveHistory();
48 voiceAIClient?.close();
49 } catch (error) {
50 Logger.write(`===CROSS_CALL_HISTORY_SAVE_ERROR===> ${JSON.stringify(error)}`);
51 }
52 VoxEngine.terminate();
53
54 }
55
56 try {
57 call.answer();
58
59 // -------------------- Load cross-call history --------------------
60 if (historyKey) {
61 const stored = await ApplicationStorage.get(historyKey);
62 rollingHistory = safeParseJsonArray(stored?.value);
63 Logger.write("===CROSS_CALL_HISTORY_LOADED===");
64 Logger.write(JSON.stringify({callerId, messages: rollingHistory.length}));
65 } else {
66 Logger.write("===CROSS_CALL_HISTORY_DISABLED=== Missing caller ID");
67 }
68
69 // -------------------- Deepgram Voice Agent settings --------------------
70 const SETTINGS_OPTIONS = {
71 tags: ["voximplant", "deepgram", "voice_agent_connector", "cross_call_history_demo"],
72 agent: {
73 language: "en",
74 greeting: "Hi! I'm Voxi. How can I help today?",
75 context: {
76 messages: rollingHistory,
77 },
78 listen: {
79 provider: {
80 type: "deepgram",
81 model: "flux-general-en",
82 },
83 },
84 think: {
85 provider: {
86 type: "open_ai",
87 model: "gpt-4o-mini",
88 temperature: 0.6,
89 },
90 prompt: SYSTEM_PROMPT,
91 },
92 speak: {
93 provider: {
94 type: "deepgram",
95 model: "aura-2-cordelia-en",
96 },
97 },
98 },
99 };
100
101 // Create client and wire media
102 voiceAIClient = await Deepgram.createVoiceAgentClient({
103 apiKey: (await ApplicationStorage.get("DEEPGRAM_API_KEY")).value,
104 settingsOptions: SETTINGS_OPTIONS,
105 });
106 VoxEngine.sendMediaBetween(call, voiceAIClient);
107
108 call.addEventListener(CallEvents.Disconnected, () => {
109 terminate();
110 });
111 call.addEventListener(CallEvents.Failed, () => {
112 terminate();
113 });
114
115 // -------------------- Update rolling history --------------------
116 // Deepgram emits history items suitable for agent.context.messages.
117 voiceAIClient.addEventListener(Deepgram.VoiceAgentEvents.History, (event) => {
118 const item = event?.data?.payload;
119 if (!item) return;
120
121 rollingHistory.push(item);
122 rollingHistory = rollingHistory.slice(-MAX_HISTORY_ITEMS);
123 });
124
125 // Optional: log transcript
126 voiceAIClient.addEventListener(Deepgram.VoiceAgentEvents.ConversationText, (event) => {
127 const {role, text} = event?.data?.payload || {};
128 if (role && text) Logger.write(`===TRANSCRIPT=== ${role}: ${text}`);
129 });
130 } catch (error) {
131 Logger.write("===UNHANDLED_ERROR===");
132 Logger.write(error);
133 terminate();
134 }
135});