CoolFace
Apppublic

HiteshiAglawe0505/safespace-ai

sourceHugging Facemitupdated 4mo agoView on Hugging Face
2likes
App README

๐ŸŒฟ SafeSpace AI 2.0

AI-powered Medical & Mental Health Assistant Multi-agent ยท Multimodal ยท WhatsApp + Web ยท Production Deployed

![Live Demo](https://huggingface.co/spaces/HiteshiAglawe0505/safespace-ai) ![Python](https://python.org) ![CrewAI](https://crewai.com) ![Groq](https://groq.com) ![LangSmith](https://smith.langchain.com) ![MCP](https://modelcontextprotocol.io)


What is SafeSpace AI?

SafeSpace is a production-deployed, multi-channel AI health assistant that provides:

  • โ€”๐Ÿฉบ Medical guidance โ€” symptom analysis, image reading (blood reports, X-rays, ECG, skin conditions), home care advice, red-flag detection
  • โ€”๐Ÿง  Mental health support โ€” CBT-based therapy conversations, emotional support, crisis detection
  • โ€”๐Ÿšจ Emergency escalation โ€” auto-triggers a real Twilio voice call when suicidal ideation or crisis is detected
  • โ€”๐Ÿ“ Therapist finder โ€” real clinic listings via Google Maps Places API through an MCP server
  • โ€”๐Ÿ–ผ๏ธ Medical image analysis โ€” upload a photo of a rash, wound, blood report, X-ray, or ECG
  • โ€”๐ŸŽ™๏ธ Voice message support โ€” speak your symptoms on WhatsApp or web; Whisper transcribes them

Available on WhatsApp (via Twilio) and a Streamlit web app โ€” both powered by the same backend deployed on Hugging Face Spaces with Nginx routing everything through a single public port.


๐Ÿ—๏ธ Architecture

User (WhatsApp / Web Browser)
         โ”‚
         โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚         NGINX  (port 7860 โ€” public)      โ”‚
โ”‚                                          โ”‚
โ”‚  /whatsapp/*  โ†’  FastAPI   :8000         โ”‚
โ”‚  /mcp/*       โ†’  MCP Server:8001  โ† NEW  โ”‚
โ”‚  /*           โ†’  Streamlit :8501         โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
         โ”‚
    โ”Œโ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
    โ”‚                   โ”‚
    โ–ผ                   โ–ผ
FastAPI              Streamlit
(WhatsApp webhook)   (Web UI)
    โ”‚                   โ”‚
    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
             โ”‚ same engine for both channels
             โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                   CORE ENGINE                    โ”‚
โ”‚                                                  โ”‚
โ”‚  Multimodal Handler                              โ”‚
โ”‚  (image โ†’ Llama 4 Scout Vision)                  โ”‚
โ”‚  (audio โ†’ Groq Whisper large-v3)                 โ”‚
โ”‚                  โ†“                               โ”‚
โ”‚  Intent Classifier                               โ”‚
โ”‚  (Groq structured output + Pydantic)             โ”‚
โ”‚  โ†’ MEDICAL / THERAPY / MIXED / UNKNOWN           โ”‚
โ”‚                  โ†“                               โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”‚
โ”‚  โ”‚           CrewAI Crew (sequential)       โ”‚    โ”‚
โ”‚  โ”‚                                          โ”‚    โ”‚
โ”‚  โ”‚  SafetyAgent   โ† always runs FIRST       โ”‚    โ”‚
โ”‚  โ”‚       โ†“                                  โ”‚    โ”‚
โ”‚  โ”‚  DoctorAgent   or  TherapistAgent        โ”‚    โ”‚
โ”‚  โ”‚  (context from SafetyAgent shared)       โ”‚    โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ”‚
โ”‚                  โ†“                               โ”‚
โ”‚  SQLite Session Memory  โ†โ†’  LangSmith Tracing    โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
         โ”‚
         โ–ผ
   ChatResponse โ†’ WhatsApp (Twilio) / Streamlit UI


MCP Server (port 8001 โ€” internal)
  TherapistAgent โ†’ maps_tool.py โ†’ POST /search
                โ†’ therapist_directory.py โ†’ Google Maps

๐Ÿค– Agentic Design โ€” The 3-Agent Crew

Every message passes through all agents in sequence, regardless of channel:

AgentRoleTools
SafetyAgentCrisis detection โ€” checks every message for suicidal ideation, self-harm, emergencies. Runs FIRST, always.emergency_call (Twilio voice)
DoctorAgentMedical guidance โ€” symptoms, image interpretation, home care, red flags. Never diagnoses.None
TherapistAgentEmotional support โ€” CBT techniques, coping strategies, therapist searchfind_nearby_therapists (Google Maps via MCP)

Why sequential? SafetyAgent runs first on every single message โ€” no medical or therapy response is ever sent before checking if it is a crisis. This is an architectural guarantee, not just a prompt instruction.

Why context sharing? Both DoctorAgent and TherapistAgent receive the SafetyAgent output via context=[safety_task]. If safety flagged a concern, the second agent's response accounts for it automatically.


๐Ÿ”Œ MCP Server โ€” Therapist Directory (Live on HF)

The therapist finder is exposed as an MCP (Model Context Protocol) server โ€” a standard by Anthropic for AI tool communication. The MCP server runs inside the same Docker container and is publicly reachable via Nginx routing.

TherapistAgent calls find_nearby_therapists tool
         โ†“
maps_tool.py detects THERAPIST_MCP_URL is set
         โ†“  HTTP POST to http://127.0.0.1:8001/search
MCP Server (mcp_server/therapist_directory.py)
         โ†“  exposes 3 tools via /tools discovery endpoint
  search_by_location()   โ†’  POST /search
  get_therapist_details() โ†’  POST /details
  list_specialties()      โ†’  GET  /specialties
         โ†“
Google Maps Places API
         โ†“
Real clinic listings with names, addresses, ratings, open/closed status

MCP endpoints (publicly accessible):

  • โ€”https://hiteshiaglawe0505-safespace-ai.hf.space/mcp/health
  • โ€”https://hiteshiaglawe0505-safespace-ai.hf.space/mcp/tools
  • โ€”https://hiteshiaglawe0505-safespace-ai.hf.space/mcp/docs

Why MCP? The therapist search logic is completely decoupled from the agent. Any future agent, external app, or partner service can call the same MCP server. The data source (Google Maps today, Practo tomorrow) is swappable without touching a single line of agent code.

Fallback design: If the MCP server is temporarily unavailable (e.g., restarting), maps_tool.py automatically falls back to calling Google Maps directly. Users always receive results.


๐Ÿ“Š LLMOps โ€” Observability with LangSmith

Every request is traced in LangSmith at smith.langchain.com under project safespace-ai.

What is logged per request (Traces tab):

FieldExample
Input: user_idweb_a66a**** / whatsapp:+91*******590
Input: channelweb / whatsapp
Input: message_typetext / image / audio
Output: intentTHERAPY / MEDICAL / MIXED
Output: confidence0.95
Output: textFull response sent to user
Output: escalatedfalse / true (emergency call fired)
Output: latency_ms5770

Tool calls (Runs tab โ†’ filter run_type=tool):

  • โ€”find_nearby_therapists โ€” location, output clinic list, latency
  • โ€”emergency_call โ€” crisis reason, Twilio SID, latency

Dataset: Every request logs intent + confidence to the safespace_intent_classification dataset for future fine-tuning.

Note on LLM call tracing: CrewAI 1.14.4 uses LiteLLM directly (bypassing LangChain wrappers) and resets LiteLLM callbacks after each run โ€” blocking third-party callback nesting. Agent-level LLM calls are observable at the trace level via latency but are not individually nested under the parent run. This is a known CrewAI 1.14.4 + LangSmith version compatibility constraint.


๐Ÿ› ๏ธ Tech Stack

CategoryTechnologyWhy
LLMGroq โ€” Llama 3.3 70BFastest inference, free tier
VisionGroq โ€” Llama 4 ScoutMedical image analysis on same API
SpeechGroq โ€” Whisper large-v3Voice message transcription
AgentsCrewAI 1.14.4Sequential multi-agent orchestration
IntentGroq structured output + PydanticReliable JSON classification, no string parsing
APIFastAPI + UvicornAsync WhatsApp webhook receiver
Web UIStreamlit 1.57Native st.audio_input() mic, rapid multimodal UI
MemorySQLite + aiosqliteLightweight async session persistence
WhatsAppTwilioWebhook + media download + voice calls
MapsGoogle Maps Places APIReal therapist/clinic listings with India data
ObservabilityLangSmithRequest tracing, tool monitoring, intent datasets
DeploymentHugging Face Spaces (Docker)Free, permanent URL, built-in secrets management
ProxyNginxRoutes WebSocket + webhook + MCP on single port 7860
ProtocolMCP (Model Context Protocol)Decoupled tool server for therapist directory

๐Ÿš€ Quick Start (Local)

bash
# 1. Clone
git clone https://github.com/HiteshiAglawe0505/safespace-ai.git
cd safespace-ai

# 2. Install
pip install -r requirements.txt

# 3. Configure
cp .env.example .env
# Required: GROQ_API_KEY, GOOGLE_MAPS_API_KEY
# Optional: LANGSMITH_API_KEY, TWILIO_* (for WhatsApp), THERAPIST_MCP_URL

# 4. Run Web UI only
streamlit run interfaces/streamlit_ui/app.py

# 5. Run WhatsApp backend (separate terminal)
python app.py
# Expose with: ngrok http 8000
# Set Twilio webhook: https://your-ngrok-url/whatsapp/webhook

# 6. Run MCP server (optional, separate terminal)
python mcp_server/therapist_directory.py
# Add to .env: THERAPIST_MCP_URL=http://localhost:8001

๐ŸŒ Deployment (Hugging Face Spaces)

bash
pip install huggingface_hub
python fix_hf_upload.py --username HiteshiAglawe0505 --token hf_xxxxx

Add secrets in Space Settings โ†’ Secrets:

SecretRequiredPurpose
GROQ_API_KEYโœ…LLM, vision, speech
GOOGLE_MAPS_API_KEYโœ…Therapist search
LANGSMITH_API_KEYRecommendedObservability
LANGSMITH_PROJECTRecommendedProject name
LANGSMITH_TRACINGRecommendedEnable tracing
TWILIO_ACCOUNT_SIDWhatsApp onlyWebhook auth
TWILIO_AUTH_TOKENWhatsApp onlyWebhook auth
TWILIO_FROM_NUMBERWhatsApp onlySender number
TWILIO_WHATSAPP_NUMBERWhatsApp onlySandbox number
EMERGENCY_CONTACTWhatsApp onlyCrisis call target

THERAPIST_MCP_URL is not a secret โ€” it is hardcoded as http://127.0.0.1:8001 inside hf_app.py since the MCP server runs inside the same container.

Live: https://huggingface.co/spaces/HiteshiAglawe0505/safespace-ai


๐Ÿ“ Project Structure

safespace-ai/
โ”œโ”€โ”€ app.py                          # Local dev: FastAPI entry point only
โ”œโ”€โ”€ hf_app.py                       # HF Spaces: starts Nginx + FastAPI + MCP + Streamlit
โ”œโ”€โ”€ Dockerfile
โ”œโ”€โ”€ requirements.txt                # crewai==1.14.4 pinned (cache_breakpoint compatibility)
โ”œโ”€โ”€ .env.example
โ”‚
โ”œโ”€โ”€ core/
โ”‚   โ”œโ”€โ”€ config.py                   # pydantic-settings: all env vars validated at startup
โ”‚   โ”œโ”€โ”€ schemas.py                  # ChatRequest, ChatResponse, Intent, MessageType
โ”‚   โ””โ”€โ”€ engine.py                   # handle_request(): multimodal routing + LangSmith tracing
โ”‚
โ”œโ”€โ”€ agents/
โ”‚   โ”œโ”€โ”€ crew.py                     # CrewAI crew: agents, tasks, location detection, kickoff
โ”‚   โ”œโ”€โ”€ intent_classifier.py        # Groq JSON mode + Pydantic โ†’ Intent enum
โ”‚   โ”œโ”€โ”€ safety.py                   # SafetyAgent: crisis detection + emergency call
โ”‚   โ”œโ”€โ”€ doctor.py                   # DoctorAgent: medical guidance, 80/20 response structure
โ”‚   โ””โ”€โ”€ therapist.py                # TherapistAgent: CBT support + therapist search
โ”‚
โ”œโ”€โ”€ tools/
โ”‚   โ”œโ”€โ”€ maps_tool.py                # FindTherapistsTool โ†’ MCP server โ†’ Google Maps
โ”‚   โ””โ”€โ”€ emergency_tool.py           # EmergencyCallTool โ†’ Twilio voice API
โ”‚
โ”œโ”€โ”€ mcp_server/
โ”‚   โ””โ”€โ”€ therapist_directory.py      # MCP server on :8001 โ€” 3 tools over Google Maps Places API
โ”‚
โ”œโ”€โ”€ multimodal/
โ”‚   โ”œโ”€โ”€ vision.py                   # describe_image() โ†’ Groq Llama 4 Scout
โ”‚   โ””โ”€โ”€ speech.py                   # transcribe_audio() โ†’ Groq Whisper large-v3
โ”‚
โ”œโ”€โ”€ memory/
โ”‚   โ””โ”€โ”€ store.py                    # SQLite: save/load session, format last 10 msgs for prompt
โ”‚
โ”œโ”€โ”€ interfaces/
โ”‚   โ”œโ”€โ”€ whatsapp/
โ”‚   โ”‚   โ”œโ”€โ”€ webhook.py              # POST /whatsapp/webhook โ€” receives Twilio form data
โ”‚   โ”‚   โ””โ”€โ”€ sender.py               # send_whatsapp_message() โ†’ Twilio Messages API
โ”‚   โ””โ”€โ”€ streamlit_ui/
โ”‚       โ””โ”€โ”€ app.py                  # Chat UI: text + image upload + st.audio_input() mic
โ”‚
โ””โ”€โ”€ observability/
    โ””โ”€โ”€ tracer.py                   # LangSmith: parent runs, tool @traceable, intent dataset

๐Ÿ”‘ Key Technical Decisions

1. Why CrewAI sequential over LangChain agents? CrewAI's Process.sequential guarantees SafetyAgent always runs first โ€” architecturally impossible to skip crisis detection. With a single LangChain agent, the router might send medical messages directly to DoctorAgent without a safety check.

2. Why Pydantic structured output for intent? Groq JSON mode + Pydantic IntentResult guarantees a valid Intent enum with confidence and reasoning. No string parsing, no hallucinated values, immediate ValidationError at the boundary rather than silent failures inside agents.

3. Why SQLite over Redis/Postgres? Session memory needs last 10 messages per user. SQLite is zero-infrastructure, async-capable via aiosqlite, and sufficient for prototype scale. The trade-off is ephemeral data on HF (wiped on container restart). Postgres is the production upgrade path with minimal code change.

4. Why Nginx on HF Spaces? HF Docker Spaces expose exactly one port (7860). Nginx routes /whatsapp/* to FastAPI, /mcp/* to the MCP server, and /* including WebSocket to Streamlit โ€” all in the same container. A Python httpx proxy blocks WebSocket upgrade headers (produces 403); Nginx handles them natively.

5. Why MCP for the therapist directory? Decouples data source from agent code. TherapistAgent calls the MCP server via HTTP โ€” it doesn't know or care whether data comes from Google Maps, Practo, or a hospital database. The backend is swappable without touching agent code.

6. Why is `crewai==1.14.4` pinned? CrewAI 1.14.5+ adds a cache_breakpoint property to system messages. Groq does not support this property and rejects every request with a 400 error. Version 1.14.4 is the last version confirmed working with Groq's API.

7. Why is `THERAPIST_MCP_URL` hardcoded as `127.0.0.1:8001`? The MCP server runs inside the same Docker container as the main app. Localhost communication is faster (no network hop), requires no HTTPS certificate, and needs no separate deployment. The public /mcp/* Nginx route exists for external callers; internal tool calls go direct.


๐Ÿ”ฎ Future Scope & Known Limitations

Current Limitations (Prototype vs Production)

LimitationImpactRoot Cause
SQLite data is ephemeralUsers lose conversation history on every HF restartSQLite lives in container filesystem, wiped on restart
Web user identity resets per tabNo memory continuity for web users across sessionsUUID generated fresh per st.session_state, no persistent login
CrewAI agent LLM calls not nested in LangSmithLLM Calls monitoring tab is emptyCrewAI 1.14.4 resets LiteLLM callbacks, blocking LangSmith nesting
MCP server restarts intermittentlyOccasional fallback to direct Google MapsHF container orchestration kills subprocesses under memory pressure
No Twilio webhook signature validationSpoofed webhook requests possibleSkipped for speed; critical for real deployment
WhatsApp is Twilio sandboxReal users cannot message without joining sandboxFree Twilio account limitation
Groq free tier rate limitsVision/speech may get 429 errors under loadModel fallback list helps but not eliminated

Roadmap โ€” Production Upgrades

1. Persistent Database โ†’ PostgreSQL / Supabase Replace SQLite with a hosted PostgreSQL database (Railway, Supabase, Neon). Session memory survives container restarts. Users retain full conversation history indefinitely. Code change is minimal โ€” aiosqlite and asyncpg have nearly identical interfaces.

2. User Authentication โ†’ Login System Add a lightweight login so web users get a persistent, consistent user_id tied to their account rather than a new UUID per browser tab. Options: Google OAuth via streamlit-google-auth, or a simple email + magic link system. WhatsApp already has natural identity via phone number.

3. RAG over Medical Knowledge Base Add a vector database (Qdrant, Pinecone) loaded with verified medical sources โ€” DSM-5 criteria, drug interaction databases, symptom-to-condition mappings. Agents would retrieve relevant documents before responding, grounding answers in verified data rather than purely Llama's training data.

4. Doctor Search for MEDICAL Intent The MCP server already accepts a specialty parameter. Add a FindDoctorsTool in maps_tool.py and attach it to DoctorAgent. Patients asking about specific medical conditions could receive listings for relevant specialists (cardiologist, dermatologist, neurologist) without any MCP server changes.

5. Upgrade CrewAI โ†’ Native LangSmith LLM Tracing Once Groq resolves the cache_breakpoint compatibility issue (or a newer CrewAI version fixes it), upgrading to CrewAI 1.15+ would restore full parent-child LLM call nesting in LangSmith. The LLM Calls and Cost & Tokens monitoring tabs would then populate automatically.

6. Fine-Tuning Pipeline LangSmith is already collecting every conversation as the safespace_intent_classification dataset. Once sufficient data accumulates, fine-tune a smaller model (Llama 3.1 8B) specifically on health-domain conversations. A fine-tuned 8B model could outperform the general 70B at a fraction of the inference cost.

7. Multi-Language Support Groq Whisper large-v3 supports 50+ languages including Hindi, Marathi, Bengali, Tamil, and Telugu. Add a language detection step in engine.py and inject a language instruction into agent task descriptions. The infrastructure already supports it โ€” just needs the detection + routing logic.

8. WhatsApp Business API โ†’ Full Production Migrate from Twilio Sandbox to a WhatsApp Business Account. Removes the requirement for users to join a sandbox. Enables proactive messaging, message templates, and higher throughput limits.

9. Horizontal Scaling Replace SQLite with PostgreSQL (item 1), add a message queue (Redis + Celery or AWS SQS) so the webhook returns 200 OK immediately and processes LLM responses asynchronously, then deploy multiple FastAPI/Streamlit instances behind a load balancer. The adapter pattern means both channels use the same brain with no refactoring needed.

10. Twilio Webhook Signature Validation Add X-Twilio-Signature header verification in webhook.py using Twilio's HMAC-SHA1 algorithm. Prevents spoofed webhook requests from external actors. One-line change using twilio.request_validator.RequestValidator.

11. User Feedback Loop โ†’ Model Improvement Add thumbs up / thumbs down buttons in the Streamlit UI that call langsmith_client.create_feedback(run_id, score). Over time, builds a labeled dataset of good and bad responses. Enables prompt optimization and identifies which intents or message types produce weak responses.

12. Voice Output โ†’ Text-to-Speech Responses For WhatsApp voice users, convert SafeSpace responses to audio using a TTS API (ElevenLabs, Google TTS) and send back as voice notes via Twilio's media messaging. Creates a fully voice-native experience for accessibility.


๐Ÿ“ธ Demo โ€” What It Can Do

CapabilityExample
Medical symptom advice"My left side of throat feels sore and heavy" โ†’ home remedies + warning signs
Blood report readingUpload CBC report image โ†’ explains Hemoglobin levels, suggests doctor visit
X-ray interpretationUpload child's chest X-ray โ†’ notes mottled lung appearance, recommends monitoring
ECG readingUpload ECG strip โ†’ identifies leads, flags possible abnormal rhythms
Skin conditionUpload photo of rash โ†’ describes appearance, home care, when to seek help
Voice noteSend audio symptom description โ†’ Whisper transcribes โ†’ full medical guidance
Crisis detection"I feel like killing myself" โ†’ emergency Twilio call placed + helpline numbers sent
Therapist finder"find therapists near Gondia Maharashtra" โ†’ 5 real clinics with ratings and hours
CBT support"I'm feeling low since a week" โ†’ validation + mindful breathing exercise
MemoryReferences previous messages in same conversation across WhatsApp sessions

๐Ÿ‘ฉโ€๐Ÿ’ป Author

Hiteshi Aglawe Aspiring GenAI / ML Engineer GitHub ยท HuggingFace


โš ๏ธ Disclaimer

SafeSpace AI is a prototype research assistant โ€” not a substitute for professional medical or mental health care. Always consult a qualified doctor or licensed therapist for medical decisions. The emergency call feature is a demonstration of crisis escalation architecture and should not be relied upon as a sole safety mechanism.