DocsAutomationCron & Heartbeat

Ryvos includes two automation systems that run in daemon mode: cron for scheduled tasks and heartbeat for periodic health monitoring.

Cron Jobs

Cron jobs let you schedule recurring agent tasks using standard 5-field cron expressions. Each job runs the agent with a specified prompt at the scheduled time.

Configuration

[[cron.jobs]]
name = "daily-report"
schedule = "0 9 * * *"                # Every day at 9:00 AM
prompt = "Generate a summary of yesterday's git commits and open PRs"
channel = "slack"                      # Optional: route output to a channel
 
[[cron.jobs]]
name = "hourly-health"
schedule = "0 * * * *"                # Every hour
prompt = "Check if the staging server at staging.example.com is responding"
channel = "telegram"
 
[[cron.jobs]]
name = "weekly-cleanup"
schedule = "0 2 * * 0"               # Sundays at 2:00 AM
prompt = "Review and clean up old log files in /var/log/app/"
 
[[cron.jobs]]
name = "deploy-check"
schedule = "*/15 * * * *"            # Every 15 minutes
prompt = "Check if the latest deployment is healthy by calling /api/health"

Cron Expression Format

┌───────── minute (0-59)
│ ┌─────── hour (0-23)
│ │ ┌───── day of month (1-31)
│ │ │ ┌─── month (1-12)
│ │ │ │ ┌─ day of week (0-6, Sunday=0)
│ │ │ │ │
* * * * *
ExpressionSchedule
0 9 * * *Daily at 9:00 AM
0 */2 * * *Every 2 hours
*/15 * * * *Every 15 minutes
0 9 * * 1-5Weekdays at 9:00 AM
0 0 1 * *First day of each month at midnight
30 8 * * 1Every Monday at 8:30 AM

Channel Routing

When a channel is specified, the cron job output is sent to that channel. Without a channel, the output is logged but not sent anywhere.

[[cron.jobs]]
name = "morning-brief"
schedule = "0 8 * * 1-5"
prompt = "Summarize today's calendar, pending PRs, and any alerts"
channel = "telegram"               # Sends the summary to Telegram

Events

Cron jobs emit events on the EventBus:

EventWhen
CronFiredA cron job has triggered (includes job name and schedule)
CronJobCompleteThe agent finished executing the cron job (includes result)

Managing Cron Jobs

Config

Edit config.toml directly:

[[cron.jobs]]
name = "my-job"
schedule = "0 9 * * *"
prompt = "Do the thing"

Tools

The agent can manage cron jobs via built-in tools:

You > Add a cron job that checks disk usage every 6 hours
Agent > [tool: cron_add] Adding cron job...
Added job "disk-check" with schedule "0 */6 * * *"

Available tools:

  • cron_list — List all jobs with next fire times
  • cron_add — Add a new job
  • cron_remove — Remove a job

Heartbeat

The heartbeat system runs periodic mini-agent sessions to check on things you care about. Unlike cron (which runs specific prompts), the heartbeat reads HEARTBEAT.md for its instructions and makes intelligent decisions about what to report.

Configuration

[heartbeat]
enabled = true
interval_secs = 3600               # Check every hour (3600 seconds)
active_hours = "08:00-22:00"       # Only run during these hours (local time)
ack_max_chars = 50                 # Suppress responses shorter than this
channel = "telegram"               # Route alerts to this channel

HEARTBEAT.md

Create HEARTBEAT.md in your workspace (or ~/.ryvos/) with instructions for what to check:

# Heartbeat Checks
 
## Server Health
- Check if https://api.example.com/health returns 200
- Check if disk usage on /home is below 80%
 
## Git Status
- Check if there are any uncommitted changes in ~/projects/main-app
- Check if main branch is up to date with origin
 
## Alerts
- If the server is down, mention it urgently
- If disk usage is above 90%, flag as critical
- If everything is fine, just say "all clear" (will be suppressed)

Smart Suppression

The ack_max_chars setting suppresses short "all good" responses. When the heartbeat check returns a response shorter than this threshold (e.g., "All systems normal" is 19 chars), it is logged but not sent to the channel.

This prevents notification fatigue. You only get alerted when something actually needs attention.

[heartbeat]
ack_max_chars = 50    # Suppress responses under 50 characters

Examples:

  • "All clear." (10 chars) -- suppressed
  • "Everything looks good, no issues." (34 chars) -- suppressed
  • "WARNING: Disk usage at 92% on /home. Server API returned 503 twice in the last hour." (86 chars) -- sent to channel

Active Hours

The heartbeat only runs during active hours:

[heartbeat]
active_hours = "08:00-22:00"       # Local timezone

Outside these hours, heartbeat checks are skipped. This prevents alerts from waking you up at 3 AM.

Events

EventWhen
HeartbeatFiredA heartbeat check has started
HeartbeatOkCheck completed, everything normal (may be suppressed)
HeartbeatAlertCheck found an issue, alert sent to channel

CLI Session Resumption

If you were interacting with Ryvos via the CLI when the heartbeat fires, the heartbeat runs in a separate session and does not interrupt your conversation. The results are routed to the configured channel.


Cron vs Heartbeat

FeatureCronHeartbeat
PurposeScheduled tasksHealth monitoring
TriggerCron expressionFixed interval
InstructionsPer-job promptHEARTBEAT.md (shared)
SuppressionNo (always sends output)Yes (ack_max_chars)
Active hoursNo (runs on schedule)Yes (configurable)
Multiple jobsYesSingle check
Channel routingPer-jobSingle channel

Use cron for specific recurring tasks (reports, cleanups, checks). Use heartbeat for general health monitoring with smart alerting.

Daemon Mode

Both cron and heartbeat require daemon mode:

ryvos daemon --gateway

To selectively disable:

ryvos daemon --no-cron              # Disable cron jobs
ryvos daemon --no-heartbeat         # Disable heartbeat

Next Steps