Engagement

ScalyClaw can proactively reach out when something actionable happens. This isn't spam — it's useful, timely context delivered to the right channel at the right moment.

Proactive System

The proactive system monitors for triggers and sends messages to your preferred channel without you having to ask first. Jobs are dispatched through the BullMQ proactive queue, processed by the same worker that handles all other queue work.

Before sending anything, the system checks two conditions:

  • Quiet hours — if the current time falls inside the configured quiet window, the message is held until the window ends.
  • Cooldown — a minimum gap between any two proactive messages prevents bursts even when multiple triggers fire at once.

The following config keys control proactive engagement. All values are stored in Redis at scalyclaw:config and editable from the dashboard.

KeyTypeDefaultDescription
enabled boolean false Master switch. Set to false to disable all proactive messages without touching any other setting.
model string Model used to generate proactive messages. Defaults to the main orchestrator model if not set.
cronPattern string "*/15 * * * *" How often the proactive system checks for triggers. Defaults to every 15 minutes. Uses standard five-field cron syntax.
idleThresholdMinutes number (minutes) 120 How long the conversation must be silent before an idle trigger fires. Measured from the timestamp of the last message in any channel.
cooldownSeconds number (seconds) 14400 Minimum time in seconds that must elapse between two proactive messages, regardless of trigger type. Default is 14400 seconds (4 hours). Prevents back-to-back pings.
maxPerDay number 3 Maximum number of proactive messages that can be sent in a single calendar day. Once the limit is reached, all further proactive messages are suppressed until the next day.
quietHours.enabled boolean false Whether the quiet-hours window is active. Set to true to suppress proactive messages between start and end.
quietHours.start number (0–23) 23 Start hour of the quiet window (inclusive), in 24-hour local time. E.g. 23 means 11 pm. Proactive messages are suppressed until end.
quietHours.end number (0–23) 7 End hour of the quiet window (exclusive), in 24-hour local time. E.g. 7 means 7 am. The system resumes normal engagement after this hour.
quietHours.timezone string IANA timezone string used to interpret start and end. E.g. "America/New_York". Falls back to the instance timezone if not set.
triggers.undeliveredResults boolean true Fire when a tool or skill result was produced while the user was unreachable and has not yet been delivered.
triggers.firedScheduledItems boolean true Fire when a scheduled reminder or task reaches its trigger time. The scheduler hands the job to the proactive queue; quiet-hours and cooldown checks apply before delivery.
triggers.unansweredMessages boolean false Fire when the user has sent a message that has not received a reply within the idle threshold window. Useful for surfacing stalled conversations.
json
// Proactive engagement config (stored in scalyclaw:config)
{
  "proactive": {
    "enabled": true,
    "model": "claude-sonnet-4-5",
    "cronPattern": "*/15 * * * *",
    "idleThresholdMinutes": 120,
    "cooldownSeconds": 14400,
    "maxPerDay": 3,
    "quietHours": {
      "enabled": true,
      "start": 23,
      "end": 7,
      "timezone": "America/New_York"
    },
    "triggers": {
      "undeliveredResults": true,
      "firedScheduledItems": true,
      "unansweredMessages": false
    }
  }
}

Triggers

A trigger is any condition that tells the proactive system there is something worth surfacing. Each trigger is an independent boolean flag under triggers in the config — enable only the ones that make sense for your workflow.

TriggerDescriptionExample
undeliveredResults Fires when a tool or skill produced a result while the user was unreachable — for example, a background agent completed a task while no conversation was active — and the result has not yet been delivered. The system surfaces the result proactively once the user is reachable. "Your code review agent finished — here's the report it produced."
firedScheduledItems Fires when a scheduled reminder or task reaches its trigger time. The scheduler hands the job off to the proactive queue; the engagement system applies quiet-hours and cooldown checks before delivery. "Good morning! Here is your Monday news summary." (from a recurring cron job)
unansweredMessages Fires when the user has sent a message that ScalyClaw has not yet replied to, and the idle threshold has elapsed since that message was sent. Useful for surfacing stalled conversations caused by transient processing errors. "It looks like I may not have replied to your earlier message — were you still waiting on something?"
Cooldown applies across all trigger types

The cooldownSeconds timer is global, not per-trigger. If a scheduled reminder fires and is delivered, no further proactive message can fire until the cooldown has elapsed — even if another trigger condition is met in that window. This keeps multiple triggers from piling up on the same quiet afternoon.

Guidelines

A few principles that keep proactive engagement useful rather than annoying:

  • Set a generous idle threshold. A value of 60–120 minutes (idleThresholdMinutes) is a reasonable starting point for most people. A threshold under 30 minutes will produce frequent check-ins that quickly become noise.
  • Always configure quiet hours. Even if your schedule is irregular, defining a sleep window prevents early-morning or late-night pings. Set quietHours.enabled to true and configure start and end as hour integers (0–23). The system will hold the message and deliver it after the quiet window ends.
  • Never follow up on your own follow-up. ScalyClaw will not send a second proactive message to chase up the first one. If you haven't responded to the check-in, it waits — the cooldownSeconds enforces this mechanically, and the identity constraint enforces it philosophically.
  • Keep triggers minimal. Start with only firedScheduledItems enabled. Add undeliveredResults once you are comfortable with the cadence, and enable unansweredMessages only if you find yourself missing stalled conversations.
Proactive messages consume LLM tokens

Every proactive message runs a full LLM call. Depending on your model, cronPattern, and which triggers are enabled, this can add up. Monitor usage on the Models page and adjust idleThresholdMinutes, cooldownSeconds, and maxPerDay if costs are higher than expected.