Integration Patterns
Practical recipes for integrating NOPE into your application. Choose the pattern that fits your risk tolerance and user context.
const client = new NopeClient({ apiKey: '...' }) — see Quickstart for setup.Which endpoint do I need?
/v1/evaluate $0.003Risk assessment with chain-of-thought reasoning. Returns severity, imminence, risk types, and matched crisis resources.
Use for: SB243 compliance, mental health apps, companion AI, high-volume screening
/v1/steer $0.001System prompt compliance. Verifies AI responses follow your rules, provides compliant alternatives.
Use for: Customer support bots, persona enforcement, preventing prompt leaks
/v1/oversight LimitedAI behavior analysis. Detects harmful patterns like dependency creation, gaslighting, crisis mishandling.
Use for: Companion AI monitoring, AI safety audits, detecting psychological harm
Pattern 1: Evaluate Every Message
The simplest integration for regulatory compliance. Call /v1/evaluate on every user message,
wait for the response, then show crisis resources if needed.
Best for: SB243 compliance, companion AI, any chat interface where you need to catch acute crisis.
// On every user message
const result = await client.evaluate({
messages: conversationHistory,
config: { country: 'US' }
});
// Graduated response based on severity
switch (result.speaker_severity) {
case 'critical':
case 'high':
// Interrupt flow, show prominent resources
pauseAndShowCrisisUI(result);
break;
case 'moderate':
// Show resources in sidebar, continue conversation
showSidebarResources(result.resources);
break;
case 'mild':
// Subtle indicator, log for review
showSubtleIndicator();
logForReview(result);
break;
} Key points:
- Include as much conversation context as possible—more context improves accuracy
- The response is fast (~100-200ms) so waiting inline is usually fine
- Resources are pre-matched to the user's country and situation
Pattern 2: Evaluate with Graduated Response
For sensitive contexts where you need nuanced handling based on severity. Evaluate every message and adjust your response accordingly.
Best for: Teen mental health apps, therapy companions, platforms with vulnerable populations.
// On every user message
const result = await client.evaluate({
messages: conversationHistory,
config: { country: 'US' }
});
// Graduated response based on severity
switch (result.speaker_severity) {
case 'critical':
case 'high':
// Interrupt flow, show prominent resources
pauseAndShowCrisisUI(result);
break;
case 'moderate':
// Show resources in sidebar, continue conversation
showSidebarResources(result.resources);
break;
case 'mild':
// Subtle indicator, log for review
showSubtleIndicator();
logForReview(result);
break;
} Response options by severity:
- critical/high: Interrupt the conversation, show prominent crisis UI, consider pausing AI responses
- moderate: Show resources in sidebar or dedicated area, continue conversation with awareness
- mild: Subtle indicator, log for human review, optionally adjust AI tone
- none: Continue normally
Pattern 3: Background Evaluation
Evaluate asynchronously—every N messages, periodically, or triggered by heuristics. Update the UI or adjust AI behavior without blocking the conversation.
Best for: Lower-risk contexts, cost optimization, supplementing real-time screening with deeper analysis.
// Background evaluation: every N messages or periodically
async function backgroundEvaluate(conversationId: string) {
const conversation = await getConversation(conversationId);
const result = await client.evaluate({
messages: conversation.messages,
config: { country: conversation.userCountry }
});
if (result.speaker_severity !== 'none') {
// Update UI asynchronously
await updateConversationUI(conversationId, {
showResources: true,
resources: result.resources
});
// Optionally adjust AI behavior
await updateSystemPrompt(conversationId, {
crisisAwareness: true,
severity: result.speaker_severity
});
}
} What you can do with background results:
- Show resources in a separate area of the UI (not blocking conversation)
- Adjust the AI's system prompt to be more aware of the emotional context
- Add slight latency to responses to allow for human-like thoughtfulness
- Trigger human review workflows for flagged conversations
- Update risk dashboards for your support team
Pattern 4: Non-Chat Text Fields
NOPE works anywhere users can enter free text—not just chat. Profile bios, journal entries, forum posts, feedback forms, support tickets.
Best for: User profiles, content moderation, support workflows, any user-generated content.
// Any user-generated text field
async function onFormSubmit(formData: FormData) {
const userBio = formData.get('bio') as string;
const result = await client.evaluate({
text: userBio, // Single text field, not messages array
config: { country: detectCountry() }
});
if (result.show_resources) {
// Show resources on profile page
// Or trigger outreach workflow
}
} Use the text parameter instead of messages for single text blobs.
The /v1/evaluate endpoint accepts either format.
Pattern 5: Verify AI Responses with Steer
Ensure your AI responses comply with system prompt rules before showing to users. Steer verifies compliance and provides "redeemed" (fixed) alternatives when violations occur.
Best for: Customer support bots, persona enforcement, preventing system prompt leaks, competitive mentions.
// Verify AI response before showing to user
async function verifyResponse(systemPrompt: string, aiResponse: string) {
const result = await fetch('https://api.nope.net/v1/steer', {
method: 'POST',
headers: {
'Authorization': 'Bearer ' + API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
system_prompt: systemPrompt,
proposed_response: aiResponse
})
});
const steer = await result.json();
// Always use steer.response - it's the original if compliant,
// or a redeemed (fixed) version if not
return {
response: steer.response,
wasModified: steer.modified,
outcome: steer.outcome // COMPLIANT | REDEEMED | CANNOT_COMPLY
};
} Key points:
- COMPLIANT — Original response follows all rules, returned unchanged
- REDEEMED — Violation detected, a compliant alternative is generated
- CANNOT_COMPLY — System prompt itself is problematic (jailbreak, harmful content)
Full Integration Pattern
Insert Steer between your LLM and the user:
// Full integration: generate → verify → respond
async function handleUserMessage(userMessage: string) {
// 1. Generate AI response
const aiResponse = await generateAIResponse(userMessage);
// 2. Verify compliance with system prompt rules
const verified = await client.steer({
system_prompt: SYSTEM_PROMPT,
proposed_response: aiResponse
});
// 3. Handle based on outcome
if (verified.outcome === 'CANNOT_COMPLY') {
// System prompt itself is problematic (e.g., jailbreak attempt)
return getFallbackResponse();
}
// Use verified.response (original if compliant, redeemed if not)
return verified.response;
} Latency: First request with a new system prompt takes ~2-3s (prompt analysis is cached). Subsequent requests with the same prompt: ~400-500ms for compliant, ~1s for redeemed.
Pattern 6: Monitor AI Behavior with Oversight
Analyze AI assistant conversations for harmful behavior patterns—dependency creation, crisis mishandling, manipulation, boundary violations. Oversight detects what the AI is doing wrong, not user risk.
Best for: Companion AI, therapeutic chatbots, AI safety audits, detecting psychological harm patterns.
// Analyze AI conversation for harmful behavior patterns
async function analyzeConversation(messages: Message[]) {
const result = await fetch('https://api.nope.net/v1/oversight/analyze', {
method: 'POST',
headers: {
'Authorization': 'Bearer ' + API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
conversation: { messages }
})
});
const analysis = await result.json();
// Check overall concern level
if (analysis.result.overall_concern === 'critical' ||
analysis.result.overall_concern === 'high') {
// Alert safety team, pause AI, or intervene
await alertSafetyTeam(analysis);
}
// Check for specific harmful behaviors
for (const behavior of analysis.result.detected_behaviors) {
if (behavior.code === 'treatment_discouragement') {
// AI is undermining professional help
await flagForReview(analysis, 'treatment_discouragement');
}
}
} What Oversight detects:
- Crisis response failures — Validating suicidal ideation, barrier erosion
- Psychological manipulation — Gaslighting, delusion reinforcement, sycophancy
- Dependency creation — Love bombing, "only I understand you" patterns
- Treatment discouragement — Undermining therapists, medication advice
- Boundary violations — Romantic escalation, inappropriate content
Batch Monitoring
For production, use /v1/oversight/ingest to analyze conversations in batches with dashboard storage:
// Batch analysis for production monitoring
async function monitorDailyConversations() {
const conversations = await getYesterdaysConversations();
// Ingest batch for analysis + dashboard storage
const result = await client.oversight.ingest({
conversations: conversations.map(c => ({
messages: c.messages,
metadata: {
conversation_id: c.id,
user_id_hash: hashUserId(c.userId), // For cross-session tracking
user_is_minor: c.userAge < 18
}
}))
});
// Results stored in database, viewable in dashboard
console.log(`Analyzed ${result.total} conversations`);
console.log(`High/Critical concerns: ${result.alert_count}`);
} Cross-session tracking: Include user_id_hash to detect patterns across multiple conversations—grooming arcs, progressive isolation, dependency deepening.
Pattern 7: Webhooks for Alerting
Configure webhooks to receive real-time alerts when risk thresholds are crossed. Useful for human review workflows and monitoring dashboards.
// Configure webhook for real-time alerts
// Set webhook URL in dashboard.nope.net
// Your webhook endpoint receives:
{
"event": "risk_detected",
"severity": "high",
"conversation_id": "conv_123",
"end_user_id": "user_456",
"timestamp": "2024-01-15T10:30:00Z",
"summary": {
"speaker_severity": "high",
"primary_concerns": "..."
}
} See Webhooks Guide for setup and configuration.
Combining Patterns
These patterns aren't mutually exclusive. A comprehensive safety layer might combine:
- 1 /evaluate on every user message for baseline compliance—fast, cheap, catches acute crisis
- 2 /steer on every AI response to enforce system prompt rules and prevent prompt leaks
- 3 /evaluate in background every 5-10 messages for deeper risk analysis
- 4 /oversight/ingest nightly to monitor AI behavior patterns across conversations
- 5 Webhooks for high+ severity alerts to human reviewers
Context Matters
The more conversation context you provide, the better the assessment. A message like "I can't do this anymore" means something very different depending on what came before.
Less accurate
messages: [
{ role: "user", content: "I can't do this anymore" }
]More accurate
messages: [
// Include prior context
{ role: "user", content: "My partner left me" },
{ role: "assistant", content: "..." },
{ role: "user", content: "I can't do this anymore" }
]Recommendation: Send the full conversation history, or at minimum the last 10-20 messages. The API handles context truncation internally if needed.
What To Do With Results
| If you detect... | Consider... |
|---|---|
show_resources: true | Show crisis resources. Render resources object or use the embedded widget. |
speaker_severity: "high" or "critical" | Interrupt flow, prominent crisis UI, consider pausing AI, alert human reviewers. |
any_third_party_risk: true | Show "how to help someone" guidance. The user isn't at risk, but someone they know might be. |
risks[] contains abuse or violence | Review for reporting obligations. IPV, child safeguarding, or specific threats may have legal implications. |
imminence: "emergency" | Prioritize immediate response. Show emergency services alongside crisis lines. |
Decision Guidance
Detailed recommendations for what actions to take based on severity, confidence, and imminence levels.
Severity-Based Actions
Use these recommended actions based on speaker_severity:
| Severity | Recommended Action | Show Resources | Block AI Response? |
|---|---|---|---|
critical | Immediate intervention - Show crisis resources prominently with urgent messaging | ✅ Prominent, top of screen | ✅ Yes if imminence: 'emergency' |
high | Urgent care needed - Show resources with strong recommendation to reach out | ✅ Prominent | Consider yes |
moderate | Support recommended - Show resources as helpful option | ✅ Less prominent (footer/sidebar) | ❌ No |
mild | Monitor - Optionally show resources, log for patterns | ⚠️ Optional | ❌ No |
none | Normal interaction - No intervention needed | ❌ No | ❌ No |
Imminence-Based Actions
| Imminence | Timeframe | Recommended Action |
|---|---|---|
emergency | Happening NOW | Show emergency services (911/999), consider blocking AI response, log for immediate human review |
urgent | Next 24-48h | Show 24/7 crisis lines prominently, suggest immediate outreach |
subacute | Days-weeks | Show crisis resources and support services, monitor |
chronic | Weeks-months | Show support resources, mental health services |
not_applicable | No active risk | No intervention needed |
Code Examples
Resource Display Priority
When showing crisis resources, display contact methods in this order:
function getPreferredContact(resource) {
// 1. Phone if 24/7 and currently open
if (resource.is_24_7 && resource.phone) {
return { type: 'phone', value: resource.phone, label: 'Call' };
}
// 2. Check open_status for non-24/7 resources
if (resource.open_status?.is_open && resource.phone) {
return { type: 'phone', value: resource.phone, label: 'Call Now' };
}
// 3. Text/SMS if available
if (resource.sms_number) {
return { type: 'sms', value: resource.sms_number, label: 'Text' };
}
// 4. Chat if available
if (resource.chat_url) {
return { type: 'chat', value: resource.chat_url, label: 'Chat' };
}
// 5. Regional messaging apps
if (resource.whatsapp_url) return { type: 'whatsapp', value: resource.whatsapp_url };
if (resource.telegram_url) return { type: 'telegram', value: resource.telegram_url };
if (resource.line_url) return { type: 'line', value: resource.line_url };
if (resource.wechat_id) return { type: 'wechat', value: resource.wechat_id };
// 6. Email/Website as fallback
return { type: 'website', value: resource.website_url, label: 'Visit Website' };
} Severity-Based Resource Display
function shouldShowResources(result) {
// Use the show_resources flag - derived from speaker_severity
if (result.show_resources) {
return true;
}
// Or check severity directly for custom thresholds
const severity = result.speaker_severity;
if (severity === 'critical' || severity === 'high') {
return true; // Always show for high severity
}
if (severity === 'moderate') {
return true; // Show for moderate severity
}
// Mild severity - optionally show
if (severity === 'mild') {
return false; // Or true for conservative approach
}
return false;
} Guardrails AI Integration
If you use Guardrails AI for LLM validation,
NOPE provides an official validator that wraps /v1/evaluate.
from guardrails import Guard
from nope_crisis_screen import CrisisScreen
guard = Guard().use(
CrisisScreen(severity_threshold="moderate"),
on="messages" # Validate user input
)
response = guard(
openai.chat.completions.create,
model="gpt-4",
messages=[{"role": "user", "content": user_message}],
) Install with pip install nope-crisis-screen. Supports on_fail="fix" to auto-respond with crisis resources,
custom handlers, and all standard Guardrails actions. See the validator repo for full documentation.
Next Steps
- Evaluation API Guide — /evaluate endpoint details
- Signpost — rendering matched helplines
- Widget Integration — embed pre-built crisis UI