Guides6 min read

AI Bot Automation with Cron Jobs

Set up automated tasks for your AI chatbot using cron jobs. Schedule reports, reminders, and recurring bot actions on your VPS.

Published: 27/01/2025

Overview

Cron jobs transform your AI chatbot from a reactive tool into a proactive assistant. Schedule daily summaries, automated reminders, system checks, and more - all running automatically on your VPS.

What You Can Automate

  • Daily/Weekly Reports: Weather, news, calendar summary
  • Reminders: Scheduled messages to channels or DMs
  • System Monitoring: VPS health checks, usage alerts
  • Data Tasks: Backup reminders, cleanup operations
  • Integrations: Sync data, update feeds, check APIs

Cron Basics

Cron Syntax

┌───────────── minute (0-59)
│ ┌───────────── hour (0-24)
│ │ ┌───────────── day of month (1-31)
│ │ │ ┌───────────── month (1-12)
│ │ │ │ ┌───────────── day of week (0-6, Sunday=0)
│ │ │ │ │
* * * * * command

Common Schedules

| Schedule | Cron Expression | |----------|-----------------| | Every hour | 0 * * * * | | Daily at 9 AM | 0 9 * * * | | Weekly Monday 8 AM | 0 8 * * 1 | | First of month | 0 0 1 * * | | Every 15 minutes | */15 * * * * |

Setup Guide

Step 1: Create Automation Scripts

Create a scripts directory:

mkdir -p /opt/openclaw/scripts

Step 2: Example - Daily Summary

Create /opt/openclaw/scripts/daily-summary.js:

const fetch = require('node-fetch');

const WEBHOOK_URL = process.env.DISCORD_WEBHOOK;
const CHANNEL_ID = process.env.SUMMARY_CHANNEL;

async function sendDailySummary() {
  const today = new Date().toLocaleDateString('en-GB');

  // Gather data for summary
  const summary = {
    date: today,
    weather: await getWeather(),
    tasks: await getTodaysTasks(),
    reminders: await getReminders()
  };

  // Send via webhook or bot API
  await sendMessage(CHANNEL_ID, formatSummary(summary));
}

sendDailySummary().catch(console.error);

Step 3: Make Executable

chmod +x /opt/openclaw/scripts/daily-summary.js

Step 4: Add to Crontab

crontab -e

Add your scheduled tasks:

# Daily summary at 8 AM
0 8 * * * cd /opt/openclaw && /usr/bin/node scripts/daily-summary.js >> /var/log/bot-cron.log 2>&1

# Weekly report every Monday at 9 AM
0 9 * * 1 cd /opt/openclaw && /usr/bin/node scripts/weekly-report.js >> /var/log/bot-cron.log 2>&1

# Hourly health check
0 * * * * cd /opt/openclaw && /usr/bin/node scripts/health-check.js >> /var/log/bot-cron.log 2>&1

Practical Automation Examples

Morning Briefing

Send a morning briefing to your Discord channel:

// scripts/morning-brief.js
async function morningBrief() {
  const brief = `
**Good Morning! ☀️**

📅 **Date:** ${new Date().toLocaleDateString('en-GB', { weekday: 'long', day: 'numeric', month: 'long' })}

🌤️ **Weather:** ${await getWeather('London')}

📰 **Top Headlines:**
${await getHeadlines(3)}

📋 **Your Day:**
${await getCalendarEvents()}

Have a productive day!
  `;

  await sendToChannel(process.env.BRIEFING_CHANNEL, brief);
}

Schedule: 0 7 * * 1-5 (7 AM weekdays)

Server Health Monitor

Alert if VPS resources are critical:

// scripts/health-check.js
const os = require('os');

async function healthCheck() {
  const memUsage = (1 - os.freemem() / os.totalmem()) * 100;
  const loadAvg = os.loadavg()[0];

  const alerts = [];

  if (memUsage > 90) {
    alerts.push(`⚠️ Memory usage critical: ${memUsage.toFixed(1)}%`);
  }

  if (loadAvg > os.cpus().length * 2) {
    alerts.push(`⚠️ CPU load high: ${loadAvg.toFixed(2)}`);
  }

  if (alerts.length > 0) {
    await sendAlert(alerts.join('\n'));
  }
}

Schedule: */15 * * * * (every 15 minutes)

Automated Backup Reminder

