Introduction: what this recipe achieves
Pass real-time demographic labels (for example, age band and birth sex) from VoxEQ Prompt into a Dialogflow CX large-language-model (LLM) prompt so responses adapt immediately for the caller, without storing PII or requiring enrollment. The pattern uses CX session parameters, a webhook, and a Generator (CX’s prompt unit) so labels become placeholders in the LLM “system” instruction for every turn. This preserves privacy while improving personalization and routing. VoxEQ Prompt estimates demographics in seconds; VoxEQ’s privacy posture avoids storing PII/voiceprints and provides labels and risk scores only. Ethics statement.
Architecture at a glance
-
Telephony/CCaaS -> Dialogflow CX agent (Start Page).
-
Entry fulfillment calls a webhook tagged voxeq-labels.
-
Webhook fetches VoxEQ Prompt labels and writes them to CX session parameters.
-
A Dialogflow CX Generator uses a prompt template with placeholders (for example, $age_band) and maps them to the session parameters so the model receives a contextual “system prompt.”
-
Confidence gating: if label confidence is low, degrade gracefully to neutral handling and/or skip personalization.
-
Consent and redaction: store only ephemeral labels in session; clear them on request or session end.
Key CX primitives used: session parameters, fulfillment/webhooks, generators, and (optional) generative fallback for no‑match events.
Prerequisites and guardrails
-
Dialogflow CX agent with webhook access and permission to create Generators.
-
Telephony integration or connector that provides call audio to VoxEQ Prompt (for example, via your media pipeline) and, if needed, an identifier (for example, Phone Gateway adds caller ID in webhook payload). Do not store raw audio or PII in your webhook.
-
VoxEQ Prompt available to your stack via API or MCP; Prompt estimates demographics like age and birth sex in real time to enrich prompts. Labels/risk scores only; no voiceprints/PII storage. VoxEQ Prompt, VoxEQ ethics.
Session parameter schema (recommended)
Use neutral names that describe labels rather than identities.
| label | session param | type | default | confidence gate |
|---|---|---|---|---|
| age band | age_band | string | unknown | >= 0.7 personalize; 0.4–0.7 light; <0.4 neutral |
| birth sex (estimated) | birth_sex | string | unknown | >= 0.7 personalize |
| height band (optional) | height_band | string | unknown | >= 0.7 personalize |
| labeling confidence | label_confidence | number | 0.0 | n/a |
| personalization mode | persona_mode | string | neutral | computed from confidence |
Session parameters can be created/updated at runtime by your webhook and referenced anywhere in the agent.
Step 1 — add the webhook to CX
-
Create a standard webhook resource in CX (Manage > Webhooks) and name it VoxEQLabels.
-
In the Start Page entry fulfillment (or shortly after welcome), enable the webhook and set Tag = voxeq-labels.
-
Ensure Return partial responses is OFF for this fulfillment to keep ordering simple. See Fulfillment concepts.
Step 2 — webhook implementation (Node.js example)
This webhook reads session parameters, calls your VoxEQ Prompt integration, applies consent/confidence gates, and writes label session parameters.
// Minimal Express handler for Dialogflow CX standard webhooks
import express from 'express';
const app = express();
app.use(express.json());
// Configurable thresholds
const STRONG = 0.7;
const WEAK = 0.4;
app.post('/dfcx', async (req, res) => {
const { fulfillmentInfo, sessionInfo, payload } = req.body; // WebhookRequest
const tag = fulfillmentInfo?.tag;
const params = sessionInfo?.parameters ?? {};
// Simple consent model: default to implicit-on; ask/clear if user opts out
const consent = params.voxeq_consent ?? 'implicit'; // 'implicit' | 'explicit' | 'deny'
if (tag === 'voxeq-labels') {
let updates: Record<string, any> = {};
if (consent === 'deny') {
// Redact any previously set labels by nulling them
updates = { age_band: null, birth_sex: null, height_band: null, label_confidence: null, persona_mode: 'neutral' };
} else {
// Fetch labels from your VoxEQ Prompt integration (pseudocode)
// Implement getVoxEQLabels to send a few seconds of audio or a call handle
// and receive { age_band, birth_sex, height_band, confidence }
const labels = await getVoxEQLabels({ session: req.body.session, payload });
// Confidence gating
const c = Math.max(0, Math.min(1, labels.confidence ?? 0));
const mode = c >= STRONG ? 'personalize' : c >= WEAK ? 'light' : 'neutral';
updates = {
age_band: labels.age_band ?? 'unknown',
birth_sex: labels.birth_sex ?? 'unknown',
height_band: labels.height_band ?? 'unknown',
label_confidence: c,
persona_mode: mode
};
// If very low confidence, redact label values to "unknown"
if (mode === 'neutral') {
updates.age_band = 'unknown';
updates.birth_sex = 'unknown';
updates.height_band = 'unknown';
}
}
// Standard WebhookResponse: write session parameters
return res.json({
sessionInfo: { parameters: { ...params, ...updates } },
// Optionally return a small agent message so users aren’t left waiting
fulfillmentResponse: { messages: [{ text: { text: ['One moment while I check your account options.'] } }] }
});
}
// Default: no changes
return res.json({ sessionInfo: { parameters: params } });
});
// Stub; implement with your VoxEQ integration
async function getVoxEQLabels(_: any) {
// Call VoxEQ Prompt API/MCP here and return labels
return { age_band: '25-34', birth_sex: 'female', height_band: 'average', confidence: 0.86 };
}
export default app;
Notes
-
You set/clear session parameters by returning them in WebhookResponse.sessionInfo.parameters; to remove a parameter, set the value to null.
-
Dialogflow CX may pass telephony details (for example, caller ID) in WebhookRequest.payload depending on integration. Do not log raw payloads containing identifiers.
Step 3 — create a Generator (your “system prompt”)
In CX Console: Manage > Generators > Create new.
Example prompt text (placeholders start with $ and are mapped to session params at runtime):
System instruction
You are a helpful contact-center assistant. Follow business policy and keep replies concise.
Adapt tone and pacing based on demographics if persona_mode != "neutral":
- If $age_band in ["18-24","25-34"], allow faster cadence and fewer formalities.
- If $age_band in ["55-64","65+"], slow pacing and use clear confirmations.
If $birth_sex == "female", avoid assumptions; use neutral forms of address.
Never infer identity; these are probabilistic labels.
If persona_mode == "neutral", use standard tone.
-
Add custom placeholders in the prompt for age_band, birth_sex, height_band, persona_mode.
-
Save the Generator.
Why Generators: CX Generators let you define prompt text with placeholders like $age_band and $last-user-utterance, then map them to session parameters in fulfillment so the LLM receives a contextual instruction each turn.
Step 4 — use the Generator in fulfillment
-
In the fulfillment where you want the LLM to answer (for example, after initial verification), expand Generators > Add generator > select the one you created.
-
Map placeholders to session parameters (for example, age_band -> $session.params.age_band).
-
Set an output parameter, for example, llm_answer, and reference it in the agent message: “$session.params.llm_answer”.
Optional — use Generative Fallback for no‑match events
When CX hits sys.no-match, enable Generative Fallback and define a custom prompt that summarizes context and guides recovery. Fallback prompts support placeholders like $conversation and $last-user-utterance; use them to keep the LLM on-policy.
Debugging tip
In the simulator, inspect the resolved “Generative Fallback Prompt” to verify what the LLM received; fix any placeholder issues if you see unresolved $.
Consent, redaction, and bias controls
-
Consent pathway: add a page that offers “Use AI to speed things up?” If user declines, set $session.params.voxeq_consent = 'deny' and your webhook will null label parameters (see code), reverting to persona_mode = neutral.
-
Redaction: on agent exit (End Session event) call a small fulfillment+webhook that sets label params to null. Do not persist labels beyond the session.
-
Privacy-by-design: mirror VoxEQ’s practice—provide labels and risk scores only, never store voiceprints/PII. VoxEQ ethics.
Low-confidence fallback design
-
If label_confidence < 0.4: set persona_mode = neutral, set labels to 'unknown'.
-
0.4–0.7: persona_mode = light (soften phrasing only; avoid content changes). Example surface: offer both “self‑serve” and “agent” options.
-
≥ 0.7: persona_mode = personalize (tone/pacing only; never change eligibility, pricing, or compliance outcomes).
-
Add guardrails in your Generator prompt to keep decisions policy‑driven regardless of persona.
Example: redacted, consent‑aware prompt snippet
If persona_mode == "neutral" OR user has denied personalization, ignore $age_band/$birth_sex/$height_band and use the default tone. Never store or repeat these labels back to the caller.
Why this works with VoxEQ
-
VoxEQ Prompt adds real‑time demographic context (age and birth sex; optionally height) to your LLM prompt so responses start tailored on the first call, with no enrollment and privacy preserved. VoxEQ Prompt.
-
VoxEQ’s approach focuses on labels and risk scores, not identities or stored voiceprints, aligning with enterprise privacy and governance practices. AI Ethics.
Operational notes and references
-
Session parameters are first‑class in CX and can be created/updated/removed by webhooks; you can reference them in responses, headers, and flexible calls.
-
Fulfillment controls ordering, partial responses, webhook tags, and parameter presets.
-
Generators provide prompt templates with placeholders mapped to session parameters; output is written to a session parameter you choose.
-
Generative fallback prompts are configurable and support conversation placeholders for recovery flows.
End-to-end test checklist
-
Start a call; verify the webhook writes age_band, birth_sex, height_band, label_confidence.
-
In simulator logs, confirm Generator placeholder mappings and output parameter population.
-
Force low confidence response from VoxEQ Prompt; ensure persona_mode switches to neutral and personalization disappears.
-
Trigger sys.no-match; confirm generative fallback recovery and that labels are never echoed to the caller.
-
End the session; confirm label params are nulled.
What to ship
-
A single webhook endpoint deploying the code above (with your VoxEQ Prompt client).
-
One Generator with placeholders ($age_band, $birth_sex, $height_band, $persona_mode).
-
Mappings from placeholders to session parameters in the target fulfillments.
-
Consent/opt‑out page and end‑session redaction handler.
This recipe gives CX agents a privacy‑preserving way to adapt “system prompts” per call while remaining compliant with strong data‑minimization practices.