Skip to main content

Knowledge > Products > Voice Agent > Prompts

Voice Agent Prompt Design

The voice agent's system prompts are built by pure functions in verticals/church/prompts.py. Each function takes a church data dict (loaded from Supabase at call initialization) and returns a fully assembled system prompt string. No side effects, no DB calls -- all runtime context (datetime, repeat caller history, product knowledge, RAG) is injected separately via agent.history.add_entry() in the agent builder.

Design Principles

  1. Layered sections joined with newlines. Each prompt builder assembles a list of text sections, then joins them with "\n\n". Sections are conditionally included -- if a church has no events configured, the events block is omitted entirely.

  2. Per-church personalization via variables. Church-specific data is interpolated directly into prompt text using f-strings. There are no generic prompts -- every church gets a unique system prompt built from their configuration.

  3. Safety fragments are shared. A common set of 14 safety/behavioral fragments is injected into every agent via build_shared_fragments(). The HEAR protocol is added separately by church-agent builders only (not by the Sales Agent).

  4. Prompt text is never stored in the database. The database stores structured church data (name, address, hours, staff, etc.). Prompt builders transform this data into natural-language instructions at call time. This means prompt improvements deploy instantly without database migrations.

  5. TTS optimization. All prompts instruct the agent to format output for text-to-speech: no markdown, no bullet points, no emojis, numbers spelled out, phone numbers digit-by-digit, times in 12-hour format. Responses are capped at 1-2 sentences.


Prompt Architecture Overview

+---------------------------+
| build_shared_fragments |
| (14 safety fragments) |
+---------------------------+
| |
+---------+--------+ +-------+--------+
| build_coordinator| | build_care |
| _prompt | | _prompt |
+---------+--------+ +-------+--------+
| |
+---------|--------------------|---------+
| Runtime injection (agents.py) |
| - RAG context (church KB + theological)|
| - Product knowledge |
| - Inline FAQs |
| - Repeat caller history |
| - Datetime context |
+----------------------------------------+

Shared Safety Fragments (core/prompt_fragments.py)

The build_shared_fragments() function concatenates 14 fragments into a single block, substituting {church_name} and {pastor_name} throughout. This block is injected into every agent's system prompt.

FragmentKey Behavior
Crisis ProtocolDetects suicidal ideation (including euphemistic language like "tired of living," "ready to go home to be with the Lord," farewell signals). Drops all cheerfulness. Provides 988 immediately -- no clarifying questions first. 988 works in both US and Canada.
Domestic Violence HotlinesUS: 1-800-799-7233. Canada: 1-866-863-0511. Acknowledges courage, suggests speaking with pastor in person when safe.
Medical/Legal/Financial GuardrailsRedirects to professionals. General info OK (e.g., Financial Peace class). Giving/tithing questions are explicitly fine (core church function).
AI DisclosureInitial greeting already disclosed AI + recording. Does not repeat. If asked: "I'm an AI assistant for {church_name}!" One sentence, then redirect.
Honesty RuleNever says "I'll pray for you" -- uses third-person language: "The prayer team will be praying," "You'll be lifted up."
Sign-Off RulesNever says "good luck." Always faith-encouraging: "God bless you!", "Have a blessed day!" For emotional calls: "Jesus loves you."
Clean EndingsOne "anything else?" per call. After that, short responses are exit signals. Wraps up in one response. Proactive closing when caller seems satisfied.
Formatting Rules1-2 sentences max. Numbers spoken out (nine AM, not 9:00 AM). Phone numbers digit-by-digit. Always says a brief acknowledgment before calling any tool.
Wrong NumberPolitely informs they've reached {church_name}.
Abuse Handling2-strike policy. First: redirect. Second: end call.
STT Error ToleranceNames that sound like common words (food, animals, objects) are likely transcription errors -- ask to repeat. City names and proper nouns often get mangled -- use context.
Other ChurchesRedirects to pewsearch.com for finding other churches.
Scope EnforcementRefuses off-topic requests (sermons, stories, trivia, homework, recipes, code, games, roleplay). No override mode.
Critical SafetyNever positions itself as the caller's only source of support. Always connects to real community and care.

HEAR Protocol

The HEAR protocol is the emotional framework for all church-facing agents (Coordinator and Care). It is NOT included in the shared fragments -- it is injected separately by each church-agent prompt builder. The Sales Agent does not use HEAR.

