Prompt Engineering¶
Voice agent prompt intelligence: tool ordering, emergency handling, consent, spelling, and booking workflows
Last Updated: 2026-03-09 (v4.3.0 — extracted from assistant
.mdprompt files)
Overview¶
The v3.0 squad's 9 agents are configured via Markdown prompt files in vapi-gitops/resources/assistants/. Each prompt encodes behavioral rules that go beyond simple conversation scripts — they define tool ordering dependencies, safety protocols, consent handling, and error recovery.
This page documents the prompt engineering intelligence that is not visible in the tool definitions or squad configuration.
| Source Files | Location |
|---|---|
| Router | resources/assistants/router-v3.md |
| Patient-ID EN/ZH | patient-id-en.md, patient-id-zh.md |
| Booking EN/ZH | booking-en.md, booking-zh.md |
| Modification EN/ZH | modification-en.md, modification-zh.md |
| Registration EN/ZH | registration-en.md, registration-zh.md |
Mandatory Tool Ordering¶
Prompts enforce strict tool-call sequencing. Violating these rules causes booking failures, hallucinated patient data, or missed collision checks.
TOOL ORDERING DEPENDENCIES (per agent)
Patient-ID:
search_patient_by_phone ──MUST precede──► Any patient-specific action
search_patient ──MUST precede──► transfer_call
(except EMERGENCY)
Booking:
find_earliest_appointment ──MUST precede──► Slot presentation
check_appointments ──MUST precede──► create_appointment
(collision check) (booking)
Modification:
check_appointments ──MUST precede──► update/cancel_appointment
(retrieve existing) (modify/cancel)
check_appointments ──MUST precede──► update_appointment
(collision check on new slot) (reschedule)
| Agent | Rule | Source |
|---|---|---|
| Patient-ID | MUST call search_patient before transfer_call. Only exception: emergency. |
patient-id-en.md:59-63 |
| Booking | MUST call check_appointments (collision check) before create_appointment |
booking-en.md:126-138 |
| Modification | MUST call check_appointments to retrieve existing appointments before any modify/cancel |
modification-en.md first turn |
| All agents | Say a brief wait phrase alongside every tool call — never call a tool in silence | booking-en.md:72-74 |
Emergency Keywords¶
All 9 agents detect emergency keywords and respond with an immediate 911 instruction. No clarifying questions, no patient lookup, no clinic mention. One message, then end call.
English Keywords (13)¶
Source: router-v3.md:44-50, replicated in all EN agent prompts
"chest pain", "cannot breathe", "can't breathe", "difficulty breathing",
"heart attack", "stroke", "seizure", "unconscious", "severe bleeding",
"choking", "emergency", "overdose", "suicidal"
Response: "This sounds like a medical emergency. Please hang up and call 911 immediately."
Chinese Keywords (12)¶
Source: router-v3.md:44-50, replicated in all ZH agent prompts
Response: "这听起来是紧急情况。请您立即挂断电话并拨打911。"
Collision Detection Workflow¶
Before booking any appointment, the Booking agent must check for existing appointments at the same time.
Source: booking-en.md:126-138
Patient agrees to slot
│
▼
┌──────────────────────────────────────┐
│ Call check_appointments: │
│ demographicId = patient ID │
│ startDate = selected date │
│ endDate = same date │
│ findAvailable = false │
│ (returns EXISTING bookings) │
└───────────┬──────────────────────────┘
│
┌──────┴──────┐
│ │
No collision Collision found
│ │
▼ ▼
Proceed to "You already have an
create_appt appointment at that time.
Would you like a
different slot?"
│
▼
find_earliest_appointment
with excludeDates filter
The same collision check applies during reschedule (modification-en.md:97-98): before confirming the new slot, check for overlapping appointments.
Visit Reason Mapping¶
The Booking agent maps patient-stated reasons to OSCAR appointment type codes and provider config visit reasons.
Source: booking-en.md:118-124
| Patient Says (EN) | Patient Says (ZH) | appointmentType | visitReason |
|---|---|---|---|
| "checkup", "general", "physical", "not sure" | "体检", "普通检查", "不确定" | B |
checkup |
| "follow-up", "results", "check results" | "复查", "看结果" | 2 |
follow_up |
| "pain", "illness", "specific complaint" | "不舒服", "疼痛", "生病" | 3 |
sick_visit |
| "prescription refill", "medication" | "配药", "续药" | P |
checkup |
| "referral", "specialist" | "转诊", "专科" | 3 |
consultation |
Default: B / checkup if unclear after one clarification attempt.
Server-side validation: appointmentType must be one of ['B', '2', '3', 'P'] or DB-configured values. Invalid values fall back to B.
SMS Consent UX¶
The opt-out SMS consent model is woven into three agent roles.
Source: patient-id-en.md:119-121, booking-en.md:154-162, modification-en.md:122-124
Patient-ID (Disclosure)¶
After identifying the patient, the agent delivers:
"This call is recorded for quality and scheduling purposes. We may also send you a text confirmation for any appointments. Let me know if you'd rather not receive texts."
- Patient says nothing or agrees →
smsConsent = true(default) - Patient declines → Agent notes
smsDeclined = truein conversation context
Booking / Modification (Action)¶
When calling create_appointment, update_appointment, or cancel_appointment:
- Pass
smsConsent: falseif patient declined during Patient-ID phase - Otherwise, omit or pass
smsConsent: true(opt-out default)
After tool response:
- If
smsSent = true→ "You'll get a text confirmation shortly." - If
smsSent = falseor patient declined → Omit any mention of texts
Consent Override¶
If patient changes their mind at any point during the call, the agent uses the most recent preference for the next tool call.
Spelling Protocol¶
Registration agents use a structured approach for name collection and verification.
Source: registration-en.md:75-78, 126-133
Flow¶
- Ask for full legal name spoken naturally
- If unclear after one attempt: "Could you spell it using words? Like A as in Apple, B as in Bravo."
- While the caller spells: STAY COMPLETELY SILENT — do not acknowledge individual letters
- Wait until the caller clearly finishes or pauses for several seconds
- Repeat the full result ONCE and ask "Is that correct?"
- If corrected, accept the final version
Patient-ID Name Confirmation¶
Source: patient-id-en.md:93-96
After caller provides name, repeat back: "Just to make sure I have it right — [name], is that correct?"
- YES → proceed to search
- NO or caller corrects/spells → use corrected name
Silent Handoff Pattern¶
No agent ever mentions "transferring", "assistant", "system", or any internal terminology. From the caller's perspective, the conversation flows naturally with brief pauses.
How It Works¶
- Agent determines handoff is needed (e.g., intent detected, registration complete)
- Agent says a brief natural phrase (from squad YAML
request-startmessage): - EN: "One moment." / "I can help with that." / "Sure, let me help with that."
- ZH: "好的!" / "好的,我来帮您处理。" / "好的。"
- Vapi performs the squad handoff (context transferred)
- Next agent's
firstMessageplays (if configured in squad YAML) - Next agent's LLM starts generating
The caller hears: brief phrase → slight pause → new agent's greeting. No "I'm transferring you to..." language.
Fallback Recovery¶
All agents follow the 3-attempt fallback rule.
Source: router-v3.md:85-87, patient-id-en.md:159-161
| Situation | After 3 unclear attempts |
|---|---|
| Router can't detect language | "Let me connect you with our staff." → transfer_call(reason: "out_of_scope") |
| Patient-ID can't identify patient | Same → transfer_call(reason: "record_not_found") |
| Booking/Modification errors | Same → transfer_call(reason: "out_of_scope") |
The transfer_call tool triggers a transfer-destination-request webhook, which routes to the clinic's configured staff phone number.
Prompt Design Principles¶
These principles are enforced across all 9 agent prompts:
| Principle | Implementation |
|---|---|
| One question per turn | Never ask two questions in the same response |
| Never confirm without tool result | "Never say 'booked' without calling the tool first and receiving success" |
| No hallucinated data | "WAIT for actual tool result before speaking about the patient" |
| Technical language ban | Never say "function", "tool", "API", "database", "system", "server", "webhook" |
| Date awareness | All prompts include {{now | date: ...}} Liquid template for current date/time |
| Clinic-agnostic | No hardcoded clinic names in prompts (P0 fix — all "Vitara" references removed) |
| Opt-out consent | SMS consent defaults to true; only set false when patient explicitly declines |
Related Documentation¶
- Squad Architecture — Agent topology, handoff matrix, voice config
- Agent Behaviors — Per-agent step-by-step behavior
- Tool Inventory — Tool parameters including
smsConsentandsmsSent - SMS Integration — Full SMS architecture and consent tracking