# Scheduling Tasks (Cron & Heartbeat) LettaBot supports two types of background tasks: - **Cron jobs**: Send scheduled messages at specific times - **Heartbeats**: Periodic agent check-ins ## Enabling Background Tasks Add to your `lettabot.yaml`: ```yaml features: cron: true heartbeat: enabled: true intervalMin: 60 # Every 60 minutes ``` Or via environment variables: ```bash CRON_ENABLED=true HEARTBEAT_ENABLED=true HEARTBEAT_INTERVAL_MIN=60 ``` ## Cron Jobs Schedule tasks that send you messages at specific times. ### Creating a Job ```bash lettabot-cron create \ --name "Morning Briefing" \ --schedule "0 8 * * *" \ --message "Good morning! Review tasks for today." \ --deliver telegram:123456789 ``` **Options:** - `--name` - Job name (required) - `--schedule` - Cron expression (required) - `--message` - Message sent when job runs (required) - `--deliver` - Where to send: `channel:chatId` (defaults to last messaged chat) ### Managing Jobs ```bash lettabot-cron list # Show all jobs lettabot-cron delete # Delete a job lettabot-cron enable # Enable a job lettabot-cron disable # Disable a job ``` ### Cron Expression Syntax ``` ┌───────── minute (0-59) │ ┌─────── hour (0-23) │ │ ┌───── day of month (1-31) │ │ │ ┌─── month (1-12) │ │ │ │ ┌─ day of week (0-6, Sun=0) * * * * * ``` **Examples:** | Expression | When | |------------|------| | `0 8 * * *` | Daily at 8:00 AM | | `0 9 * * 1-5` | Weekdays at 9:00 AM | | `0 */2 * * *` | Every 2 hours | | `30 17 * * 5` | Fridays at 5:30 PM | | `0 0 1 * *` | First of month at midnight | ### Example Jobs **Daily morning check-in:** ```bash lettabot-cron create \ -n "Morning" \ -s "0 8 * * *" \ -m "Good morning! What's on today's agenda?" ``` **Weekly review:** ```bash lettabot-cron create \ -n "Weekly Review" \ -s "0 17 * * 5" \ -m "Friday wrap-up: What did we accomplish this week?" ``` **Hourly reminder:** ```bash lettabot-cron create \ -n "Hydration" \ -s "0 * * * *" \ -m "Time to drink water!" ``` ## Heartbeats Heartbeats are periodic check-ins where the agent can: - Review pending tasks - Check reminders - Perform proactive actions ### Configuration ```yaml features: heartbeat: enabled: true intervalMin: 60 # Default: 60 minutes skipRecentUserMin: 5 # Skip auto-heartbeats for N minutes after user messages (0 disables) ``` By default, automatic heartbeats are skipped for 5 minutes after a user message to avoid immediate follow-up noise. - Set `skipRecentUserMin: 0` to disable this skip behavior. - Manual `/heartbeat` always bypasses the skip check. ### Manual Trigger You can trigger a heartbeat manually via the `/heartbeat` command in any channel. ### How It Works 1. At each interval (or when `/heartbeat` is called), the agent receives a heartbeat message 2. The agent runs in **Silent Mode** - responses are not automatically delivered 3. If the agent wants to message you, it must use `lettabot-message send` This prevents unwanted messages while allowing proactive behavior when needed. ### Heartbeat To-Dos Heartbeats include a `PENDING TO-DOS` section when actionable tasks exist. Tasks can come from: - `lettabot todo ...` CLI commands - The `manage_todo` tool - Built-in Letta Code todo tools (`TodoWrite`, `WriteTodos`, `write_todos`), which are synced into LettaBot's persistent todo store Only actionable tasks are shown in the heartbeat prompt: - `completed: false` - `snoozed_until` not set, or already in the past ## Silent Mode Both cron jobs and heartbeats run in **Silent Mode**: - The agent's text output is NOT automatically sent to users - The agent sees a `[SILENT MODE]` banner with instructions - To send messages, the agent must explicitly run: ```bash lettabot-message send --text "Your message here" ``` **Requirements for background messaging:** - Bash tool must be enabled for the agent - A user must have messaged the bot at least once (establishes delivery target) ## Monitoring & Logs ### Check Job Status ```bash lettabot-cron list ``` Shows: - Job ID, name, schedule - Next run time - Last run status ### Log Files - `cron-jobs.json` - Job configurations - `cron-log.jsonl` - Execution logs ### Cron Storage Path Cron state is resolved with deterministic precedence: 1. `RAILWAY_VOLUME_MOUNT_PATH` 2. `DATA_DIR` 3. `WORKING_DIR` 4. `/tmp/lettabot` Migration note: - Older versions used `process.cwd()/cron-jobs.json` when `DATA_DIR` was not set. - On first run after upgrade, LettaBot auto-copies that legacy file into the new canonical cron path. ## Troubleshooting ### Cron jobs not running 1. Check `features.cron: true` in config 2. Verify schedule expression is valid 3. Check `lettabot-cron list` for next run time ### Agent not sending messages during heartbeat 1. Check if Bash tool is enabled (agent needs to run CLI) 2. Verify a user has messaged the bot at least once 3. Check the [ADE](https://app.letta.com) to see agent activity ### Jobs running but no messages received The agent runs in Silent Mode - it must actively choose to send messages. Check the agent's behavior in the ADE to see what it's doing during background tasks.