Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Handle mental health crisis situations in AI coaching safely. Use when implementing crisis detection, safety protocols, emergency escalation, or suicide prevention features. Activates for crisis keywords, safety planning, hotline integration, and risk assessment.
.claude/skills/crisis-response-protocol/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-08 | ✗→✓ | ▲ Improved | — | — |
| case-10 | ✗→✓ | ▲ Improved | — | — |
| case-09 | ✗→✓ | ▲ Improved | — | — |
| case-11 | ✗→✓ | ▲ Improved | — | — |
| case-13 | ✗→✓ | ▲ Improved | — | — |
This skill helps you implement safe crisis intervention features for the AI coaching system, following mental health best practices.
✅ USE this skill for:
❌ DO NOT use for:
sober-addict-protector or recovery-coach-patterns> AI should NEVER be the sole responder in acute crisis situations. > Always provide pathways to human support and emergency services.
typescriptinterface RiskIndicators { // PRIMARY - Immediate escalation required primary: { suicidalIdeation: string[]; // "want to die", "end it all" selfHarmIntent: string[]; // "hurt myself", "cutting" homicidalIdeation: string[]; // "hurt someone" activeSubstanceEmergency: string[]; // "overdosed", "can't stop" }; // SECONDARY - Elevated monitoring secondary: { severeDepression: string[]; // "hopeless", "no point" panicSymptoms: string[]; // "can't breathe", "heart racing" psychoticSymptoms: string[]; // "hearing voices" severeAnxiety: string[]; // "terrified", "losing control" }; // TERTIARY - Check-in triggers tertiary: { isolationPatterns: string[]; // "no one cares", "alone" substanceRelapse: string[]; // "started using", "slipped" hopelessness: string[]; // "never get better" }; }
typescript// src/lib/ai/crisis-detection.ts export interface CrisisAssessment { level: 'none' | 'low' | 'medium' | 'high' | 'critical'; indicators: string[]; recommendedAction: CrisisAction; timestamp: Date; } export type CrisisAction = | 'continue_conversation' | 'gentle_check_in' | 'safety_resources' | 'crisis_protocol' | 'emergency_escalation'; export function assessCrisisLevel( messageContent: string, conversationHistory: Message[], userCheckInHistory: CheckIn[] ): CrisisAssessment { const indicators: string[] = []; let level: CrisisAssessment['level'] = 'none'; // Check primary indicators (critical) if (hasPrimaryIndicators(messageContent)) { level = 'critical'; indicators.push('primary_risk_detected'); } // Check secondary indicators if (hasSecondaryIndicators(messageContent)) { level = level === 'none' ? 'high' : level; indicators.push('secondary_risk_detected'); } // Check pattern indicators from history if (hasWorseningPattern(userCheckInHistory)) { level = level === 'none' ? 'medium' : level; indicators.push('worsening_trend'); } // Check conversation escalation if (hasEscalatingDistress(conversationHistory)) { level = level === 'none' ? 'medium' : level; indicators.push('escalating_distress'); } return { level, indicators, recommendedAction: getRecommendedAction(level), timestamp: new Date(), }; }
Normal AI coaching interaction.
typescriptconst gentleCheckInResponse = ` I want to make sure I understand how you're feeling. It sounds like you're going through a difficult time. Would you like to: - Talk more about what's on your mind? - Try a grounding exercise together? - Look at some coping strategies? I'm here to listen. `;
typescriptconst safetyResourcesResponse = ` I hear that you're struggling, and I want you to know that support is available. Here are some resources that might help: 📞 988 Suicide & Crisis Lifeline: Call or text 988 💬 Crisis Text Line: Text HOME to 741741 🌐 SAMHSA Helpline: 1-800-662-4357 Would you like to talk about what's going on, or would connecting with one of these resources feel right? `;
typescriptconst crisisProtocolResponse = ` I'm concerned about what you've shared, and I want to make sure you're safe. Right now, I'd like you to consider reaching out to someone who can help: 🆘 If you're in immediate danger: Call 911 📞 988 Suicide & Crisis Lifeline: Call or text 988 (24/7) 💬 Crisis Text Line: Text HOME to 741741 These are trained counselors who understand what you're going through. Is there someone you trust - a friend, family member, or sponsor - who you could reach out to right now? I'm still here with you. `;
typescriptconst emergencyResponse = ` I'm very concerned about your safety right now. 🆘 Please call 911 or go to your nearest emergency room immediately. If you can't do that, please call 988 right now - they can help. Your life matters. Please reach out for help right now. [EMERGENCY CONTACTS DISPLAYED] `; // System action: Flag for human review, notify emergency contact if configured
typescript// src/lib/ai/chat-handler.ts export async function handleChatMessage( message: string, conversationId: string, userId: string ): Promise<ChatResponse> { // 1. Assess crisis level BEFORE generating AI response const crisisAssessment = await assessCrisisLevel( message, await getConversationHistory(conversationId), await getUserCheckIns(userId, 7) ); // 2. Log assessment (for safety review) await logCrisisAssessment(userId, conversationId, crisisAssessment); // 3. Handle based on level if (crisisAssessment.level === 'critical') { // Don't use AI - provide immediate crisis response await notifyEmergencyContact(userId); await flagForHumanReview(conversationId, 'critical_crisis'); return { message: emergencyResponse, showEmergencyContacts: true, disableChat: true, // Prevent further AI interaction crisisLevel: 'critical', }; } if (crisisAssessment.level === 'high') { // Provide crisis resources, continue with caution await flagForHumanReview(conversationId, 'high_risk'); return { message: crisisProtocolResponse, showCrisisResources: true, crisisLevel: 'high', }; } // 4. For lower levels, proceed with AI but inject safety context const systemPrompt = getSystemPromptWithSafetyContext(crisisAssessment); const aiResponse = await generateAIResponse(message, systemPrompt); // 5. Post-process AI response for safety const safeResponse = await validateResponseSafety(aiResponse); return { message: safeResponse, crisisLevel: crisisAssessment.level, }; }
typescript// src/lib/crisis/resources.ts export const crisisResources = { national: [ { name: '988 Suicide & Crisis Lifeline', phone: '988', text: '988', url: 'https://988lifeline.org', available: '24/7', description: 'Free, confidential crisis support', }, { name: 'Crisis Text Line', text: 'HOME to 741741', url: 'https://www.crisistextline.org', available: '24/7', description: 'Text-based crisis support', }, { name: 'SAMHSA National Helpline', phone: '1-800-662-4357', url: 'https://www.samhsa.gov/find-help/national-helpline', available: '24/7', description: 'Substance abuse and mental health referrals', }, ], recovery: [ { name: 'AA Hotline', phone: '1-800-839-1686', url: 'https://www.aa.org', description: 'Alcoholics Anonymous support', }, { name: 'NA Helpline', phone: '1-818-773-9999', url: 'https://na.org', description: 'Narcotics Anonymous support', }, ], specialized: [ { name: 'Veterans Crisis Line', phone: '988 (press 1)', text: '838255', description: 'For veterans and service members', }, { name: 'Trevor Project', phone: '1-866-488-7386', text: 'START to 678-678', description: 'LGBTQ+ youth crisis support', }, ], };
typescript// src/lib/crisis/emergency-contacts.ts export async function notifyEmergencyContact(userId: string): Promise<void> { const contacts = await getEmergencyContacts(userId); if (contacts.length === 0) { // Log that no emergency contact was available await logCrisisEvent(userId, 'no_emergency_contact'); return; } const primaryContact = contacts[0]; // Send notification (SMS, email, or push) await sendEmergencyNotification(primaryContact, { type: 'crisis_alert', message: `${userName} may be in crisis and could use your support. ` + `Please reach out to them if you can.`, // Never include conversation content - privacy }); // Audit log await logCrisisEvent(userId, 'emergency_contact_notified', { contactId: primaryContact.id, }); }
typescript// Prompt injection for safety context const safetySystemPrompt = ` CRITICAL SAFETY INSTRUCTIONS: 1. You are NOT a therapist or crisis counselor 2. For ANY mention of self-harm, suicide, or harming others: - Express genuine concern - Provide crisis resources (988, Crisis Text Line) - Encourage professional help - Do NOT attempt to counsel through crisis 3. Never minimize feelings or use toxic positivity 4. Never promise confidentiality about safety concerns 5. Always validate emotions while encouraging professional support 6. If user mentions relapse, acknowledge and provide SAMHSA helpline `; // Response validation async function validateResponseSafety(response: string): Promise<string> { const unsafePatterns = [ /don't (call|reach out|get help)/i, /you don't need (help|therapy|a professional)/i, /just (think positive|be happy|get over it)/i, /it's not that (bad|serious)/i, ]; for (const pattern of unsafePatterns) { if (pattern.test(response)) { // Flag for review and return safe fallback await flagForReview('unsafe_response_pattern'); return getSafeFallbackResponse(); } } return response; }
typescript// All crisis events must be logged for review export async function logCrisisEvent( userId: string, eventType: CrisisEventType, details?: Record<string, unknown> ): Promise<void> { await db.insert(crisisEvents).values({ id: generateId(), userId, eventType, details: JSON.stringify(sanitizeDetails(details)), createdAt: new Date(), reviewed: false, // Requires human review }); // Critical events trigger immediate notification if (isCriticalEvent(eventType)) { await notifyOnCallStaff(userId, eventType); } }
typescript// NEVER use real crisis content in tests describe('Crisis Detection', () => { it('detects high-risk indicators', () => { // Use clearly artificial test phrases const result = assessCrisisLevel( '[TEST_HIGH_RISK_INDICATOR]', [], [] ); expect(result.level).toBe('high'); }); it('provides appropriate resources', () => { const response = getCrisisResponse('high'); expect(response).toContain('988'); expect(response).toContain('Crisis Text Line'); }); });
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-08 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-16 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-07 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-10 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-09 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-22 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-11 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-06 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-05 | pass→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-18 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-13 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-17 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-14 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-01 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-19 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-04 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-02 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-20 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-03 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-15 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-12 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-21 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +45 percentage points is the difference between those two pass rates over the 22 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
The per-case answers from this run were removed by the retention sweep, so the case table below shows the verdicts without the text either arm produced. The counts above were recorded at the time and are unaffected. Answers are now kept for 180 days.
Other measured skills in the registry, with their headline benchmark lift.