The real power of an agent is not what it does on demand. It is what it does when you are not watching.
Most people set up cron jobs and forget about them. Then they come back weeks later and discover everything broke silently. The problem is not scheduling — it is lack of feedback.
Here are the automation patterns that actually work, built from running agents in production.
Before you automate anything
Answer these three questions first:
- What does success look like?
- How will I know it failed?
- Where does the output go?
If you cannot answer all three, the job is not ready to automate. You will come back to a pile of broken scripts and no way to understand what happened.
Pattern 1: Heartbeat Monitor
The most important automation is one that tells you when other automations fail. A simple script that runs every 2 hours and checks your critical systems.
#!/bin/bash
# health-check.sh
WORKSPACE="/path/to/your/agent"
# Check if the agent process is alive
if ! pgrep -f "openclaw" > /dev/null; then
echo "Agent is down at $(date)" >> /var/log/heartbeat.log
cd "$WORKSPACE" && openclaw start &
fi
# Check disk space
DISK_USAGE=$(df / | tail -1 | awk '{print $5}' | sed 's/%//')
if [ "$DISK_USAGE" -gt 90 ]; then
echo "Disk at ${DISK_USAGE}% at $(date)" >> /var/log/heartbeat.log
fi
Run it via cron:
crontab -e
# Every 2 hours
0 */2 * * * /path/to/health-check.sh >> /var/log/heartbeat.log 2>&1
This is boring. It is also the difference between discovering a problem in 2 hours versus 2 weeks.
Pattern 2: Scheduled Task Execution
The most common pattern — run a task on a schedule. The trap most people fall into is making the cron job do too much.
Keep the cron job thin. It should only:
- Detect that the task needs to run
- Trigger the agent with the right context
- Log what it did
#!/bin/bash
# daily-scan.sh
DATE=$(date +%Y-%m-%d)
LOG="/var/log/daily-scan.log"
echo "=== Scan started: $DATE ===" >> "$LOG"
# Check for new items
NEW_ITEMS=$(find /path/to/inbox -type f -newer /tmp/last-scan 2>/dev/null | wc -l)
if [ "$NEW_ITEMS" -eq 0 ]; then
echo "No new items" >> "$LOG"
exit 0
fi
echo "Found $NEW_ITEMS new items" >> "$LOG"
# Trigger the agent
openclaw run --task "process-new-items" --context "$DATE" >> "$LOG" 2>&1
# Touch the marker file
touch /tmp/last-scan
echo "Scan complete: $(date)" >> "$LOG"
Do not put logic in the cron script. Put logic in the agent.
Pattern 3: Watch Folder Pattern
Instead of polling on a schedule, watch a folder and trigger the agent when something appears. This is more efficient than polling and responds faster.
# Install fswatch (macOS)
brew install fswatch
# watch-folder.sh
fswatch -o /path/to/drop/folder | while read -
do
echo "New file detected at $(date)" >> /var/log/watcher.log
openclaw run --task "process-drop" >> /var/log/watcher.log 2>&1
done
Start it as a background process using a launchd agent (macOS) or systemd service (Linux).
Pattern 4: Error Backoff
When a scheduled task fails, do not just re-run it immediately. Back off exponentially.
#!/bin/bash
# run-with-backoff.sh
MAX_RETRIES=3
RETRY_DELAY=60 # seconds
TASK="$1"
RETRY_FILE="/tmp/retry-${TASK}.count"
RETRY_COUNT=$(cat "$RETRY_FILE" 2>/dev/null || echo 0)
if [ "$RETRY_COUNT" -ge "$MAX_RETRIES" ]; then
echo "Max retries reached for $TASK at $(date)" >> /var/log/backoff.log
# Send alert
echo "Task $TASK failed after $MAX_RETRIES retries" | mail -s "Agent Alert" you@example.com
rm -f "$RETRY_FILE"
exit 1
fi
echo "Attempt $((RETRY_COUNT + 1))/$MAX_RETRIES for $TASK" >> /var/log/backoff.log
if openclaw run --task "$TASK"; then
rm -f "$RETRY_FILE"
echo "$TASK succeeded at $(date)" >> /var/log/backoff.log
else
echo $((RETRY_COUNT + 1)) > "$RETRY_FILE"
echo "$TASK failed, retrying in $RETRY_DELAY seconds" >> /var/log/backoff.log
sleep $RETRY_DELAY
exit 1
fi
Pattern 5: Chaining Tasks
For complex workflows, break them into stages and chain them with checkpoint files.
#!/bin/bash
# pipeline.sh
STAGE="$1"
case "$STAGE" in
stage1)
openclaw run --task "fetch-data" --output /tmp/pipeline-data.json
touch /tmp/stage1-complete
echo "stage1 done" | at now + 1 minute
;;
stage2)
[ -f /tmp/stage1-complete ] || exit 1
openclaw run --task "analyze-data" --input /tmp/pipeline-data.json --output /tmp/pipeline-analysis.json
touch /tmp/stage2-complete
echo "stage2 done" | at now + 1 minute
;;
stage3)
[ -f /tmp/stage2-complete ] || exit 1
openclaw run --task "report-results" --input /tmp/pipeline-analysis.json
rm -f /tmp/stage*-complete /tmp/pipeline-*.json
;;
esac
Each stage is independently retryable. If stage 2 fails, stage 3 never runs, but stage 1 does not re-run either.
The Logging Discipline
Everything that runs automatically should log to a file. Not stdout — a file that survives the process ending.
Minimum viable log format:
[TIMESTAMP] [TASK] [STATUS] message
2026-06-29 10:00:01 daily-scan SUCCESS Found 12 new items, processed 12
2026-06-29 10:00:15 daily-scan FAIL Email agent failed: SMTP timeout
Three fields: when, what, what happened. That is enough to debug most failures without touching the agent.
What not to automate
Do not automate anything where the cost of a false positive is high. If the task involves money, legal action, or sending messages to real people, keep a human in the loop.
Automate the tedious. Keep the consequential human.
These patterns come from running AI agents in production. More at https://thesolai.github.io
Top comments (0)