Skip to content
Learn Agentic AI15 min read0 views

AI Agent for Crisis Helplines: Initial Assessment, Resource Matching, and Warm Handoff

Build an AI agent that performs initial crisis assessments, matches callers with appropriate resources, and executes warm handoffs to trained counselors — with safety-first design principles.

Safety-First Design for Crisis AI

Crisis helplines handle deeply sensitive interactions. An AI agent in this context must follow one unwavering principle: the agent triages and routes, it never counsels. This tutorial builds an agent that performs structured assessments, matches callers with resources, and executes warm handoffs to trained counselors. Safety always takes priority over efficiency.

Assessment Data Structures

from dataclasses import dataclass, field
from datetime import datetime
from typing import Optional
from enum import Enum
from uuid import uuid4


class RiskLevel(Enum):
    LOW = "low"
    MODERATE = "moderate"
    HIGH = "high"
    CRITICAL = "critical"


class CrisisCategory(Enum):
    MENTAL_HEALTH = "mental_health"
    SUBSTANCE_USE = "substance_use"
    DOMESTIC_VIOLENCE = "domestic_violence"
    HOMELESSNESS = "homelessness"
    FOOD_INSECURITY = "food_insecurity"
    GENERAL_DISTRESS = "general_distress"


@dataclass
class CrisisAssessment:
    assessment_id: str = field(default_factory=lambda: str(uuid4()))
    caller_name: str = "Anonymous"
    crisis_category: Optional[CrisisCategory] = None
    risk_level: RiskLevel = RiskLevel.LOW
    is_immediate_danger: bool = False
    has_suicidal_ideation: bool = False
    assessment_notes: str = ""
    created_at: datetime = field(default_factory=datetime.utcnow)
    handoff_to: Optional[str] = None


@dataclass
class CrisisResource:
    resource_id: str = field(default_factory=lambda: str(uuid4()))
    name: str = ""
    category: CrisisCategory = CrisisCategory.GENERAL_DISTRESS
    phone: str = ""
    serves_area: list[str] = field(default_factory=list)
    accepts_walk_ins: bool = False

Initial Assessment Tool

The assessment tool uses structured questions and keyword detection to classify risk level.

from agents import function_tool

assessments_log: list[CrisisAssessment] = []

CRITICAL_INDICATORS = [
    "suicide", "kill myself", "end my life", "want to die",
    "self-harm", "cutting", "overdose", "gun",
    "being beaten", "he is hitting me", "she is hitting me",
    "child is being hurt", "locked in",
]

HIGH_RISK_INDICATORS = [
    "not safe", "afraid", "threatened", "stalking",
    "nowhere to go", "sleeping outside", "evicted today",
    "relapse", "withdrawal", "haven't eaten",
]


@function_tool
async def perform_assessment(
    caller_description: str,
    caller_name: str = "Anonymous",
    caller_city: str = "",
    caller_state: str = "",
) -> dict:
    """Perform an initial crisis assessment based on the caller's
    description. Classifies risk level and identifies needs."""
    text_lower = caller_description.lower()

    risk_level = RiskLevel.LOW
    is_danger = False
    has_si = False

    if any(ind in text_lower for ind in CRITICAL_INDICATORS):
        risk_level = RiskLevel.CRITICAL
        is_danger = True
        has_si = any(w in text_lower for w in [
            "suicide", "kill myself", "end my life", "want to die"])
    elif any(ind in text_lower for ind in HIGH_RISK_INDICATORS):
        risk_level = RiskLevel.HIGH

    category = CrisisCategory.GENERAL_DISTRESS
    for cat, kws in {
        CrisisCategory.MENTAL_HEALTH: ["depressed", "anxiety", "panic"],
        CrisisCategory.SUBSTANCE_USE: ["drinking", "drugs", "relapse"],
        CrisisCategory.DOMESTIC_VIOLENCE: ["hitting", "abuse", "violent"],
        CrisisCategory.HOMELESSNESS: ["homeless", "shelter", "evicted"],
    }.items():
        if any(kw in text_lower for kw in kws):
            category = cat
            break

    assessment = CrisisAssessment(
        caller_name=caller_name, crisis_category=category,
        risk_level=risk_level, is_immediate_danger=is_danger,
        has_suicidal_ideation=has_si, assessment_notes=caller_description,
    )
    assessments_log.append(assessment)

    response = {"assessment_id": assessment.assessment_id,
                "risk_level": risk_level.value, "category": category.value,
                "is_immediate_danger": is_danger}

    if risk_level == RiskLevel.CRITICAL:
        response["immediate_action"] = (
            "CRITICAL: Initiate warm handoff. Advise calling 911 if "
            "in physical danger. Provide 988 for mental health crisis.")

    return response

