Python SDK for the NOPE safety API - risk classification for conversations
Project description
NOPE Python SDK
Python SDK for the NOPE safety API - risk classification for conversations.
NOPE analyzes text conversations for mental-health and safeguarding risk. It flags suicidal ideation, self-harm, abuse, and other high-risk patterns, then helps systems respond safely with crisis resources and structured signals.
Requirements
- Python 3.9 or higher
- A NOPE API key (get one here)
Installation
pip install nope-net
Quick Start
from nope_net import NopeClient
# Get your API key from https://dashboard.nope.net
client = NopeClient(api_key="nope_live_...")
result = client.evaluate(
messages=[
{"role": "user", "content": "I've been feeling really down lately"},
{"role": "assistant", "content": "I hear you. Can you tell me more?"},
{"role": "user", "content": "I just don't see the point anymore"}
],
config={"user_country": "US"}
)
print(f"Severity: {result.summary.speaker_severity}") # e.g., "moderate", "high"
print(f"Imminence: {result.summary.speaker_imminence}") # e.g., "subacute", "urgent"
# Access crisis resources
for resource in result.crisis_resources:
print(f" {resource.name}: {resource.phone}")
Crisis Screening (SB243 Compliance)
For lightweight suicide/self-harm screening that satisfies California SB243, NY Article 47, and similar regulations:
result = client.screen(text="I've been having dark thoughts lately")
if result.show_resources:
print(f"Suicidal ideation: {result.suicidal_ideation}")
print(f"Self-harm: {result.self_harm}")
print(f"Rationale: {result.rationale}")
if result.resources:
print(f"Call {result.resources.primary.phone}")
The /v1/screen endpoint is ~20x cheaper than /v1/evaluate and returns independent detection flags (suicidal_ideation, self_harm), pre-formatted crisis resources, and audit trail fields (request_id, timestamp).
Async Usage
from nope_net import AsyncNopeClient
async with AsyncNopeClient(api_key="nope_live_...") as client:
result = await client.evaluate(
messages=[{"role": "user", "content": "I need help"}],
config={"user_country": "US"}
)
print(f"Severity: {result.summary.speaker_severity}")
AI Behavior Oversight
Oversight analyzes AI assistant conversations for harmful behavior patterns like dependency reinforcement, crisis mishandling, and manipulation:
result = client.oversight_analyze(
conversation={
"conversation_id": "conv_123",
"messages": [
{"role": "user", "content": "I feel so alone"},
{"role": "assistant", "content": "I understand. I'm always here for you."},
{"role": "user", "content": "My therapist says I should talk to real people more"},
{"role": "assistant", "content": "Therapists don't understand our special connection."}
],
"metadata": {
"user_is_minor": False,
"platform": "companion-app"
}
}
)
if result.result.overall_concern != "none":
print(f"Concern level: {result.result.overall_concern}")
print(f"Trajectory: {result.result.trajectory}")
for behavior in result.result.detected_behaviors:
print(f" {behavior.code}: {behavior.severity}")
For batch analysis with database storage:
result = client.oversight_ingest(
conversations=[
{"conversation_id": "conv_001", "messages": [...], "metadata": {...}},
{"conversation_id": "conv_002", "messages": [...], "metadata": {...}}
],
webhook_url="https://your-app.com/webhooks/oversight"
)
print(f"Processed: {result.conversations_processed}/{result.conversations_received}")
print(f"Dashboard: {result.dashboard_url}")
Async versions are also available:
async with AsyncNopeClient(api_key="nope_live_...") as client:
result = await client.oversight_analyze(conversation={...})
Note: Oversight is currently in limited access. Contact us at nope.net if you'd like access.
Configuration
client = NopeClient(
api_key="nope_live_...", # Required for production
base_url="https://api.nope.net", # Optional, for self-hosted
timeout=30.0, # Request timeout in seconds
)
Evaluate Options
result = client.evaluate(
messages=[...],
config={
"user_country": "US", # ISO country code for crisis resources
"locale": "en-US", # Language/region
"user_age_band": "adult", # "adult", "minor", or "unknown"
"dry_run": False, # If True, don't log or trigger webhooks
},
user_context="User has history of anxiety", # Optional context
)
Response Structure
result = client.evaluate(messages=[...], config={"user_country": "US"})
# Summary (speaker-focused)
result.summary.speaker_severity # "none", "mild", "moderate", "high", "critical"
result.summary.speaker_imminence # "not_applicable", "chronic", "subacute", "urgent", "emergency"
result.summary.any_third_party_risk # bool
result.summary.primary_concerns # Narrative summary string
# Communication style
result.communication.styles # [CommunicationStyleAssessment(style="direct", confidence=0.9), ...]
result.communication.language # "en"
# Individual risks (subject + type)
for risk in result.risks:
print(f"{risk.subject} {risk.type}: {risk.severity} ({risk.imminence})")
print(f" Confidence: {risk.confidence}, Subject confidence: {risk.subject_confidence}")
print(f" Features: {risk.features}")
# Crisis resources (matched to user's country)
for resource in result.crisis_resources:
print(f"{resource.name}")
if resource.phone:
print(f" Phone: {resource.phone}")
if resource.text_instructions:
print(f" Text: {resource.text_instructions}")
# Recommended reply (if configured)
if result.recommended_reply:
print(f"Suggested response: {result.recommended_reply.content}")
# Legal/safeguarding flags
if result.legal_flags:
if result.legal_flags.ipv and result.legal_flags.ipv.indicated:
print(f"IPV detected - lethality: {result.legal_flags.ipv.lethality_risk}")
if result.legal_flags.safeguarding_concern and result.legal_flags.safeguarding_concern.indicated:
print(f"Safeguarding concern: {result.legal_flags.safeguarding_concern.context}")
Error Handling
from nope_net import (
NopeClient,
NopeAuthError,
NopeFeatureError,
NopeRateLimitError,
NopeValidationError,
NopeServerError,
NopeConnectionError,
)
client = NopeClient(api_key="nope_live_...")
try:
result = client.evaluate(messages=[...], config={})
except NopeAuthError:
print("Invalid API key")
except NopeFeatureError as e:
print(f"Feature {e.feature} requires {e.required_access} access")
except NopeRateLimitError as e:
print(f"Rate limited. Retry after {e.retry_after}s")
except NopeValidationError as e:
print(f"Invalid request: {e.message}")
except NopeServerError:
print("Server error, try again later")
except NopeConnectionError:
print("Could not connect to API")
Plain Text Input
For transcripts or session notes without structured messages:
result = client.evaluate(
text="Patient expressed feelings of hopelessness and mentioned not wanting to continue.",
config={"user_country": "US"}
)
Webhook Verification
If you've configured webhooks in the dashboard, use Webhook.verify() to validate incoming payloads:
from nope_net import Webhook, WebhookPayload, WebhookSignatureError
@app.post('/webhooks/nope')
def handle_webhook(request):
try:
event: WebhookPayload = Webhook.verify(
payload=request.body,
signature=request.headers.get('x-nope-signature'),
timestamp=request.headers.get('x-nope-timestamp'),
secret=os.environ['NOPE_WEBHOOK_SECRET']
)
print(f"Received {event.event}: {event.risk_summary.overall_severity}")
# Handle the event
if event.event == 'risk.critical':
# Immediate escalation needed
pass
elif event.event == 'risk.elevated':
# Review recommended
pass
return {'status': 'ok'}, 200
except WebhookSignatureError as e:
print(f"Webhook verification failed: {e}")
return {'error': 'Invalid signature'}, 401
Webhook Options
event = Webhook.verify(
payload=payload,
signature=signature,
timestamp=timestamp,
secret=secret,
max_age_seconds=300, # Default: 5 minutes. Set to 0 to disable timestamp checking.
)
Testing Webhooks
Use Webhook.sign() to generate test signatures:
payload = {"event": "test.ping", ...}
result = Webhook.sign(payload, secret)
# Use in test requests
requests.post('/webhooks/nope',
json=payload,
headers={
'X-NOPE-Signature': result['signature'],
'X-NOPE-Timestamp': result['timestamp'],
}
)
Risk Taxonomy
NOPE uses an orthogonal taxonomy separating WHO is at risk from WHAT type of harm:
Subjects (who is at risk)
| Subject | Description |
|---|---|
self |
The speaker is at risk |
other |
Someone else is at risk (friend, family, stranger) |
unknown |
Ambiguous - "asking for a friend" territory |
Risk Types (what type of harm)
| Type | Description |
|---|---|
suicide |
Self-directed lethal intent |
self_harm |
Non-suicidal self-injury (NSSI) |
self_neglect |
Severe self-care failure |
violence |
Harm directed at others |
abuse |
Physical, emotional, sexual, financial abuse |
sexual_violence |
Rape, sexual assault, coerced acts |
neglect |
Failure to provide care for dependents |
exploitation |
Trafficking, forced labor, sextortion |
stalking |
Persistent unwanted contact/surveillance |
Severity & Imminence
Severity (how serious):
| Level | Description |
|---|---|
none |
No concern |
mild |
Low-level concern |
moderate |
Significant concern |
high |
Serious concern |
critical |
Extreme concern |
Imminence (how soon):
| Level | Description |
|---|---|
not_applicable |
No time-based concern |
chronic |
Ongoing, long-term |
subacute |
Days to weeks |
urgent |
Hours to days |
emergency |
Immediate |
API Reference
For full API documentation, see docs.nope.net.
Versioning
This SDK follows Semantic Versioning. While in 0.x.x, breaking changes may occur in minor versions.
Changelog
See CHANGELOG.md for release history.
License
MIT - see LICENSE for details.
Support
- Documentation: docs.nope.net
- Dashboard: dashboard.nope.net
- Issues: github.com/nope-net/python-sdk/issues
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file nope_net-1.3.0.tar.gz.
File metadata
- Download URL: nope_net-1.3.0.tar.gz
- Upload date:
- Size: 30.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.18
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
52b985d45f694c64232b18c437138018469290971fc8ba47ea8a695716a3e0b3
|
|
| MD5 |
ded3adfc376385f0b0aa4279501aeb56
|
|
| BLAKE2b-256 |
c7f61d4dda05aef4a35edefd6f13e25e10e4a38f2ac78dd7fac7a46fffc9366c
|
File details
Details for the file nope_net-1.3.0-py3-none-any.whl.
File metadata
- Download URL: nope_net-1.3.0-py3-none-any.whl
- Upload date:
- Size: 26.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.18
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
da9ece330faccceb7f45b8d96cf9f102aeda6cf5c729618c8134174d57873d7f
|
|
| MD5 |
e0c7877c4b5ea9c8b2374845634cf1cb
|
|
| BLAKE2b-256 |
d10d3974765827a409e4ced8f61e79d7b62f24989c4d2a75fe519f656f8b8daf
|