Dynamic Prompts Before the First Ring
Static prompts produce generic calls. Dynamic prompts produce conversations. Here's how Talkif assembles a personalized, context-aware prompt for every call — and why the person on the other end can tell the difference.
Every voice agent needs instructions. But static prompts break the moment you need personalization — a caller's name, their company, whether they're calling in or being called. Talkif solves this with a template resolution pipeline that assembles a context-aware prompt for every call, before the agent says a word.
The Problem With Static Prompts
Most voice AI setups start the same way: someone writes a system prompt, hardcodes it into an agent, and hits deploy. It works — until it doesn't.
The agent greets every caller the same way. It doesn't know who it's talking to. It can't reference a previous conversation, a company name, or a timezone. It asks questions it already has answers to. The caller notices. They disengage. The call fails — not because the AI was bad, but because it started without context.
This is the gap between a demo and a production voice agent. Demos sound impressive with generic prompts. Real calls need to know who's on the line.
The Template Layer
Every prompt in Talkif is a Handlebars template — not static text. When a call starts, the platform resolves that template against real data: who the contact is, why they're being called, what business is calling, and what time it is in their timezone.
Four namespaces are available at resolution time:
contact.*— name, email, company, timezone, language, notes, interests, tags, custom fieldscall.*— direction (inbound/outbound), caller and callee numbersaccount.*— your business name and identifiersystem.*— current date, time, and timezone
A template looks like this:
handlebarsYou are calling on behalf of {{default account.name "our office"}}
to confirm an upcoming appointment.
Address the contact as {{default contact.firstName "there"}}.
{{#if contact.email}}
Offer to send a confirmation email to {{contact.email}}.
{{/if}}
{{#if (includes contact.tags "vip")}}
This is a high-priority contact. Be especially attentive.
{{/if}}
{{#if contact.timezone}}
The contact's local time is based on {{contact.timezone}}.
Be mindful of their schedule.
{{/if}}
Current date: {{system.date}}The engine supports conditionals, comparisons (eq, ne, gt, lt), regex matching, array operations (includes, join), fallback defaults, and existence checks. Enough logic to handle real-world branching without turning prompts into unreadable code.
What Happens at Call Time
When a call is initiated — inbound or outbound — the backend assembles context from three sources before the agent receives any instructions:
-
Contact lookup. For inbound calls, the caller's phone number is matched against your contact database. For outbound calls, the contact ID is resolved directly. For campaign calls, a frozen snapshot of the contact's data — captured at enrollment time — is used to guarantee consistency across retries and rescheduled attempts.
-
Call and account metadata. Direction, phone numbers, and your business identity are injected automatically.
-
System clock. Current date and time in UTC, so the agent always knows "when" it is.
The Handlebars engine evaluates every expression, resolves every variable, and strips dead conditional branches. What comes out the other side is clean text — no template syntax, no unresolved placeholders. A prompt that reads like it was written for this specific call.
What This Changes for the Caller
The person on the other end of the call doesn't know about Handlebars templates. They don't care about your prompt engineering. What they notice is whether the agent knows who they are.
Without dynamic prompts, every call sounds like this:
"Hi, this is a call from our office. Can I get your name?"
With dynamic prompts, the same call sounds like this:
"Hi Sarah, this is Acme Dental calling to confirm your Thursday appointment. I see you prefer mornings — does 9 AM still work?"
And it happens in under one second. Template resolution runs in microseconds — there's no added latency from personalization. The agent picks up, greets the caller by name, and references their specific context without any perceptible delay. Dynamic content with no tradeoff on response time.
The agent didn't ask for a name it already had. It didn't fumble through a generic opener. It started with context and moved straight to value. That single difference — skipping the "who are you?" phase — changes the entire tone of the call. The caller feels recognized, not processed.
For inbound calls, the effect is even stronger. When someone calls your support line and the agent already knows their company, their timezone, and their notes from the last interaction — the conversation starts at step three instead of step one.
What This Changes for You
As a Talkif user, dynamic prompts eliminate an entire class of problems:
One flow, many contacts. You don't need a separate agent configuration for every customer segment. A single flow with well-written templates adapts to each contact automatically. A VIP tagged contact gets different treatment than a first-time caller — same flow, same template, different resolved prompt.
Campaigns that actually personalize. When you run an outbound campaign across 10,000 contacts, each call gets a prompt built from that contact's specific data. The agent references their name, their company, their notes. At scale, this is the difference between a robocall and a conversation.
Less prompt maintenance. Static prompts rot. A contact changes their company, you update the contact record, and the next call reflects it automatically. You're not hunting through prompt text to find hardcoded names.
Self-Healing Contact Resolution
Not every call has perfect data. Someone calls from a number you don't have on file. A contact record is missing an email. A custom field hasn't been filled in yet.
The template engine handles this gracefully at every level:
Fallback defaults. The default helper provides a natural substitute when data is missing:
handlebarsAddress the contact as {{default contact.firstName "there"}}.If the contact's name exists, the agent uses it. If not, it says "there" — no blank space, no "undefined", no crash.
Conditional blocks. The ifExists helper lets entire sections of the prompt appear or disappear based on what data is available:
handlebars{{#ifExists contact.company}}
They work at {{contact.company}}. Reference their business context.
{{/ifExists}}
{{#ifExists contact.notes}}
Previous interaction notes: {{contact.notes}}
{{/ifExists}}No company on file? That block doesn't exist in the resolved prompt. The agent never references something it doesn't have.
Phone-based fallback. When an inbound caller isn't in your contact database, the system still builds a context — with the phone number as the only known field. Your template degrades gracefully:
handlebars{{#if contact.name}}
You are speaking with {{contact.name}}.
{{else}}
The caller's number is {{call.fromNumber}}.
Ask for their name early in the conversation.
{{/if}}The agent's behavior adapts to data availability, not the other way around. You write one template that handles the full spectrum — from a rich CRM record to a completely unknown caller.
Campaign snapshots. For outbound campaigns, contact data is frozen at enrollment time. If a contact's record is updated mid-campaign, the call still uses the data that was current when the campaign was created. This prevents inconsistencies when a contact's name, company, or notes change between scheduling and dialing.
Use Cases
Appointment reminders. The agent knows the contact's name, timezone, and appointment details. It confirms or reschedules without asking for information the system already has.
Sales outreach. Prompts pull from contact notes, interests, and tags to shape the pitch. A contact tagged "enterprise" gets a different conversation than one tagged "startup." Same flow, different context.
Support triage. Inbound callers are matched by phone number. The agent sees their company, their language preference, and any notes from previous calls. Resolution starts faster.
Collections and follow-ups. Sensitive calls where knowing the contact's history matters. The agent references specific details without the caller having to repeat themselves.
Multilingual campaigns. The contact.language variable lets a single template branch into different behavioral instructions based on the contact's preferred language — without duplicating flows.
Why Templates, Not Runtime LLM Generation
An alternative approach: feed contact data into an LLM at call time and let it generate the prompt on the fly. We chose deterministic templates instead for three reasons.
Predictability. You see exactly what the agent receives. No drift between calls. No model hallucinating instructions you didn't write. The template is the contract.
Speed. Handlebars resolution takes microseconds. An LLM generation step adds seconds of latency before the agent can start processing. In voice, every millisecond of silence is a signal to the caller that something is wrong.
Auditability. Every resolved prompt is traceable to a template version plus the input data. You can reproduce exactly what any agent received on any call. For regulated industries, this isn't optional.
AI-Assisted Authoring
Writing Handlebars templates from scratch isn't always intuitive — especially when you have dozens of available variables and helpers. The Prompt Library includes an AI assistant that knows your schema.
Describe what you want in plain language. It generates a complete, valid template using only variables that actually exist in your account. The assistant enforces proper Handlebars syntax, avoids literal dialogue scripts, and supports multi-turn refinement. You stay in control of the final template — the AI just gets you there faster.