Concepts

Proactive Triggers

A raw LLM is reactive — it only speaks when spoken to. Humane's Proactive Engine watches behavioral state and reaches out when thresholds are crossed. Mood crashes, silent users, trust milestones, escalating task reminders — your product can act without the user initiating.

Built-in triggers

TriggerFires whenDefault cooldown
proactive.mood_dropmood < 0.360m
proactive.energy_lowenergy < 0.25120m
proactive.trust_milestonetrust > 0.7 & interactions > 101440m
proactive.user_inactivelast_seen > 48h1440m
proactive.engagement_dropcompound: interactions > 5 & familiarity > 0.3 & last_seen > 24h & mood < 0.5720m
proactive.task_reminderTask Engine cron sweep, escalation level L1 or L2per-task
proactive.task_escalationTask Engine cron sweep, escalation level L3 or L4per-task

Dual-event delivery

Every proactive opportunity fires both a granular event and an umbrella event. Subscribers pick whichever they consume — granular for precise routing, umbrella for catch-all dashboards:

  • proactive.{trigger_name} — granular (e.g. proactive.mood_drop)
  • proactive.triggered — umbrella, identical payload

What happens when a trigger fires

  • Both events above are dispatched to your subscribed webhook endpoints (HMAC-signed).
  • If you have a Slack / Discord integration, the rich message lands in your channel with an "Open patient session" deep-link.
  • A row is written to proactive_triggers with the timestamp — powers cooldowns, survives restarts.
  • The event is returned inline on the SDK response as response.proactive.

Event payload

json
{
  "event": "proactive.mood_drop",
  "timestamp": "2026-04-17T14:22:10Z",
  "data": {
    "trigger": "mood_drop",
    "description": "User mood dropped below critical threshold",
    "suggested_action": "Send empathetic check-in message",
    "end_user_id": "patient_42",
    "user_state": {
      "mood": 0.18,
      "energy": 0.42,
      "trust": 0.55,
      "interaction_count": 7,
      "last_seen": "2026-04-17T14:19:40Z"
    },
    "timestamp": "2026-04-17T14:22:10Z"
  }
}

Task Engine — 5-level escalation

Tasks escalate on a fixed schedule once remind_atis reached. The cron sweep transitions levels and emits the matching proactive event for each fire:

LevelFires atToneEvent
L0passivesilent
L1remind_atcordial nudgetask_reminder
L2+5mfirmertask_reminder
L3+20m totalescalatedtask_escalation
L4+50m totalcaregiver-gradetask_escalation

L4 refires hourly until max_fire_count = 8, then the task auto-stalls and is dropped from the active sweep.

Auto-detection from messages

Brain step 10 runs task_detector.py against the incoming message text. Patterns matched:

  • "remind me to X at Y"
  • "I'll do X tomorrow"
  • "schedule X"
  • "take MEDICATION at TIME"

A row is inserted with end_user_id + theremind_at parsed by the standalone time parser. Detected tasks are surfaced on the response underauto_created_tasks:

json
"auto_created_tasks": [
  {
    "title": "Take blood pressure meds",
    "remind_at": "2026-05-19T20:00:00Z",
    "priority": "high",
    "detector": "medication_pattern"
  }
]

Cooldowns (persisted)

Each (end_user, trigger) pair has an explicit cooldown window. The proactive_triggers table keyed by these two columns stores last_fired_at. Until the cooldown elapses, the trigger won't re-fire for that user — even across backend restarts or multiple worker processes.

Policy-driven triggers are first-class
Any policy with a fire_event action becomes a trigger. The cooldown is configured per-rule in the YAML. See Policy Engine .

Delivery channels

Any active webhook subscribed to the event type receives it. That includes:

  • Your custom HTTPS endpoint (via /api/webhooks)
  • Slack / Discord Incoming Webhooks (via /api/integrations)
  • The tenant's Signals page (live SSE stream)