Knowledge > Products > Voice Agent > Troubleshooting
Voice Agent Troubleshooting
Known issues, debugging procedures, and resolution steps for the ChurchWiseAI Voice Agent.
1. Calls Not Reaching the Agent (LiveKit SIP Routing)
Symptom: Calls fail to connect — callers hear silence, a busy signal, or the Twilio default "this number is not in service" message.
Cause: The Twilio SIP trunk is not correctly configured to forward to the LiveKit Cloud SIP gateway, or the Railway agent worker is not running.
Debugging steps:
- Check that the Railway service is running and healthy (Railway dashboard or
railway logs). - Check the LiveKit Cloud project (
cwa-voice-9x077mph) dashboard for active agent workers. - Verify the Twilio SIP trunk is forwarding to the correct LiveKit Cloud SIP gateway URL.
- Check
LIVEKIT_URL,LIVEKIT_API_KEY, andLIVEKIT_API_SECRETare set in Railway environment variables. - Check
voice_call_logs— if rows exist witherror_messageset, the agent is receiving the call but crashing. If no rows at all, the SIP routing is failing before the agent worker.
2. Agent Worker Not Starting on Railway
Symptom: Railway deploys successfully but the agent never answers calls. Railway shows the service as running but no logs from main.py.
Debugging steps:
- Check Railway logs for Python import errors or missing environment variable errors at startup.
- Verify all required environment variables are set in Railway:
LIVEKIT_URL,LIVEKIT_API_KEY,LIVEKIT_API_SECRETCARTESIA_API_KEY,DEEPGRAM_API_KEYSUPABASE_URL,SUPABASE_SERVICE_ROLE_KEYGEMINI_API_KEY,ANTHROPIC_API_KEY
- If the worker starts but immediately exits, check for a
livekit-agentsversion mismatch — pin tolivekit-agents~=1.5.
3. Health Check Failing on Railway
Symptom: Railway restarts the service repeatedly. Health check endpoint returns 404 or connection refused.
Cause: The FastAPI app defaults to binding to localhost (127.0.0.1), which is not accessible from Railway's health check probe. Railway needs the app to listen on 0.0.0.0.
Fix: Ensure main.py uses:
app.run(host="0.0.0.0")
The health check endpoint is:
@app.fastapi_app.get("/status")
async def health_status():
return {"status": "ok", "service": "churchwiseai-voice"}
Note: Railway uses this health check endpoint to verify the agent worker process is alive. Ensure the endpoint is present and the service binds to 0.0.0.0.
4. Calls Going to Sales Agent Instead of Church
Symptom: A church's phone number rings but the caller gets the Sales Agent instead of the church's personalized agent.
Debugging steps:
-
Check PHONE_REGISTRY in session.py Is the church's Twilio number listed in
PHONE_REGISTRYwith the correctchurch_id?PHONE_REGISTRY = {"+1XXXXXXXXXX": "church-uuid-here",}If not listed, the system falls back to a database lookup (step 2).
-
Check database lookup Query
church_voice_agentsfor the phone number:SELECT church_id, twilio_phone_numberFROM church_voice_agentsWHERE twilio_phone_number = '+1XXXXXXXXXX';If no row exists or
twilio_phone_numberis null/wrong, the DB lookup returns nothing and the call falls back to Sales. -
Check Twilio SIP trunk forwarding Verify in the Twilio console that the church's number is forwarding to the correct LiveKit Cloud SIP gateway URL. If it is forwarding to the wrong endpoint (or not forwarding at all), calls will route incorrectly.
-
Check call limit
SELECT calls_this_month, calls_limitFROM church_voice_agentsWHERE church_id = 'church-uuid-here';If
calls_this_month >= calls_limit(and calls_limit > 0), the church is over its monthly limit.load_church_data()returns None and the call falls back to Sales. Resetcalls_this_monthto 0 if it is a new billing period. -
Check church_voice_agents row exists
SELECT * FROM church_voice_agents WHERE church_id = 'church-uuid-here';If no row exists, the agent cannot be built and falls back to Sales.
-
Check Railway logs Look at the
INBOUND CALLlog line in main.py output:INBOUND CALL -- to=+1XXXXXXXXXX from=+1YYYYYYYYYY room=...Verify the
tonumber (fromsip.trunkPhoneNumber) matches what you expect.
5. Poor Audio Quality
Symptom: Caller reports choppy audio, latency, echoing, or robotic-sounding responses.
Possible causes and fixes:
-
Network latency The audio path is: Twilio SIP trunk → LiveKit Cloud SIP gateway → Railway agent worker → Cartesia TTS → LiveKit Cloud → Twilio. Each hop adds latency. If Railway is in a region far from LiveKit Cloud's SIP gateway, audio latency increases. Check Railway region settings and consider aligning with LiveKit Cloud's region.
-
TTS voice selection Some Cartesia voices perform better than others in telephony contexts. The defaults are:
- Female: Cindy (
1242fb95-7ddd-44ac-8a05-9e8a22a6137d) - Male: Carson (
86e30c1d-714b-4074-a1f2-1cb6b552fb49) Custom voices cloned from low-quality source audio may produce poor results. VerifyCARTESIA_API_KEYis valid if TTS is silent.
- Female: Cindy (
-
Caller's phone/network VoIP callers, poor cell signal, or speakerphone use can degrade STT accuracy, which cascades into poor responses.
-
LLM response latency If Gemini 2.5 Flash is slow (rare), the caller hears a longer silence before the response. The filler phrases ("One moment...") mitigate this, but sustained LLM latency degrades the experience. Check Gemini API status.
6. Tools Not Executing
Symptom: The agent talks about submitting a prayer request or scheduling a callback but the tool never actually fires. No database record is created. No notification email is sent.
Debugging steps:
-
Check feature flags in church_voice_agents
SELECT prayer_requests_enabled, callback_scheduling_enabled,visitor_intake_enabled, giving_enabled, cal_enabled, pco_enabledFROM church_voice_agentsWHERE church_id = 'church-uuid-here';Tools are only added to the agent if their corresponding feature flag is enabled. For example:
giving_enabledmust be true AND (giving_urloretransfer_emailmust be set) forsend_giving_linkto be availablecal_enabledmust be true ANDcal_event_type_idmust be set for Cal.com toolspco_enabledmust be true ANDpco_app_id+pco_secretmust be set for Planning Center tools
-
Check the agent's tool list Look at the Railway logs for the agent build. The tools list is constructed in
build_coordinator_agent()inverticals/church/agents.py. If a tool is not in the list, the LLM cannot call it. -
Check Supabase connectivity Tools read
ctx.turn_env.supabaseat runtime. If the Supabase client is None (failed to initialize), tools log a warning and return a generic success message without writing to the database. -
Check tool execution logs Background tools (prayer_request, callback) yield intermediate messages. Look for log lines like:
Prayer request saved for church {church_id}Callback request saved for church {church_id}If these are missing, the DB write failed.
-
Check notification delivery Tool notifications are fire-and-forget. Check:
notification_emailon church_voice_agents (is it set? is it valid?)notification_phone(for urgent SMS)- Twilio SMS logs (for SMS delivery failures)
- Email delivery logs (Resend/SendGrid depending on current provider)
7. Wrong Theological Vocabulary
Symptom: The agent uses Protestant language for a Catholic church (e.g., "worship service" instead of "Mass") or Catholic language for a Baptist church (e.g., "parish" instead of "congregation").
Debugging steps:
-
Check denomination in churches table
SELECT denomination FROM churches WHERE id = 'church-uuid-here';The denomination field drives the theological lens selection.
-
Check DENOMINATION_TO_LENS mapping The mapping is in
core/rag.py. Verify the denomination string matches one of the keys:- "Catholic" or "Roman Catholic" -> lens ID 7
- "Baptist", "Southern Baptist", etc. -> lens ID 14
- "Methodist", "United Methodist", etc. -> lens ID 5
- "Presbyterian", "PCA", "PCUSA", "Reformed" -> lens ID 4
- "Non-denominational", "Community Church", "Bible Church" -> lens ID 10 (Christocentric, default)
If the denomination string does not match any key, it falls back to Christocentric (lens ID 10).
-
Check RAG results Session-init RAG searches
unified_rag_contentfiltered by theological lens. If the lens is wrong, the agent receives content from the wrong tradition, which influences its vocabulary. -
Check the system prompt
build_coordinator_prompt(church)inverticals/church/prompts.pymay include denomination-specific instructions. Verify the church dict has the correct denomination value.
8. Repeat Caller History Not Loading
Symptom: The agent does not recognize a returning caller, even though the same phone has called the same church before.
Debugging steps:
-
Check voice_call_logs for matching records
SELECT id, from_number, church_id, summary, created_atFROM voice_call_logsWHERE from_number = '+1CALLERNUMBER'AND church_id = 'church-uuid-here'ORDER BY created_at DESCLIMIT 5;The repeat caller history looks for calls from the same
from_numberto the samechurch_idwithin the last 90 days. -
Check that summaries exist The repeat caller block only includes calls where the
summaryfield is not null. Summaries are generated by the async Gemini classification after the call ends. If classification failed (no GEMINI_API_KEY, API error, transcript too short), the summary will be empty. -
Check the 90-day window
SELECT created_at FROM voice_call_logsWHERE from_number = '+1CALLERNUMBER'AND church_id = 'church-uuid-here'ORDER BY created_at DESC;If the most recent call is older than 90 days, it will not appear in the repeat caller history.
-
Check caller ID availability Some callers block their caller ID. If
call_request.from_is empty or anonymized, the system cannot match them to previous calls. -
Privacy-gated behavior Even when repeat caller history loads successfully, the agent is instructed: "Do NOT mention these unless the caller brings them up first." The history is there for context but the agent will not proactively say "I see you called last week about..."
9. SMS Not Sending
Symptom: Tools like send_sms_link, send_giving_link, or send_directions_link report failure. The caller does not receive a text message.
Debugging steps:
-
Check Twilio credentials The SMS functions in
core/notifications.pyuse Twilio to send SMS. Verify the environment variables:TWILIO_ACCOUNT_SIDTWILIO_AUTH_TOKENTWILIO_PHONE_NUMBER(the "from" number for SMS)
-
Check 10DLC registration status US carriers require 10DLC registration for A2P (application-to-person) messaging. If the Twilio number is not registered for 10DLC, messages may be silently dropped or blocked by carriers. Check the Twilio console for 10DLC campaign status.
-
Check the "from" number The SMS must be sent from a Twilio number that is SMS-capable. Not all Twilio voice numbers support SMS. Verify in the Twilio console that the from-number has SMS capability.
-
Check the caller's phone number
- Is
caller_phonepopulated? Tools fall back toctx.turn_env.caller_phone(from caller ID) if the explicit argument is empty. - Is the number in E.164 format (+1XXXXXXXXXX)?
- Is the number a landline? SMS cannot be delivered to most landlines.
- Is
-
Check Twilio SMS logs Twilio provides detailed delivery logs in the console under Monitor > Logs > SMS. Look for error codes:
- 30003: Unreachable destination
- 30004: Message blocked
- 30005: Unknown destination
- 30006: Landline or unreachable carrier
- 30007: Filtered (spam detection)
10. Care Agent Handoff Not Happening
Symptom: A caller shares grief, prayer needs, or emotional distress, but the Coordinator does not offer to transfer to the Care Agent. The Coordinator handles the topic directly.
Debugging steps:
-
Check TIER_AGENTS for the church's plan
SELECT plan FROM premium_churches WHERE church_id = 'church-uuid-here';Then check
verticals/church/config.py:TIER_AGENTS = {"starter": ["care", "coordinator"],"pro": ["care", "coordinator"],"suite": ["care", "coordinator"],}If "care" is not in the list for the church's plan tier, the
transfer_to_caretool is not added to the Coordinator and handoffs cannot happen. -
Check if the Care Agent built successfully The Care Agent build is wrapped in a try/except in
build_coordinator_agent(). If it fails (e.g., missingANTHROPIC_API_KEY), the system logs:Care Agent build failed (...), Coordinator will handle all topicsCheck Railway logs for this message.
-
Check ANTHROPIC_API_KEY The Care Agent uses Claude Haiku 4.5 as its primary LLM. If
ANTHROPIC_API_KEYis not set or is invalid, the Care Agent cannot be built. -
The handoff is LLM-judgment-based Unlike crisis detection (regex-based, deterministic), the Care handoff depends on the Coordinator LLM's judgment about when to transfer. The tool description instructs the LLM to "ALWAYS empathize first and ask if they'd like to speak with the Care Agent before transferring." If the LLM does not judge the conversation as requiring pastoral care, it will not offer the transfer. This is by design -- not every mention of prayer or difficulty requires a handoff.
-
Check the Coordinator's system prompt The system prompt from
build_coordinator_prompt(church)includes instructions about when to use thetransfer_to_caretool. If the prompt is malformed or missing the handoff instructions, the LLM may not know the tool is available.
General Debugging Tips
Checking Railway Logs
The voice agent runs on Railway. Logs are available via the Railway dashboard or railway logs. After pushing a code change, Railway auto-deploys — monitor the deploy log for startup errors before placing a test call.
Checking Call Records
-- Recent calls for a church
SELECT call_sid, from_number, to_number, status, duration_seconds,
summary, category, urgency, created_at
FROM voice_call_logs
WHERE church_id = 'church-uuid-here'
ORDER BY created_at DESC
LIMIT 10;
Checking Church Configuration
-- Full config for a church
SELECT cva.*, c.name, c.denomination, c.address,
pc.plan, pc.calls_this_month, pc.calls_limit
FROM church_voice_agents cva
JOIN churches c ON c.id = cva.church_id
LEFT JOIN premium_churches pc ON pc.church_id = cva.church_id
WHERE cva.church_id = 'church-uuid-here';
Environment Variables Required
Set these in the Railway service environment (not in .env files):
| Variable | Used By | Purpose |
|---|---|---|
LIVEKIT_URL | main.py | LiveKit Cloud WebSocket URL (wss://cwa-voice-9x077mph.livekit.cloud) |
LIVEKIT_API_KEY | main.py | LiveKit Cloud API key |
LIVEKIT_API_SECRET | main.py | LiveKit Cloud API secret |
DEEPGRAM_API_KEY | main.py | STT (Deepgram via livekit-plugins-deepgram) |
CARTESIA_API_KEY | agents.py | TTS (Cartesia Sonic via livekit-plugins-cartesia) |
SUPABASE_URL | session.py | Database connection |
SUPABASE_SERVICE_ROLE_KEY | session.py | Database auth (service role for writes) |
GEMINI_API_KEY | agents.py, turn_processor.py | Coordinator LLM + call classification |
ANTHROPIC_API_KEY | agents.py | Care Agent LLM |
OPENAI_API_KEY | core/rag.py | Embedding generation (text-embedding-3-small) |
TWILIO_ACCOUNT_SID | core/notifications.py | SMS sending |
TWILIO_AUTH_TOKEN | core/notifications.py | SMS auth |
TWILIO_PHONE_NUMBER | core/notifications.py | SMS from-number |
If any of these are missing, the corresponding feature degrades gracefully (non-fatal) rather than crashing the call. The LiveKit variables are required for the agent to start at all.