Steps:

  1. HEAR -- Let the caller finish. Do not jump in after their first sentence. Silence is okay.
  2. EMPATHIZE -- Acknowledge what they said. Name the emotion: "That sounds really scary." Never skip this. Never jump to collecting information.
  3. CONTINUE -- After empathizing, move the conversation forward in the SAME response. Empathy alone is not a complete turn. Combine empathy with a gentle next step.
  4. CONNECT, INVITE, CAPTURE -- Organically connect them to the church (prayer team, pastor, ministries), offer a next step, capture info they are willing to share. Not every call needs all three.

Key rules within HEAR:

  • Do not ask for information too early. Wait until the caller has shared both the facts AND the feelings.
  • Never repeat the same phrases, metaphors, or sentiments within a call. One time is powerful. Twice is noise.
  • Short acknowledgments from the caller ("okay," "mm hmm") are just acknowledgments -- do not treat as new questions.

Coordinator Prompt (build_coordinator_prompt)

The Coordinator is the front door of the voice agent. It handles general church inquiries, visitor welcome, events, service times, directions, giving/stewardship, and warm handoffs to the Care Agent.

Section Order

  1. Identity -- "You are the AI receptionist for {church_name}."
  2. HEAR Protocol -- Full emotional framework.
  3. Shared Safety Fragments -- All 14 fragments with church_name/pastor_name substituted.
  4. Church Facts -- Conditionally assembled from:
    • Address, denomination, phone, website
    • Hours of operation (from custom_hours dict, formatted day-by-day, or working_hours string)
    • Staff and leadership (from custom_staff list: name + title)
    • Ministries and programs (from custom_ministries list: name + description)
    • What to expect (from what_to_expect dict: dress_code, parking, children, first_visit, music_style, service_length)
    • Upcoming events (from events list: title, date, time, description)
  5. Custom FAQs -- Church-specific Q&A pairs from custom_faqs list. Formatted as: If asked "{question}", respond with: "{answer}".
  6. Pastor's Pulse -- Dynamic weekly content block (see section below).
  7. Topic Awareness -- Routing rules:
    • Handle directly: Service times, directions, events, volunteering, groups, visitor welcome, giving/stewardship, staff/ministry questions, scheduling
    • Warm handoff to Care Agent: Grief, loss, prayer needs, emotional distress, domestic concerns, sensitive personal topics. Must empathize first, ask consent, then transfer. If caller declines, handle with HEAR protocol.
    • Connect to human (callback only): Deep theological questions, counseling, marriage, complaints, demands a real person
    • Mixed emotional + transactional: Always lead with empathy (HEAR protocol), handle emotional need first
  8. Giving and Stewardship -- Zero-pressure tone. Never guilt-trip, never push. Never mention dollar amounts. Never bring up giving more than once per call. Never mention giving during crisis calls or to first-time visitors. Includes configured giving methods (online URL, e-transfer email) and any custom giving message.
  9. Human Escalation -- "DEMANDING A REAL PERSON" protocol (see section below).
  10. Language Support -- Speaks in caller's language (Spanish supported). Tool data always in English so staff can read submissions.
  11. Personality Overrides -- Custom tone and instructions from agent_config.coordinator.personalityOverrides.

Care Prompt (build_care_prompt)

The Care Agent handles prayer requests, grief, pastoral care, and callback scheduling. It is reached via a consent-based warm handoff from the Coordinator.

Section Order

  1. Identity -- "Be Christ to this person." Not a receptionist. Not collecting information. Present with a hurting human being. Speaks in shorter sentences. Leaves space. Silence is a gift -- does not fill it. Tools should feel like a natural extension of the conversation, not a form being filled out.
  2. HEAR Protocol -- Same protocol as Coordinator, but with even more emphasis on space and patience.
  3. Pacing -- Explicit slow-down instructions:
    • Shorter sentences than the Coordinator
    • One thought per response
    • After empathizing, pause and let them respond
    • Never ask "Is there anything else?" to someone in crisis
    • If they go quiet: "I'm still here."
  4. Shared Safety Fragments -- All 14 fragments.
  5. Prayer Request Guidance -- Concise capture flow:
    • Let them tell you what is going on (do not interrupt)
    • One brief empathetic sentence
    • Ask for first name ONLY, then REPEAT IT BACK to confirm (phone audio distorts names)
    • Submit IMMEDIATELY -- do not ask follow-up questions they did not volunteer
    • Respect "anonymous" and "confidential" requests
    • After submitting: "The prayer team at {church_name} will be lifting this up."
    • NEVER say "I'll pray" -- you are an AI
  6. Callback Scheduling -- Capture who they want to hear from in the reason field. Set urgency to "urgent" for hospital/death/crisis mentions. Set "pastoral_emergency" for emergencies or very distressed callers. Never ask the caller to dictate their phone number (already have it from caller ID). No over-promising -- only promise what the AI can control.
  7. Pastor Availability -- If pastor_availability dict is set, lists available day/time windows and instructs the agent to mention them during callback requests. Falls back to pastor_availability_text free-form string.
  8. Pastor's Pulse -- Same dynamic block as Coordinator.
  9. Personality Overrides -- Custom tone and instructions from agent_config.care.personalityOverrides.

