Skip to content

Prompt System

The AI receptionist's system prompt is built from a Firestore template + business data. This doc explains the full pipeline.

Pipeline

Firestore template          Business document          Session context
(config/prompts/templates)  (businesses/{uid})          (channel, callerPhone, etc.)
        │                          │                          │
        └──────────┬───────────────┘──────────────────────────┘

         buildPromptContext()   ← prompt.js: builds context object from biz data


         renderPrompt()        ← promptService.js: fetches template, interpolates {{vars}}


         Final system prompt   → sent to OpenAI Realtime / Chat Completions

Template Source

Templates live in Firestore at config/prompts/templates/{templateId}. The main template is receptionist.

Templates are seeded from docs/prompts/receptionist.md via scripts/seed-prompts.mjs. Editing the markdown file alone does nothing — you must re-run the seed script to push changes to Firestore.

The admin UI (AdminPrompts.tsx) can also edit templates directly in Firestore.

There is no fallback. If the Firestore template is missing, the API throws. Seed with:

bash
GOOGLE_APPLICATION_CREDENTIALS=path/to/key.json node scripts/seed-prompts.mjs

Template Variables

The template uses placeholders. The buildPromptContext() function in prompt.js produces the context object:

VariableSourceNotes
nameai.aiNameFalls back to "the receptionist"
businessNameprofile.nameFalls back to vertical terminology
toneai.tone
greetingai.greeting
triageRulesVertical configIndustry-specific safety rules (e.g. medical triage)
calendarInstructionsBuilt conditionallyOnly if Google Calendar is connected. Includes verification flow instructions that vary by ai.callerVerification level and channel (phone vs web).
contactInfoprofile.phone/fax/email/website/address
locationsprofile.locations[]
practitionersprofile.practitioners[]Includes qualifications, specialties, bio
hoursprofile.hours[]Open days only
firstVisitInfoprofile.firstVisitInfo[]
bookingRequirementsprofile.bookingReferral, required fields, instructions
feesprofile.feesConsultation fees, payment methods, Medicare info
faqsknowledge[]Q&A pairs
customPromptai.customPromptFree-form instructions appended to prompt
escalationescalation[]Generates tool-use instructions per escalation rule
callControlConditionalPhone-only. Rules for handling silence, filler sounds, goodbye, abusive callers.
sessionInfoConditionalCaller phone number (from Twilio) and return caller name if recognized.

Unused in the template resolve to empty string (not an error).

Two Prompt Endpoints

GET /api/prompt — used by the browser voice client (VoiceGPT.tsx)

  • Auth: business owner's Firebase ID token
  • Business ID: from token's uid claim
  • No session context (no caller phone, no channel flag)

GET /api/portal/prompt — used by the portal chat (ChatGPT.tsx)

  • Auth: any authenticated user (visitor or owner)
  • Business ID: from ?businessId= query param
  • Side effects: sets visitor custom claim if user has no role, writes to visitors/{uid}/businesses/{bizId}

Caching

promptService.js caches Firestore reads (templates and tool docs) in memory with a 60-second TTL. Changes to templates take up to 60s to take effect on a running API instance.