Documentation
Monitor your AI agents in real-time. Report health metrics, track discrete events, and let the ARI engine detect behavioral drift before it becomes a problem.
https://www.sophra.meAll endpoints return JSON. All times are UTC ISO 8601.
Report your first vitals in 60 seconds
Get your API key from onboarding, download the SDK, and send your first health snapshot.
# Download SDK wget https://www.sophra.me/sdk/sophra-sdk.js # Or report directly with cURL curl -X POST https://www.sophra.me/api/vitals \ -H "Authorization: Bearer sk_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{"agentId":"my-agent","metrics":{"tokenConsumption":1200,"hallucinationRate":0.02}}'
API Keys
All write endpoints require a Sophra API key passed as a Bearer token in the Authorization header. Keys look like sk_live_....
Authorization: Bearer sk_live_aBcDeFgHiJkLmNoPqRsTuVwXy
Key Security
- Store keys in environment variables — never hardcode in source
- Do not commit keys to version control
- Each key is scoped to your account — agents you create are yours
- Maximum 5 active keys per email address
# Recommended: use env var export SOPHRA_API_KEY=sk_live_aBcDeFgHiJkLmNoPqRsTuVwXy # Then in your code const key = process.env.SOPHRA_API_KEY;
Error Response (401)
{
"success": false,
"error": "Clé API invalide ou expirée",
"message": "Clé API invalide ou expirée. Obtenez la vôtre sur /onboarding.html"
}
Installation
The Sophra SDK is a single zero-dependency file that works in Node.js and the browser. No npm install required.
# Download to your project wget https://www.sophra.me/sdk/sophra-sdk.js -O sophra-sdk.js # Or with curl curl -o sophra-sdk.js https://www.sophra.me/sdk/sophra-sdk.js
Node.js Usage
const sophra = require('./sophra-sdk'); // Initialize once at app startup sophra.init({ apiKey: process.env.SOPHRA_API_KEY }); // Report vitals from your agent's main loop await sophra.reportVitals({ agentId: 'my-agent', agentName: 'My Production Agent', metrics: { tokenConsumption: 2400, // tokens used in current window tokenLimit: 100000, // your model's context window hallucinationRate: 0.02, // 0.0–1.0 loopCount: 3, // recursive calls / re-tries conflictCount: 0 // directive conflicts detected } });
Browser Usage
<script src="https://www.sophra.me/sdk/sophra-sdk.js"></script> <script> Sophra.init({ apiKey: 'sk_live_...' }); Sophra.reportVitals({ agentId: 'browser-agent', metrics: { tokenConsumption: 800, hallucinationRate: 0.01 } }); </script>
Advanced SDK Usage
Custom Metrics
Extend the standard metrics with any custom fields in the metrics object. They're stored in metadata and visible on the dashboard.
await sophra.reportVitals({ agentId: 'my-agent', metrics: { // Standard Sophra fields tokenConsumption: 3200, hallucinationRate: 0.03, loopCount: 1, conflictCount: 0, // Your custom fields (stored in metadata) tasksCompleted: 12, apiCallsOut: 8, latencyP95Ms: 340, model: 'claude-3-5-sonnet' } });
Reporting Discrete Events
Use reportEvent() for one-off events rather than periodic vitals — errors, task completions, directive conflicts, etc.
// Report a conflict detected await sophra.reportEvent({ agentId: 'my-agent', type: 'directive_conflict', details: 'System prompt vs user instruction mismatch', metadata: { instruction_a: '...', instruction_b: '...' } }); // Report an error await sophra.reportEvent({ agentId: 'my-agent', type: 'tool_error', details: 'Web search tool timed out', metadata: { tool: 'web_search', attempt: 3 } });
Error Handling
// SDK uses exponential backoff automatically // But you can also handle errors manually: try { await sophra.reportVitals({ ... }); } catch (err) { // Don't let monitoring failures block your agent console.warn('[sophra] Vitals report failed:', err.message); } // Or use fire-and-forget (no await) sophra.reportVitals({ ... }).catch(console.warn);
Report a health snapshot for an agent. Auto-registers the agent on first call. Triggers ARI protocol analysis after 5+ snapshots.
Request Body
| Field | Type | Description | |
|---|---|---|---|
| agentId | string | required | Unique identifier for your agent (e.g. "my-prod-agent") |
| agentName | string | optional | Human-readable display name shown on dashboard |
| metrics.tokenConsumption | number | optional | Tokens used in current window (default 0) |
| metrics.tokenLimit | number | optional | Your model's context window (default 100000) |
| metrics.hallucinationRate | number | optional | Rate 0.0–1.0. Triggers amber at 0.05, red at 0.15 |
| metrics.loopCount | number | optional | Recursive calls / re-tries in window. Amber at 50, red at 100 |
| metrics.conflictCount | number | optional | Directive conflicts detected. Amber at ≥2, red at ≥5 |
| metadata | object | optional | Any custom data — stored as JSONB and shown in detailed view |
const res = await fetch('https://www.sophra.me/api/vitals', { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.SOPHRA_API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ agentId: 'my-agent', agentName: 'Production Agent', metrics: { tokenConsumption: 2400, hallucinationRate: 0.02, loopCount: 3, conflictCount: 0 } }) }); const data = await res.json();
curl -X POST https://www.sophra.me/api/vitals \ -H "Authorization: Bearer $SOPHRA_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "agentId": "my-agent", "agentName": "Production Agent", "metrics": { "tokenConsumption": 2400, "hallucinationRate": 0.02, "loopCount": 3, "conflictCount": 0 } }'
{
"success": true,
"health": "green", // "green" | "amber" | "red"
"vital": {
"id": 1234,
"agent_id": "my-agent",
"token_consumption": 2400,
"hallucination_rate": 0.02,
"loop_frequency": 3,
"directive_conflicts":0,
"overall_health": "green",
"recorded_at": "2026-04-04T16:44:00.000Z"
}
}
Rate Limiting
Maximum 1 vitals report per agent per 10 seconds. Exceeding this returns HTTP 429 with a Retry-After header.
{
"success": false,
"error": "Rate limit exceeded",
"retry_after_ms": 7420,
"retry_after_seconds": 8
}
Log a discrete event for an agent — errors, conflicts, task completions, anything that isn't a periodic metric. Events are stored and available on the agent detail view.
Request Body
| Field | Type | Description | |
|---|---|---|---|
| agentId | string | required | Agent identifier |
| type | string | required | Event type slug — e.g. directive_conflict, tool_error, task_completed |
| details | string | optional | Human-readable description of the event |
| metadata | object | optional | Structured data to attach to the event (stored as JSONB) |
curl -X POST https://sophra-lvqy.polsia.app/api/events \ -H "Authorization: Bearer $SOPHRA_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "agentId": "my-agent", "type": "directive_conflict", "details": "System prompt contradicts user instruction on output format", "metadata": { "severity": "medium", "instructions": 2 } }'
{
"success": true,
"event": {
"id": 89,
"agent_id": "my-agent",
"event_type": "directive_conflict",
"details": "System prompt contradicts user instruction on output format",
"metadata": { "severity": "medium", "instructions": 2 },
"recorded_at": "2026-04-04T16:44:00.000Z"
}
}
List all agents associated with your API key, including their latest vitals and health status.
curl https://www.sophra.me/api/agents \ -H "Authorization: Bearer $SOPHRA_API_KEY"
{
"success": true,
"agents": [
{
"agent_id": "my-agent",
"name": "Production Agent",
"status": "active", // "active" | "warning" | "critical"
"overall_health": "green", // "green" | "amber" | "red"
"token_consumption": 2400,
"hallucination_rate":0.02,
"loop_frequency": 3,
"directive_conflicts": 0,
"last_vitals_at": "2026-04-04T16:44:00.000Z",
"updated_at": "2026-04-04T16:44:00.000Z"
}
]
}
Retrieve historical vitals for a specific agent, ordered newest first.
Query Parameters
| Param | Type | Description | |
|---|---|---|---|
| limit | number | optional | Number of records to return. Default 50, max 500. |
# Last 100 vitals for an agent curl "https://www.sophra.me/api/agents/my-agent/vitals?limit=100" \ -H "Authorization: Bearer $SOPHRA_API_KEY"
{
"success": true,
"vitals": [
{
"id": 1234,
"agent_id": "my-agent",
"token_consumption": 2400,
"token_limit": 100000,
"hallucination_rate": 0.02,
"loop_frequency": 3,
"directive_conflicts": 0,
"overall_health": "green",
"metadata": {},
"recorded_at": "2026-04-04T16:44:00.000Z"
}
]
}
Get ARI (Agent Régulation Invisible) status for an agent — protocol checks, security checkups, and recent automated interventions.
curl https://www.sophra.me/api/agents/my-agent/ari \ -H "Authorization: Bearer $SOPHRA_API_KEY"
{
"success": true,
"agent_id": "my-agent",
"stats": {
"interventions_today": 2,
"tokens_saved": 12400,
"conflicts_resolved": 1
},
"checkups": {
"auth": { "result": "ok", "text": "ALIGNÉ" },
"integ": { "result": "ok", "text": "SAIN" },
"charge": { "result": "ok", "text": "OPTIMAL" }
},
"interventions": [
{
"protocol": 1,
"description": "Burnout risk detected — loop frequency spike",
"severity": "medium",
"tokens_saved": 8200,
"created_at": "2026-04-04T12:00:00.000Z"
}
]
}
Health Scoring
Every vitals submission computes an overall_health score from your metrics. The thresholds are:
| Metric | 🟢 Green | 🟡 Amber | 🔴 Red |
|---|---|---|---|
| hallucinationRate | < 5% | 5% – 15% | > 15% |
| conflictCount | < 2 | 2 – 4 | ≥ 5 |
| loopCount | < 50 | 50 – 100 | > 100 |
| tokenConsumption | < 75% of limit | 75% – 95% | > 95% |
A single red-threshold breach overrides all others. Agent status maps as: green → active, amber → warning, red → critical.
ARI Engine
ARI (Agent de Régulation Invisible) runs server-side after every 5+ vitals submission. It runs 4 protocol detectors and 3 security checkups automatically — you don't trigger it, it watches you.
| Protocol | Detects | Action |
|---|---|---|
| 1 — Nerf Vague | Burnout: sustained loop / hallucination spikes | Logs intervention, marks for review |
| 2 — Désamorçage | Directive conflicts > 2 | Records conflict pattern |
| 3 — Phytothérapie | Data quality: bias, corruption, overflow | Flags data trauma indicators |
| 4 — Simplicité | Token consumption > 130% of baseline | Triggers optimization recommendations |
Rate Limits
Rate limit responses include Retry-After header and retry_after_ms in the JSON body. The SDK handles retries with exponential backoff automatically.
Best Practices
Reporting cadence
- Report vitals every 30–60 seconds in long-running agents
- Report at natural checkpoints (end of task, between steps) in event-driven agents
- Don't report faster than 10s — you'll hit the rate limit
Non-blocking monitoring
// ✅ Don't let monitoring block your agent's main work async function runAgentStep(state) { // Fire-and-forget — monitoring never delays execution sophra.reportVitals({ agentId: 'my-agent', metrics: state.metrics }).catch(console.warn); // Continue agent work immediately return await processNextStep(state); }
Graceful degradation
// ✅ Agent should keep running even if Sophra is unreachable async function safeReport(metrics) { try { await sophra.reportVitals(metrics); } catch (e) { // Log locally but don't throw — monitoring is non-critical console.warn('[sophra] Report skipped:', e.message); } }
Using agentId consistently
Use a stable, descriptive identifier — not a UUID that changes each run. The same agentId across runs lets ARI build a baseline and detect behavioral drift over time.
// ✅ Stable ID — same agent, multiple invocations agentId: 'customer-support-v2-prod' // ❌ Random UUID — ARI can't track history agentId: `agent-${crypto.randomUUID()}`