Scheduler
Background job processing for digests, reminder notifications, and content processing. The scheduling system is fully dynamic, storing cron patterns and job configurations in the SQLite database rather than using static environment variables.Overview
The scheduler uses BullMQ with Redis to run periodic jobs. It is always enabled — Redis is a required dependency. If Redis is unreachable at startup, EchOS exits with an actionable error message.Prerequisites
- Redis instance running (default:
redis://localhost:6379)
Configuration
Scheduling relies on the database and dynamic APIs. Only the connection variable is maintained in.env:
| Variable | Description | Default | Example |
|---|---|---|---|
REDIS_URL | Redis connection URL | redis://localhost:6379 | redis://myhost:6379 |
Managing Schedules
You can create, update, and delete schedules dynamically without restarting the application. EchOS provides two ways to do this:- Agent Tool: The
manage_scheduletool allows the AI assistant to manage background jobs on your behalf. - Web API: The
@echos/webplugin exposes RESTful CRUD endpoints under/api/schedules(requiresWEB_API_KEY).
config field designed to pass custom arguments to its plugin’s job processor (e.g., custom prompts or categorization rules).
Jobs
Daily Digest (digest)
The Digest Plugin generates summaries of your latest notes, memories, and upcoming reminders.
- Type:
digest - Config options:
prompt(varies the tone),lookbackDays(how far back to summarize),categories(filters notes by tags). - Default behavior: Creates a temporary AI agent and sends the summary via Notification Service.
- Reading Queue section: The digest automatically calls
reading_queue(limit 3) and includes a “Reading Queue” section showing your top 3 unread items.
Reminder Check (reminder-check)
Queries the SQLite database for pending reminders with a due date in the past. Due reminders are sorted by priority (high first) and sent as a notification.
Note: The system internally schedules a quick check every minute to dispatch due reminders, distinct from customizable user schedules.
Trash Purge (trash_purge)
Permanently removes notes that have been soft-deleted for more than 30 days. This job runs automatically on a fixed schedule — it cannot be customised via manage_schedule.
- Schedule: Daily at 3 AM (
0 3 * * *) - Behavior: Fetches all
status=deletednotes, checksdeleted_at, and for each note older than 30 days: removes the.mdfile fromknowledge/.trash/, purges the SQLite row, and removes the LanceDB vector - Location:
packages/scheduler/src/workers/trash-purge.ts
Content Processing (process_article, process_youtube)
Processes long-form article and YouTube URLs queued by the agent during conversations. This runs automatically when URLs are submitted; no manual schedule creation is needed.
RSS Feed Poll (rss_poll)
The RSS plugin polls all subscribed feeds for new articles and saves them as notes.
- Type:
rss_poll - Default schedule: Every 4 hours (
0 */4 * * *) — auto-registered on first startup, no manual setup needed - Config options: none
- Behavior: For each subscribed feed, fetches the RSS/Atom XML, filters entries newer than
lastEntryDate, extracts full article text, applies AI categorization, and saves each new entry as a note. Deduplication is atomic — concurrent poll and refresh cannot create duplicate notes.
rss-poll schedule to cron 0 */2 * * *.
Knowledge Resurfacing (resurface)
The Resurface Plugin surfaces forgotten notes from your knowledge base using spaced repetition and on-this-day discovery.
- Type:
resurface - Config options:
mode—'forgotten'(oldest un-surfaced first),'on_this_day'(same calendar date in prior years),'random','mix'(default)limit— number of notes to broadcast (default:3, max:10)
- Behavior: Queries notes where
last_surfacedisNULLor older than 7 days, picks the best candidates per strategy, sends a formatted Telegram notification, and updates each note’slast_surfacedtimestamp.
0 9 * * *, type resurface.
Architecture
ScheduleManager listens for changes made through the tools and Web API, applying them instantly to the running BullMQ scheduler.
Graceful Shutdown
On SIGINT/SIGTERM, the worker and queue are closed before interfaces and storage. In-progress jobs will complete before the worker shuts down.Example Usage
With the scheduler running, you can ask the agent:“Create a daily digest at 8am that looks back 3 days and focuses on ‘business’ and ‘music’ categories, using a professional tone.”The agent will use
manage_schedule (action: upsert) to build and inject the exact JSON configuration and cron expression 0 8 * * *.