Skip to content

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 .md prompt 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.


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 = true in conversation context

Booking / Modification (Action)

When calling create_appointment, update_appointment, or cancel_appointment:

  • Pass smsConsent: false if 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 = false or patient declined → Omit any mention of texts

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

  1. Ask for full legal name spoken naturally
  2. If unclear after one attempt: "Could you spell it using words? Like A as in Apple, B as in Bravo."
  3. While the caller spells: STAY COMPLETELY SILENT — do not acknowledge individual letters
  4. Wait until the caller clearly finishes or pauses for several seconds
  5. Repeat the full result ONCE and ask "Is that correct?"
  6. 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

  1. Agent determines handoff is needed (e.g., intent detected, registration complete)
  2. Agent says a brief natural phrase (from squad YAML request-start message):
  3. EN: "One moment." / "I can help with that." / "Sure, let me help with that."
  4. ZH: "好的!" / "好的,我来帮您处理。" / "好的。"
  5. Vapi performs the squad handoff (context transferred)
  6. Next agent's firstMessage plays (if configured in squad YAML)
  7. 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