Resource Matching Tool

After assessment, the agent matches the caller with relevant local resources.

resources_db: list[CrisisResource] = []

NATIONAL_RESOURCES = [
    {"name": "988 Suicide & Crisis Lifeline", "phone": "988",
     "category": "mental_health"},
    {"name": "National Domestic Violence Hotline",
     "phone": "1-800-799-7233", "category": "domestic_violence"},
    {"name": "SAMHSA National Helpline", "phone": "1-800-662-4357",
     "category": "substance_use"},
]


@function_tool
async def find_resources(
    crisis_category: str,
    state: str = "",
) -> dict:
    """Find crisis resources matching the caller's category."""
    category = CrisisCategory(crisis_category)
    matches = []

    for nr in NATIONAL_RESOURCES:
        if nr["category"] == crisis_category:
            matches.append({"name": nr["name"], "phone": nr["phone"],
                            "type": "national"})

    for resource in resources_db:
        if resource.category != category:
            continue
        if state and resource.serves_area and state not in resource.serves_area:
            continue
        matches.append({"name": resource.name, "phone": resource.phone,
                        "type": "local", "walk_ins": resource.accepts_walk_ins})

    return {"resources": matches, "total_found": len(matches)}

Warm Handoff Tool

The warm handoff ensures the caller is connected to a human, not just given a phone number.

See AI Voice Agents Handle Real Calls

Book a free demo or calculate how much you can save with AI voice automation.

@function_tool
async def initiate_warm_handoff(
    assessment_id: str,
    counselor_type: str,
    urgency: str = "standard",
) -> dict:
    """Initiate a warm handoff to a trained counselor."""
    assessment = None
    for a in assessments_log:
        if a.assessment_id == assessment_id:
            assessment = a
            break

    if not assessment:
        return {"error": "Assessment not found"}

    counselor_queue = {
        "mental_health": "Licensed Mental Health Counselor",
        "substance_use": "Substance Abuse Counselor",
        "domestic_violence": "DV Advocate",
        "general": "Crisis Counselor",
    }
    counselor = counselor_queue.get(counselor_type, "Crisis Counselor")
    assessment.handoff_to = counselor

    return {
        "status": "handoff_initiated",
        "counselor_type": counselor,
        "estimated_wait": "under 2 minutes" if urgency == "critical"
            else "5-10 minutes",
        "risk_level": assessment.risk_level.value,
    }

Assembling the Crisis Agent

from agents import Agent, Runner

crisis_agent = Agent(
    name="Crisis Helpline Agent",
    instructions="""You are a crisis helpline triage agent.
Your role: assess, connect, and support — NEVER counsel.

RULES:
1. Suicidal ideation detected -> provide 988 + warm handoff
2. Physical danger -> advise calling 911 first
3. NEVER attempt therapy or clinical advice
4. Stay with the caller until a counselor connects
5. For low-risk, provide resources and offer to check back

TONE: Warm, calm, empathetic, non-judgmental.""",
    tools=[
        perform_assessment,
        find_resources,
        initiate_warm_handoff,
    ],
)

result = Runner.run_sync(
    crisis_agent,
    "I just lost my apartment and I have nowhere to go tonight. "
    "I have two kids with me. It is getting cold outside.",
)
print(result.final_output)

FAQ

Is it safe to use AI for crisis helplines?

AI should never replace trained crisis counselors. This agent serves as a triage layer that reduces wait times by gathering initial information and routing callers to the right specialist. The agent always defers to human counselors for anything beyond basic assessment. Every interaction is logged for supervisory review.

How does the warm handoff work technically?

In production, the warm handoff integrates with a call center platform like Twilio. When initiated, the caller enters a priority queue, the assessment summary appears on the counselor's screen, and the connection is maintained until the counselor confirms they are on the line.

What if no counselors are available?

The agent provides direct phone numbers for national crisis lines (988, NDVH, SAMHSA) and stays engaged with the caller using grounding techniques developed by clinical staff until a counselor becomes available. For critical-risk cases, the agent advises calling 911.


#CrisisSupport #AISafety #NonprofitAI #AgenticAI #Python #LearnAI #AIEngineering

Share this article
C

CallSphere Team

Expert insights on AI voice agents and customer communication automation.

Try CallSphere AI Voice Agents

See how AI voice agents work for your industry. Live demo available -- no signup required.