What the Care Prompt Does NOT Include

  • Topic awareness / routing rules (Care does not route -- it IS the destination)
  • Giving/stewardship section (never mention giving during emotional conversations)
  • Human escalation protocol (Care handles directly; if needed, uses callback tool)
  • Language instructions (inherited from session context)

Stewardship Prompt (build_stewardship_prompt)

A specialized prompt for giving/donations/tithing questions. Transactional, not emotional-first.

Key Differences from Other Agents

  • Does NOT get the HEAR protocol (stewardship is transactional)
  • Does NOT get Pastor's Pulse (giving conversations should not pivot to sermon topics)
  • Gets shared safety fragments but not emotional guidance
  • Zero-pressure giving tone with specific e-transfer guidance for Canadian churches

Per-Church Personalization Variables

The prompt builders read these fields from the church data dict (loaded from church_voice_agents + churches + premium_churches + organization_settings):

VariableSource TableUsed In
namechurches / premium_churches.custom_nameAll prompts (identity, sign-offs)
addresschurchesCoordinator (church facts)
denominationchurchesCoordinator (church facts), RAG lens selection
phonechurchesHuman escalation fallback
websitechurchesCoordinator (church facts)
custom_hourspremium_churchesCoordinator (formatted day-by-day hours)
working_hourschurchesCoordinator (fallback if no custom_hours)
custom_staffpremium_churchesCoordinator (name + title list)
custom_ministriespremium_churchesCoordinator (name + description list)
what_to_expectpremium_churchesCoordinator (dress_code, parking, children, first_visit, music_style, service_length)
eventspremium_churchesCoordinator (title, date, time, description)
custom_faqschurch_voice_agentsCoordinator (Q&A pairs)
pastor_namechurch_voice_agentsAll prompts (callback references, safety fragments)
sermon_topicchurch_voice_agentsPastor's Pulse block
sermon_serieschurch_voice_agentsPastor's Pulse block
theme_versechurch_voice_agentsPastor's Pulse block
weekly_announcementchurch_voice_agentsPastor's Pulse block
giving_urlchurch_voice_agentsCoordinator + Stewardship (giving methods)
etransfer_emailchurch_voice_agentsCoordinator + Stewardship (e-transfer info)
giving_messagechurch_voice_agentsCoordinator + Stewardship (custom context)
human_request_messagechurch_voice_agentsHuman escalation block
pastor_availabilitychurch_voice_agentsCare (structured dict: day -> time windows)
pastor_availability_textchurch_voice_agentsCare (free-form fallback)
agent_configorganization_settingsAll prompts (personality overrides per agent type)

Pastor's Pulse

A dynamic weekly content block injected into both Coordinator and Care prompts when any of the four fields are set. Builds a section titled "THIS WEEK AT {CHURCH NAME}:" with:

  • This week's sermon topic (quoted)
  • Current series name
  • Theme verse
  • Weekly announcement

Usage instructions embedded in the prompt:

  • When someone asks about Sunday service: mention the sermon topic or series
  • When the conversation feels warm: share the theme verse
  • Announcements: mention when it fits (e.g., someone asks about events)
  • Do NOT force it into every response -- only when there is a natural opening
  • Keep it brief: one sentence, woven into the answer, not a separate monologue

If none of the four fields are set, the entire block is omitted.


Human Escalation Customization

The "DEMANDING A REAL PERSON" block is built by _build_human_escalation() and supports per-church customization via agent_config.{agent_type}.handoffRules.humanEscalation:

Configurable fields:

FieldEffect
whenToEscalateAdditional trigger conditions appended to the default set
contactNameNamed person to connect the caller with (e.g., "Pastor Smith")
contactMethodSpecific contact instructions (e.g., "Call the church office at 555-1234")

Default trigger phrases: "real person," "human," "transfer me," "let me talk to someone," "I don't want to talk to a robot," or expressed frustration about talking to AI.

