Cron Jobs
Scheduled jobs run inside --serve mode alongside the Discord bot and HTTP API.
Configuration
Add jobs under cron.jobs in config.yaml:
cron:
enabled: true
jobs:
- name: "daily-email-summary"
schedule: "0 9 * * *" # standard cron syntax
prompt: "Summarize my unread emails from the last 24 hours"
profile: "email-checker"
delivery:
channel: "log" # or "discord" / "discord-dm"
Set cron.enabled: true and run with --serve — the scheduler starts automatically.
Job modes
Wake agent (default)
wakeAgent: true runs the full agent loop with the configured prompt, then delivers
the response via the configured delivery channel.
Add note
wakeAgent: false injects the prompt as a user message into the session without
running the agent loop. Useful for queuing context for the next interaction.
Delivery channels
log(default) — prints the response to stdoutdiscord— sends to a Discord channel (requiresdelivery.targetchannel ID)discord-dm— sends as a DM to the bot owner
Job options
| Field | Description |
|-------|-------------|
| name | Unique job identifier |
| schedule | Cron expression (standard 5-field syntax) |
| prompt | The message sent to the agent |
| profile | Named profile to use (optional) |
| wakeAgent | Run agent loop (default true) or just inject message |
| newSession | Start a fresh session each run (default false) |
| delivery.channel | Output channel: log, discord, or discord-dm |
| delivery.target | Discord channel ID (required for discord delivery) |
| hooks | Job-specific hooks (appended to profile hooks) |
Prompt templating
Cron prompts support template variables:
| Variable | Description |
|----------|-------------|
| {{last_run}} | ISO timestamp of the last run |
| {{last_run_epoch}} | Unix timestamp of the last run |
| {{last_response}} | The agent's response from the last run |
| {{next_task}} | First "Next:" line from the profile's goals.md |
Example with hooks
cron:
enabled: true
jobs:
- name: "morning-briefing"
schedule: "0 8 * * *"
prompt: "Give me a morning briefing based on the context below."
profile: "researcher"
hooks:
beforeRun:
- tool: gmail
args: { action: "check", query: "newer_than:1d" }
skipIf: "no new messages"
- tool: web_search
args: { query: "AI news today" }
Job state
Job state (last run time, last response) is tracked in the cron_jobs database table
and persists across restarts.