Seven habits I use so one bad API call does not wreck the whole morning briefing.
If I let a briefing invent its own format every morning, the next step has to guess what it is reading.
Instead of "Write a morning briefing", use a template with fill-in sections:
## Morning Briefing: {{date}}
### Weather
{{weather_summary}}
### Schedule
{{calendar_events}}
### AI News
{{news_summary_3_items}}
### Markets
{{market_snapshot}}
The agent fills in {{variables}} instead of deciding the structure from scratch.
If the news API returns a 503, the whole briefing should not die. The failed section should say it is unavailable and the rest should still arrive.
Wrap each data fetch in its own error handler:
def fetch_weather():
try:
return get_weather_data()
except Exception as e:
return "Weather unavailable"
def fetch_news():
try:
return get_news_data()
except Exception as e:
return "News unavailable"
The briefing still delivers with one section marked unavailable instead of the whole thing failing.
Your 6:40 AM cron fires the briefing. But what if the server was restarting at 6:40? You get nothing.
Add a heartbeat check. It asks, "did the daily briefing run today?" If not, it runs the briefing. One missed cron should not cost you the whole day's briefing.
The main job runs at 6:40 AM. A second check looks for a missing briefing and only runs it if the first one did not.
The exact interval matters less than the habit: one scheduled job checks whether the other one did its job.
When one step fails, the agent should keep going when it can. It should also leave enough of a note that you can find the problem later.
That is how a broken API key becomes a fixable note instead of two days of missing output.
When you have 12 API keys and one expires, which one broke the workflow?
Structure your config so each integration has its own labeled section:
# .env # --- Weather --- OPENWEATHER_API_KEY=... # --- News --- BRAVE_API_KEY=... GNEWS_API_KEY=... # --- Calendar --- GOOGLE_CALENDAR_CREDENTIALS=/path/to/creds.json
When something breaks, the labels tell you where to look first.
Your agent will happily produce 5,000 words if you let it. Telegram has message limits. Your attention has limits.
Hard constraints in the skill definition:
## Output Rules - Total output: under 800 words - Each section: 3-5 bullet points max - Weather: 2 sentences - News: 3 headlines, 1 sentence each - Markets: numbers only, no commentary
The constraint is the point. If the briefing is too long to read, the workflow did not work.
You may not notice the agent is broken until you wonder, "why didn't I get my briefing today?"
Set up a health check cron that runs independently and reports:
This runs as its own job, separate from the automations it monitors.
My current Raspberry Pi 5 setup uses:
Every pattern above came from something breaking and then showing up again later.
The OpenClaw bundle includes the morning briefing folder, setup notes, and related scripts. Use it as a reference setup before building your own.