// scripts/backup-reminder.js
async function backupReminder() {
  const lastBackup = await getLastBackupDate();
  const daysSince = (Date.now() - lastBackup) / (1000 * 60 * 60 * 24);

  if (daysSince > 7) {
    await sendDM(process.env.ADMIN_USER,
      `🔔 Reminder: It's been ${Math.floor(daysSince)} days since your last backup. Consider backing up your bot data.`
    );
  }
}

Schedule: 0 10 * * * (daily at 10 AM)

Weekly Activity Report

// scripts/weekly-report.js
async function weeklyReport() {
  const stats = await getBotStats();

  const report = `
**📊 Weekly Bot Report**

**Messages Processed:** ${stats.messages}
**Active Users:** ${stats.users}
**Avg Response Time:** ${stats.avgResponseTime}ms
**Errors:** ${stats.errors}

**Top Commands:**
${stats.topCommands.map((c, i) => `${i+1}. ${c.name}: ${c.count}`).join('\n')}

**Cost Summary:**
API calls: ${stats.apiCalls}
Estimated cost: £${stats.estimatedCost.toFixed(2)}
  `;

  await sendToChannel(process.env.REPORTS_CHANNEL, report);
}

Schedule: 0 9 * * 1 (Monday 9 AM)

Using Environment Variables

Create a cron-specific env file:

# /opt/openclaw/.env.cron
DISCORD_WEBHOOK=https://discord.com/api/webhooks/...
ADMIN_USER=123456789
BRIEFING_CHANNEL=987654321
WEATHER_API_KEY=your-key

Load in cron jobs:

0 8 * * * . /opt/openclaw/.env.cron && cd /opt/openclaw && node scripts/morning-brief.js

Logging Best Practices

Dedicated Log File

# Create log with rotation
0 8 * * * cd /opt/openclaw && node scripts/task.js >> /var/log/bot-automation.log 2>&1

Log Rotation

Create /etc/logrotate.d/bot-automation:

/var/log/bot-automation.log {
    daily
    rotate 7
    compress
    missingok
    notifempty
}

Error Handling

Notify on Failure

// Wrapper for all scripts
async function runWithNotification(task) {
  try {
    await task();
  } catch (error) {
    await sendAlert(`❌ Automation failed: ${error.message}`);
    process.exit(1);
  }
}

runWithNotification(morningBrief);

Retry Logic

async function withRetry(fn, attempts = 3) {
  for (let i = 0; i < attempts; i++) {
    try {
      return await fn();
    } catch (error) {
      if (i === attempts - 1) throw error;
      await sleep(5000 * (i + 1)); // Exponential backoff
    }
  }
}

PM2 Alternative

For complex scheduling, use PM2 cron:

// ecosystem.config.js
module.exports = {
  apps: [
    {
      name: 'daily-summary',
      script: './scripts/daily-summary.js',
      cron_restart: '0 8 * * *',
      autorestart: false
    },
    {
      name: 'health-check',
      script: './scripts/health-check.js',
      cron_restart: '*/15 * * * *',
      autorestart: false
    }
  ]
};

Start: pm2 start ecosystem.config.js

Security Considerations

Limit Script Permissions

# Run cron as dedicated user
sudo -u botuser crontab -e

Don't Store Secrets in Scripts

Always use environment variables or secure vaults.

Monitor Cron Execution

# Check cron logs
grep CRON /var/log/syslog | tail -20

Troubleshooting

Cron not running

  1. Check cron service: systemctl status cron
  2. Verify syntax: crontab -l
  3. Check user has cron access

Script works manually but not in cron

  • Use absolute paths
  • Set PATH in crontab
  • Load environment explicitly
PATH=/usr/local/bin:/usr/bin:/bin
0 8 * * * cd /opt/openclaw && node scripts/task.js

Time zone issues

# Set timezone in crontab
TZ=Europe/London
0 8 * * * cd /opt/openclaw && node scripts/task.js

Related Guides

Need Help?

Setting up automation requires careful planning. Our premium service includes custom automation setup for your specific needs.

Need a VPS for Your Bot?

We recommend Hostinger KVM 2 VPS - reliable, fast, and perfect for AI chatbots. Get started with our recommended setup.

Get Hostinger VPS

Need Help With Setup?

Got your VPS? Let us handle the technical work. Professional setup and maintenance for OpenClaw (formerly Clawd.bot).