Skip to content

Proactive messages — where they come from

When Neo sends the user something without being asked (a heads-up, a briefing, a noticing), it came from one of three daemon sources. If the user asks "how often do you send these?" or "where did this come from?", use this map — do not guess from the scheduler file alone (the briefing is NOT in it).

One corpus. This is both a user-facing overview and one of Neo's runtime self-docs: it is copied verbatim to ~/.neo/docs/self/proactive-messages.md at install time, so it is the file Neo reads to answer cadence/origin questions about itself. It is written in the second person ("you") because Neo reads it about itself.

The three sources

SourceWhat it isWhere it's configuredProvenance label
ReflectionA daily cross-session "noticing" pass that surfaces things worth telling the user.Cron row in ~/.neo/scheduler/scheduled_tasks.json (tag reflect).reflection-job
DreamPeriodic memory consolidation; may surface a note.Cron row in the scheduler (tag dream).heartbeat-job / reflection-job
Workflows (e.g. AI briefing)A multi-step Tier-2 workflow the daemon runs unattended, ending in a push.~/.neo/workflows/<id>/definition.yamlNOT in the scheduler file.the workflow id, e.g. ai-briefing

How delivery works

All three enqueue a notice into the owner's notification outbox (~/.neo/daemon/notifications/<sessionId>/) via the notify-owner primitive. The channel bridge (running inside neo-tg / neo-wa) drains that outbox and forwards the notice to the bound chat. Each notice record carries a source: field naming the job/workflow that produced it.

Tracing a specific message

  1. Check the source label on the notice if you can see it — it names the origin directly (e.g. source: ai-briefing).
  2. Check the scheduler: ~/.neo/scheduler/scheduled_tasks.json. Reflection and dream appear here as cron rows with a schedule you can read off directly (e.g. 0 3 * * * = daily 03:00).
  3. If it's not in the scheduler, it's a workflow. List ~/.neo/workflows/*/definition.yaml and read the matching one. Its triggers: block tells you how it fires — manual means it only runs when explicitly invoked (or dispatched by the daemon), NOT on a fixed clock, so don't claim a cadence the file doesn't state.

Answering "how often?"

Read the actual schedule before answering. If the source is a cron job, quote the cron expression. If it's a workflow with triggers: [manual], say plainly that it has no fixed schedule and runs when invoked/dispatched — don't invent a cadence.