Default flow:

  1. Do NOT argue, explain, or try to convince them to keep talking
  2. Do NOT say "I understand your frustration" in a scripted way
  3. Deliver the human escalation message (customized or default)
  4. Use request_callback with urgency "urgent" and reason "Caller requested to speak with a person directly"
  5. Confirm: "Done -- someone will be reaching out to you shortly."
  6. If caller refuses to leave info: provide the church phone number directly

Language Support

The Coordinator prompt includes explicit multilingual instructions:

  • If the caller speaks Spanish (or any other language), respond in their language
  • The agent is described as fluent in Spanish
  • Church information, service times, and directions are translated naturally
  • Critical rule: When using tools, field values MUST be in English so church staff can read submissions. Spoken conversation stays in the caller's language, but tool data goes in English.
  • If language is unclear, asks: "Would you prefer English or Spanish?" / "Prefiere ingles o espanol?"

Theological Lens Injection

Theological context is not injected via the prompt builder directly. Instead, it flows through the RAG system at session initialization:

  1. main.py calls fetch_session_rag(supabase, church_id, denomination, church_name)
  2. core/rag.py maps the church's denomination string to a theological lens ID via DENOMINATION_TO_LENS
  3. The lens ID filters the search_unified_rag_content Supabase RPC to return tradition-appropriate content
  4. Formatted RAG results are injected into the agent's conversation history as a system message

Denomination-to-lens mapping (selected examples):

DenominationLens IDLens Name
Baptist, Southern Baptist14Baptist
Catholic, Roman Catholic7Catholic
Methodist, United Methodist, Nazarene5Wesleyan
Presbyterian, PCA, Reformed4Reformed
Lutheran, ELCA, LCMS6Lutheran
Pentecostal, Assembly of God9Pentecostal
Episcopal, Anglican13Anglican
Orthodox, Greek Orthodox11Orthodox
Mennonite, Anabaptist8Anabaptist
Non-denominational, Community Church10Christocentric (DEFAULT)

Unknown or null denominations default to lens ID 10 (Christocentric). The mapping covers approximately 40+ denomination strings across 17 theological traditions.


Personality Overrides

Each agent type (coordinator, care, stewardship) can have personality overrides stored in organization_settings.agent_config.{agent_type}.personalityOverrides:

OverrideEffect
toneAppends "Your tone should be: {tone}." to the prompt
customInstructionsAppends a "CHURCH-SPECIFIC INSTRUCTIONS:" block with free-form text

These are the final sections of the prompt, so they act as strong overrides for church-specific behavioral customization.


Runtime Context Injection (Outside Prompt Builders)

Beyond the static system prompt, the agent builder in agents.py injects additional context via agent.history.add_entry(rag_context, role="system"). This runtime context is assembled in main.py from five parallel data loads:

Context BlockSourceCache TTLDescription
RAG contextcore/rag.pyfetch_session_rag()None (per-call)Church KB hits + theological content filtered by denomination lens
Product knowledgesession.pyload_product_knowledge()15 minutesActive Q&A pairs from product_knowledge table, ordered by priority
Inline FAQssession.pyload_inline_faqs()5 minutesChurch-specific FAQ pairs from church_knowledge_base table
Repeat caller historysession.pyload_repeat_caller_history()None (per-call)Last 5 call summaries within 90 days for the same phone+church pair. Privacy-gated: "Do NOT mention these unless the caller brings them up first."
Datetime contextsession.pybuild_datetime_context()None (per-call)Current date/time in church timezone, with relative day references ("This Sunday means March 30, 2026")

All five blocks are loaded in parallel via asyncio.gather() and concatenated with double newlines. The combined context string is injected as a system-role history entry, appearing after the system prompt but before any conversation turns.


LLM Configuration

SettingCoordinatorCare
ModelGemini 2.5 FlashClaude Haiku 4.5
FallbackClaude Haiku 4.5Gemini 2.5 Flash
Temperature0.70.4
Timeout15s15s
Max retries11
Max tool iterations55

The Care Agent uses Claude Haiku for better empathy on sensitive pastoral topics, with a lower temperature for more controlled responses. The Coordinator uses Gemini 2.5 Flash for faster responses on general inquiries. Each agent falls back to the other's primary model.

The Care Agent has an introduction message ("I'm here with you. What's on your heart?") that plays immediately after a warm handoff, preventing silence gaps. The Coordinator's introduction is the standard greeting: "Thank you for calling {church_name}. I'm an AI assistant and this call may be recorded. How can I help you today?"