Daily automated security reports with inline button updates
The Morning Report system runs three automated cron jobs that check server health, security status, and available updates. Reports are delivered to Telegram with clickable inline buttons for applying updates.
| Time | Job | Purpose |
|---|---|---|
04:00 |
daily-auto-update | Auto-update skills, check OpenClaw updates |
05:00 |
reboot-check | Alert if kernel needs reboot (only on mismatch) |
06:00 |
morning-health-report | Full security report + update button |
This does NOT render as a clickable button:
[inline_button:Apply Updates:apply_system_updates]
The user sees raw text, not a button.
Use the CLI command with JSON-formatted buttons:
openclaw message send \
--channel telegram \
--target "85126311" \
--buttons '[[{"text": "โ
Apply Updates", "callback_data": "apply_system_updates"}]]' \
-m "Your message here"
# Single button
--buttons '[[{"text": "Button Text", "callback_data": "action_name"}]]'
# Two buttons side by side
--buttons '[[{"text": "Yes", "callback_data": "yes"}, {"text": "No", "callback_data": "no"}]]'
# Two rows of buttons
--buttons '[[{"text": "Row 1", "callback_data": "r1"}],[{"text": "Row 2", "callback_data": "r2"}]]'
[[...]] โ outer array is rows, inner array is buttons per rowtext โ what the user sees on the buttoncallback_data โ identifier sent back when button is clicked๐ฆ <b>Morning Health Report</b>
โ
<b>SSH:</b> 211 attacks blocked
User sees: <b>Morning Health Report</b> (literal text)
๐ฆ Morning Health Report
โ
SSH: 211 attacks blocked (fail2ban active)
๐ด OOM: 1 kill yesterday (opencode)
๐ฆ Updates: 25 packages ready
<b>, <i>, <code> show as text**bold** shows as literal asterisks
Location: /home/clawdija/asistent/v2/workspace/daily-security-report.sh
When updates are available, the script outputs:
[UPDATES_AVAILABLE:25]
The agent reads this signal and knows to send a message with an "Apply Updates" button.
Location: /home/clawdija/asistent/v2/cron/jobs.json
{
"id": "c7c04792-76d1-46b6-a925-27151dfe12b8",
"name": "morning-health-report",
"enabled": true,
"schedule": {
"kind": "cron",
"expr": "0 6 * * *"
},
"payload": {
"kind": "agentTurn",
"message": "Good morning! Run the daily security report:\n\n1. Execute ~/asistent/v2/workspace/daily-security-report.sh...\n2. Check for OpenClaw updates...\n3. Run memory-recall.sh recent 3...\n\nINLINE BUTTONS (IMPORTANT):\nIf updates available, use this EXACT command:\nopenclaw message send --channel telegram --target \"85126311\" \\\n --buttons '[[{\"text\": \"โ
Apply Updates\", \"callback_data\": \"apply_system_updates\"}]]' \\\n -m \"Your plain text message\"\n\nDO NOT use [inline_button:...] or HTML tags.\n\nCALLBACK HANDLING:\n- When callback_data \"apply_system_updates\" received:\n a) React with ๐ first\n b) Run ~/asistent/v2/workspace/system-update.sh\n c) Report results"
},
"delivery": {
"mode": "announce",
"channel": "last"
}
}
schedule.expr โ Cron expression (0 6 * * * = 06:00 daily)sessionTarget โ isolated (fresh session each run)delivery.mode โ announce (send result to user)delivery.channel โ last (use last active channel)# List all cron jobs
openclaw cron list
# Edit a job
openclaw cron edit <job-id> --message "New prompt..."
# Run a job manually (debug)
openclaw cron run <job-id>
# View run history
openclaw cron runs --id <job-id>
When a user taps an inline button, the callback_data is sent to the agent.
The agent must handle it appropriately.
| callback_data | Action | Script |
|---|---|---|
apply_system_updates |
Apply pending package updates | ~/asistent/v2/workspace/system-update.sh |
Every message deserves a response. When user sends a message or clicks a button:
Telegram doesn't show delivery confirmations โ only the agent can confirm receipt.
| File | Purpose |
|---|---|
~/asistent/v2/workspace/daily-security-report.sh |
Generates the security report |
~/asistent/v2/workspace/system-update.sh |
Applies package updates |
~/asistent/v2/workspace/reboot-check.sh |
Checks if kernel reboot needed |
~/asistent/v2/cron/jobs.json |
Cron job definitions |
~/asistent/v2/logs/daily-security-report.log |
Report execution logs |
Symptom: Message shows [inline_button:...] as text
Solution: Use openclaw message send --buttons '[[...]]' instead of text placeholder
Symptom: <b> shows literally in message
Solution: Remove HTML tags, use plain text with emoji
Symptom: User receives multiple identical reports
Solution: Check if multiple cron jobs with same schedule exist: openclaw cron list
Symptom: User taps button but nothing happens
Solution: Verify callback handling is in cron job prompt, check agent received the callback
Symptom: No report at expected time
Solution: Check gateway is running, verify cron job enabled: openclaw cron list
openclaw message send \
--channel telegram \
--target "85126311" \
--buttons '[[{"text": "โ
Action", "callback_data": "action_name"}]]' \
-m "Plain text message with emoji ๐ฆ"
~/asistent/v2/workspace/daily-security-report.sh
~/asistent/v2/workspace/system-update.sh
openclaw cron list
openclaw cron runs --id c7c04792-76d1-46b6-a925-27151dfe12b8
openclaw cron edit c7c04792-76d1-46b6-a925-27151dfe12b8 --message "New prompt"