Skip to content

Proactive reminders and follow-ups

This page is for users and operators who want Raven to offer reminders and follow-up work without a new request each time. It covers enabling, configuring, observing, and stopping Sentinel. Developers should use Proactivity Design and Implementation for the decision pipeline and execution contracts.

Choose the right mechanism

The Proactive Engine includes Sentinel and the time-driven Cron and Heartbeat services. They have different purposes and independent lifecycles:

Mechanism Use it when What starts the work
Sentinel Raven should decide whether a contextual reminder or follow-up is useful A periodic evaluation of memory, recent conversations, and derived signals
Cron You want an explicitly scheduled task or reminder A user-created schedule
Heartbeat You maintain periodic tasks in HEARTBEAT.md Its own timer or an early wake request

Editing an existing Cron job in the web settings keeps its original messaging channel and recipient. Changing its name, instruction, or schedule does not move delivery to the local app. New jobs created there use the local app.

Sentinel is off by default (sentinel.enabled=false). Enabling it does not enable task discovery automatically; disabling it does not disable Cron or Heartbeat. Use Command Reference for their separate commands.

Sentinel can stay silent, send a standalone reminder, append a reminder to a later reply, wait for a session to become idle, or spawn a background task. These are model decisions, not guaranteed schedules: use Cron when the timing must be explicit, and do not rely on Sentinel as the sole alert for a critical deadline.

Before enabling

  • Configure a working model provider; the Planner normally inherits agents.defaults.model. See Quick Start.
  • Configure the messaging channel that should receive reminders and verify that ordinary messages work there.
  • Review which agent-home memory and session data the configured model provider may receive. Sentinel uses these as planning context.
  • Review tool permissions, workspace restrictions, and subagent backends. Enabling Sentinel in the gateway also wires background task spawning; it is not a reminders-only switch.

The steps below use raven gateway, which assembles and runs the Sentinel stack. A standalone raven sentinel command does not start a background service.

Enable and configure

From a source checkout, inspect the saved configuration:

uv run raven sentinel status

Merge the following fragment into your existing config.json (normally ~/.raven/config.json); do not replace your provider or channel settings. Use JSON, not YAML. Replace telegram:123456789 with your own enabled channel and recipient:

{
  "sentinel": {
    "enabled": true,
    "tick_interval_seconds": 1800,
    "task_discovery_targets": ["telegram:123456789"],
    "nudge_policy": {
      "max_nudges_per_hour": 1,
      "max_nudges_per_day": 4,
      "quiet_hours": [23, 7],
      "high_priority_bypasses_limits": false
    }
  }
}

This example uses lower quotas than the defaults and disables the high-priority bypass. Then start the gateway, or restart the gateway process you already run:

uv run raven gateway

For a deployment whose targets and limits are already configured, the switch also has a CLI:

uv run raven sentinel enable

The switch and quota commands update the saved configuration; restart the gateway for them to take effect. Run configuration commands with the same RAVEN_HOME as the gateway. sentinel status reports saved settings, not proof that a running process has reloaded them.

Delivery targets

sentinel.task_discovery_targets supplies destinations for task discovery and plain nudges aimed at the internal sentinel:direct target, such as daily-plan reminders. Plain nudges use these destinations even when task discovery is disabled.

  • "channel:chat_id": a specific recipient; preferable when a channel has multiple conversations.
  • "channel": resolve the most recent recipient in that channel at fire time.
  • "*": expand to enabled gateway channels and resolve their recent recipients.

An empty list leaves the daily discovery batch without a destination. A plain nudge can still target a concrete session. For an internal target such as sentinel:direct, if the configured targets resolve to no recipients (including when the list is empty), the runner falls back to a single most-recent active session, not a broadcast. If no suitable session can be resolved, the nudge has no delivery target. A literal tui target is not automatically forwarded by a gateway that has no matching outlet. Start with one explicit recipient before choosing broadcast.

Frequency and quiet hours

Common settings under sentinel:

Setting Default Meaning
tick_interval_seconds 1800 Evaluation interval in seconds; minimum 60
evaluator_model null Inherit the main model, or select a Planner model
nudge_policy.max_nudges_per_hour 3 Base hourly quota; adaptive and weekend factors can change the effective limit
nudge_policy.max_nudges_per_day 10 Daily policy cap; high priority cannot bypass it
nudge_policy.quiet_hours [23, 7] Quiet window in the runtime host's local time
nudge_policy.high_priority_bypasses_limits true Allow high priority to bypass quiet hours and the hourly quota, subject to policy checks
nudge_policy.min_interval_seconds 300 Minimum interval for the same session
inject_enabled / defer_enabled true / true Wire reply-appended and delayed reminders; disabling one leaves its decisions unexecuted

To change the two quotas without editing JSON:

uv run raven sentinel config set --max-nudges-per-hour 1 --max-nudges-per-day 4

Restart afterward. These are Sentinel policy limits, not account-wide billing caps. User-scheduled Cron jobs bypass the policy check; when the shared ledger is wired, their fires still consume counters seen by Sentinel, except a run the model ends with [SILENT].

The policy is not a strict send-time barrier for queued messages. Injects are checked and charged when queued; deferred reminders are checked at registration but currently lack a send-time recheck and quota-recording callback. To keep Sentinel nudges out of quiet windows, also disable inject, defer, and the high-priority bypass, or keep Sentinel off. This does not silence Cron or already-running tasks. See Policy boundaries.

Optional task discovery

Task discovery proposes a numbered menu of tasks. It is separately opt-in. Merge these fields into the same sentinel object, retaining your delivery targets:

{
  "task_discovery_enabled": true,
  "task_discovery_time": "08:00",
  "task_discovery_require_confirm": true
}

The daily batch runs on a Sentinel tick after the configured local time, not at an exact minute. Targets default to an empty list, so enabling discovery alone does not deliver a menu. By default a menu has at most four options and expires after 60 minutes.

Reply with /pick N in the same conversation for deterministic option selection without a classifier call. Bare numbers and natural-language choices require a configured model provider and model for the classifier, and sufficient confidence in its result. Without that classifier, use /pick N to select an option. Then answer the confirmation if requested. A selected option can start agent work, invoke a tool, spawn a subagent, or confirm a learned routine. The confirmation setting applies to menu choices; it is not an approval step for every Planner-generated spawn_agent decision.

Inspect and troubleshoot

These commands inspect saved settings or persisted state:

uv run raven sentinel status
uv run raven sentinel nudges
uv run raven sentinel decisions
uv run raven sentinel routines
uv run raven sentinel attention
uv run raven sentinel behaviors

To inspect one planning decision when Sentinel is enabled:

uv run raven sentinel tick --dry-run

Dry-run disables nudge execution and task discovery, but still runs planning and state maintenance: it may call the model and refresh derived state. It is not a read-only check or a free preview. The CLI's --live mode uses a headless sink for dispatcher output, including plain nudges and discovery menus; it does not verify delivery to a real channel.

Symptom Check
Saved settings say enabled, but nothing runs Restart the gateway and check its startup output; confirm it uses the same configuration home
A tick returns skip Often normal: quiet hours, unchanged context, or no useful action; inspect reason and route
Decision exists, but no message arrives Check the recipient, enabled channel, policy denial, queue expiry, and no_delivery_target / degraded:... result
No task menu appears Check the separate discovery switch, non-empty targets, local time, quota, and menu expiry
No routines or behaviors appear Routine learning needs enough parseable history; behavior extraction is separately off by default
Reminders are too frequent Lower quotas, review high-priority bypass, and inspect Cron separately

Replying /dismiss after a recent nudge in the same session records dismissal and starts a cooldown. An ordinary reply is recorded as neutral, not automatically as acceptance. Neither is a global stop command.

Costs and safety limits

A tick that reaches the Planner makes a model request; provider retries can add requests. Fast paths can skip that request. Task discovery, optional daily analysis, routine validation, behavior extraction, and spawned tasks can add their own model or tool costs. A 30-minute interval is not a total cost cap.

The Planner may receive memory, recent conversation excerpts, selected attention.md sections, and folded behavior events. Runtime state and feedback persist across restarts; see State and feedback for the files and their roles.

A spawned task uses the selected subagent backend. The built-in raven-loop backend has an iteration cap and omits messaging and recursive-spawn tools. However, tools.restrict_to_workspace defaults to false, and ProactiveSpawn does not force it on or add an overall task timeout. External ACP and CLI agents run as host processes. Review Sandbox for what isolation does and does not cover.

Disable Sentinel

uv run raven sentinel disable

Restart the gateway to stop its Sentinel stack. The command alone does not stop a currently running stack, cancel an already-dispatched task, remove state, or disable Cron and Heartbeat. If you need an immediate stop, stop the running gateway and inspect any remaining external agent processes separately. Persisted queues are not cleared by disabling; inspect them before re-enabling.

Implementation reference

The implementation sections formerly on this page now live in Proactivity Design and Implementation. Older section links land on the matching entry below: