If you've been running OpenClaw on a Mac Mini that crashes at 3 AM, SSH-ing into a VPS to restart your morning briefing agent, or storing Google OAuth tokens in a folder that lives dangerously close to your Downloads — stop. This guide walks you through running OpenClaw automations inside Paradime, from zero to scheduled, production-grade agents that clean your calendar, triage your inbox, and deliver morning briefings — with no always-on laptop, no plaintext secrets, and no 2 AM debugging sessions.
What Is OpenClaw (and Why It Needs a Scheduler)
OpenClaw is an open-source AI agent that doesn't just answer questions — it carries out tasks. Connect it to your calendar, email, file system, Slack, or browser, and it can create events, triage your inbox, draft messages, generate reports, and manage workflows without you lifting a finger. People use OpenClaw to handle the kind of everyday admin that's too tedious to do manually but too nuanced for a simple IFTTT rule.
The most popular OpenClaw automations are recurring: a morning briefing that summarizes your day, an inbox sweep that categorizes emails every hour, a calendar audit that detects double-bookings before they embarrass you. These automations work best when they run on a schedule, reliably, around the clock.
The Always-On Laptop Problem
The default OpenClaw setup assumes you have a machine running 24/7. That's fine for a demo. In practice, it means:
Uptime depends on hardware. A Mac Mini that goes to sleep, a laptop lid that closes, a WiFi blip at 4 AM — and your morning briefing never fires. You discover this at 9 AM when you walk into a meeting unprepared.
Secrets live on the machine. Google OAuth tokens, API keys for Anthropic or OpenAI, Slack webhook URLs — all sitting in config files on a physical device. One stolen laptop and every integration is compromised.
No visibility into failures. When a cron job fails silently on your VPS, you don't know until the automation stops producing results. There's no centralized log, no alerting, no run history.
Scaling means more machines. Want to add a second automation? A third? Now you're managing multiple cron jobs across machines, each with their own credential story and failure mode.
The core issue: OpenClaw was designed for agents that run continuously. But most practical automations are event-driven or scheduled — and they need infrastructure that's built for that pattern.
Why Paradime for OpenClaw Automations
Paradime is an all-in-one platform for scheduling and running code in production. Its Bolt scheduler natively supports Python scripts as first-class scheduled tasks — with cron triggers, retry logic, encrypted secrets, Slack/email/Teams notifications, and full run history. While Paradime is widely known for orchestration, Bolt's Python support makes it a perfect home for any scheduled automation, including OpenClaw agents.
Here's what changes when you move OpenClaw automations to Paradime:
Concern
Running Locally
Running in Paradime
Uptime
Depends on your laptop/VPS
99.9%+ managed infrastructure
Secrets
Files on disk, env vars in shell profiles
Encrypted at rest, scoped per environment
Scheduling
System cron, launchd, or a bash loop
UI-driven cron with timezone support
Failure alerting
Checking logs manually
Slack, email, and Teams notifications on failure
Run history
Scattered terminal output
Centralized logs with Summary, Console, and Debug views
Scaling
One cron job per machine
Unlimited schedules, one dashboard
The shift: Your OpenClaw agent stops being "that script on my Mac Mini" and becomes a governed, monitored, always-on automation — without you managing any infrastructure.
Prerequisites
Paradime Account
You need an active Paradime workspace. If you don't have one, start a free 14-day trial — no credit card required.
A Git Repository
Paradime connects to your Git provider (GitHub, GitLab, or Bitbucket) and runs code from a repository. If you don't already have one connected, you'll set this up during onboarding. Your OpenClaw scripts will live in this repo.
Our recommendation: For scheduled automations, the OpenClaw Python SDK combined with direct API keys (Anthropic, OpenAI) is the simplest path. You skip running your own gateway and still get structured outputs, streaming, and multi-step orchestration.
API Credentials for Integrations
Depending on your use case, gather the credentials you'll need:
Integration
Credential Type
Where to Get It
Gmail / Calendar
Google OAuth credentials.json
Google Cloud Console → APIs & Services → Credentials
Slack
Bot token or webhook URL
Slack App Settings → OAuth & Permissions
Anthropic (Claude)
API key
console.anthropic.com
OpenAI
API key
platform.openai.com
Weather
API key
openweathermap.org or weatherapi.com
Step 1: Add Your OpenClaw Scripts to a Repository
Paradime runs Python scripts that live in your connected Git repository. Create a scripts/ directory to keep your OpenClaw automations organized.
Recommended Project Structure
Each script is a standalone Python file that Paradime's Bolt scheduler can execute independently. We'll walk through building each one in the use case sections below.
Step 2: Configure Dependencies with Poetry
Paradime uses Poetry for Python dependency management. This ensures every scheduled run installs exactly the same package versions — no drift between what worked yesterday and what breaks today.
Adjust the dependencies based on which integrations your scripts need. The openclaw-sdk is the core requirement; the rest depends on your use cases.
Important: Commit both pyproject.toml and poetry.lock to your repository. The lock file guarantees deterministic builds — the same versions every time, in every run.
Step 3: Store Secrets Securely in Paradime
This is where Paradime eliminates the scariest part of running OpenClaw automations: credential management. Instead of OAuth tokens in ~/.config/gog/ or API keys in .env files, everything lives in Paradime's encrypted environment variable store.
Add Environment Variables for Bolt (Production)
Go to Settings → Workspaces → Environment Variables.
In the Bolt Schedules section, click Add New.
Add each secret your scripts need:
Key
Example Value
Purpose
ANTHROPIC_API_KEY
sk-ant-xxxxxxxxxxxx
AI provider for agent reasoning
OPENCLAW_GATEWAY_URL
ws://your-server:18789/gateway
Self-hosted gateway (if applicable)
OPENCLAW_API_KEY
sk-oc-xxxxxxxxxxxx
Gateway authentication
GOOGLE_CREDENTIALS_JSON
{"installed":{"client_id":"...}}
Google OAuth credentials (JSON string)
GOOGLE_TOKEN_JSON
{"token":"...","refresh_token":"..."}
Google OAuth token (JSON string)
SLACK_WEBHOOK_URL
https://hooks.slack.com/services/...
Slack incoming webhook
SLACK_BOT_TOKEN
xoxb-xxxxxxxxxxxx
Slack bot for richer interactions
WEATHER_API_KEY
abc123...
Weather data provider
Add Variables for Code IDE (Development)
Repeat the same process in the Code IDE section for testing. Use development-safe values — a test Slack channel instead of #general, a staging calendar instead of your primary one.
Why separate environments? Your development variables might point to test accounts and sandbox APIs. Production should hit your real integrations. Keeping them isolated prevents accidentally sending test messages to your entire team.
If a variable is missing, Python raises a KeyError — which surfaces clearly in Bolt logs and triggers your failure notifications. Fail loud, fail fast.
Step 4: Test in the Paradime Code IDE
Before scheduling anything, verify your scripts work in Paradime's development environment.
Open the Terminal
In the Paradime Code IDE, open a new terminal (`Ctrl+Shift+``). Your repository is checked out and Code IDE environment variables are loaded.
Install Dependencies and Run
If everything is configured correctly, you'll see your script's output in the terminal. If not, the error messages will point you to the exact problem — a missing environment variable, a bad API key, or a connectivity issue.
Step 5: Create Bolt Schedules for Each Automation
Now promote your tested scripts to production. In Paradime, click Bolt in the top navigation, then Create Schedule.
The Universal Pattern
Every OpenClaw automation follows the same two-command pattern in Bolt:
Critical:poetry install must always be the first command. It creates the virtual environment and installs all dependencies before your script runs.
Trigger Types
Trigger
Cron Example
Best For
Every morning at 7 AM
0 7 * * *
Morning briefings
Every hour
0 * * * *
Inbox triage
Every Monday at 9 AM
0 9 * * 1
Weekly calendar cleanup
Every Friday at 5 PM
0 17 * * 5
Weekly status digests
On API call
Bolt API trigger
Event-driven workflows (e.g., new client)
Notifications
For every schedule, configure failure alerts at minimum. Go to Notification Settings in the schedule and add a Slack channel or email address. You can also set SLA alerts if a run takes longer than expected — a useful signal that your OpenClaw gateway or AI provider is experiencing latency.
Use Case 1: Morning Briefing — Calendar, Email, Weather
The classic OpenClaw automation. Every morning, your agent compiles a summary of today's calendar events, urgent emails, and the weather — then sends it to you via Slack.
The Script
"""
morning_briefing.py
Sends a daily briefing via Slack: calendar, email highlights, weather.
"""importosimportjsonimportasyncioimportrequestsfromdatetimeimportdatetime,timedeltafromopenclaw_sdkimportOpenClawClientfromopenclaw_sdk.core.configimportClientConfigGATEWAY_URL = os.environ["OPENCLAW_GATEWAY_URL"]API_KEY = os.environ["OPENCLAW_API_KEY"]SLACK_WEBHOOK = os.environ["SLACK_WEBHOOK_URL"]WEATHER_KEY = os.environ["WEATHER_API_KEY"]CITY = os.environ.get("BRIEFING_CITY","London")defget_weather(city: str) -> str:
"""Fetch today's weather summary."""url = f"https://api.weatherapi.com/v1/forecast.json?key={WEATHER_KEY}&q={city}&days=1"resp = requests.get(url,timeout=10)data = resp.json()forecast = data["forecast"]["forecastday"][0]["day"]return(f"🌤 {city}: {forecast['condition']['text']}, "f"{forecast['mintemp_c']}–{forecast['maxtemp_c']}°C, "f"{forecast['daily_chance_of_rain']}% chance of rain")asyncdefbuild_briefing() -> str:
"""Use OpenClaw to compile calendar + email summary."""config = ClientConfig(gateway_ws_url=GATEWAY_URL,api_key=API_KEY,timeout=120,)asyncwithOpenClawClient.connect(**config.model_dump())asclient:
agent = client.get_agent("briefing-bot")result = awaitagent.execute(f"Today is {datetime.now().strftime('%A, %B %d, %Y')}. ""Check my calendar for today's events and scan my email ""for anything urgent from the last 12 hours. ""Give me a concise morning briefing under 200 words. ""Format: Calendar section first, then Email highlights.")returnresult.contentifresult.successelse"⚠️ Agent failed to generate briefing."defsend_to_slack(message: str):
"""Post the briefing to Slack."""weather = get_weather(CITY)full_message = f"*☀️ Morning Briefing — {datetime.now().strftime('%A, %B %d')}*\n\n{weather}\n\n{message}"requests.post(SLACK_WEBHOOK,json={"text": full_message},timeout=10)print(f"Briefing sent to Slack at {datetime.now().isoformat()}")if__name__ == "__main__":
briefing = asyncio.run(build_briefing())send_to_slack(briefing)
"""
morning_briefing.py
Sends a daily briefing via Slack: calendar, email highlights, weather.
"""importosimportjsonimportasyncioimportrequestsfromdatetimeimportdatetime,timedeltafromopenclaw_sdkimportOpenClawClientfromopenclaw_sdk.core.configimportClientConfigGATEWAY_URL = os.environ["OPENCLAW_GATEWAY_URL"]API_KEY = os.environ["OPENCLAW_API_KEY"]SLACK_WEBHOOK = os.environ["SLACK_WEBHOOK_URL"]WEATHER_KEY = os.environ["WEATHER_API_KEY"]CITY = os.environ.get("BRIEFING_CITY","London")defget_weather(city: str) -> str:
"""Fetch today's weather summary."""url = f"https://api.weatherapi.com/v1/forecast.json?key={WEATHER_KEY}&q={city}&days=1"resp = requests.get(url,timeout=10)data = resp.json()forecast = data["forecast"]["forecastday"][0]["day"]return(f"🌤 {city}: {forecast['condition']['text']}, "f"{forecast['mintemp_c']}–{forecast['maxtemp_c']}°C, "f"{forecast['daily_chance_of_rain']}% chance of rain")asyncdefbuild_briefing() -> str:
"""Use OpenClaw to compile calendar + email summary."""config = ClientConfig(gateway_ws_url=GATEWAY_URL,api_key=API_KEY,timeout=120,)asyncwithOpenClawClient.connect(**config.model_dump())asclient:
agent = client.get_agent("briefing-bot")result = awaitagent.execute(f"Today is {datetime.now().strftime('%A, %B %d, %Y')}. ""Check my calendar for today's events and scan my email ""for anything urgent from the last 12 hours. ""Give me a concise morning briefing under 200 words. ""Format: Calendar section first, then Email highlights.")returnresult.contentifresult.successelse"⚠️ Agent failed to generate briefing."defsend_to_slack(message: str):
"""Post the briefing to Slack."""weather = get_weather(CITY)full_message = f"*☀️ Morning Briefing — {datetime.now().strftime('%A, %B %d')}*\n\n{weather}\n\n{message}"requests.post(SLACK_WEBHOOK,json={"text": full_message},timeout=10)print(f"Briefing sent to Slack at {datetime.now().isoformat()}")if__name__ == "__main__":
briefing = asyncio.run(build_briefing())send_to_slack(briefing)
"""
morning_briefing.py
Sends a daily briefing via Slack: calendar, email highlights, weather.
"""importosimportjsonimportasyncioimportrequestsfromdatetimeimportdatetime,timedeltafromopenclaw_sdkimportOpenClawClientfromopenclaw_sdk.core.configimportClientConfigGATEWAY_URL = os.environ["OPENCLAW_GATEWAY_URL"]API_KEY = os.environ["OPENCLAW_API_KEY"]SLACK_WEBHOOK = os.environ["SLACK_WEBHOOK_URL"]WEATHER_KEY = os.environ["WEATHER_API_KEY"]CITY = os.environ.get("BRIEFING_CITY","London")defget_weather(city: str) -> str:
"""Fetch today's weather summary."""url = f"https://api.weatherapi.com/v1/forecast.json?key={WEATHER_KEY}&q={city}&days=1"resp = requests.get(url,timeout=10)data = resp.json()forecast = data["forecast"]["forecastday"][0]["day"]return(f"🌤 {city}: {forecast['condition']['text']}, "f"{forecast['mintemp_c']}–{forecast['maxtemp_c']}°C, "f"{forecast['daily_chance_of_rain']}% chance of rain")asyncdefbuild_briefing() -> str:
"""Use OpenClaw to compile calendar + email summary."""config = ClientConfig(gateway_ws_url=GATEWAY_URL,api_key=API_KEY,timeout=120,)asyncwithOpenClawClient.connect(**config.model_dump())asclient:
agent = client.get_agent("briefing-bot")result = awaitagent.execute(f"Today is {datetime.now().strftime('%A, %B %d, %Y')}. ""Check my calendar for today's events and scan my email ""for anything urgent from the last 12 hours. ""Give me a concise morning briefing under 200 words. ""Format: Calendar section first, then Email highlights.")returnresult.contentifresult.successelse"⚠️ Agent failed to generate briefing."defsend_to_slack(message: str):
"""Post the briefing to Slack."""weather = get_weather(CITY)full_message = f"*☀️ Morning Briefing — {datetime.now().strftime('%A, %B %d')}*\n\n{weather}\n\n{message}"requests.post(SLACK_WEBHOOK,json={"text": full_message},timeout=10)print(f"Briefing sent to Slack at {datetime.now().isoformat()}")if__name__ == "__main__":
briefing = asyncio.run(build_briefing())send_to_slack(briefing)
Bolt Schedule Configuration
Setting
Value
Name
morning-briefing
Commands
poetry install → poetry run python scripts/morning_briefing.py
Trigger
Cron: 0 7 * * * (7:00 AM daily)
Notifications
Slack #alerts on failure
Use Case 2: Inbox Triage and Auto-Categorization
Your agent scans unread emails every hour, categorizes them (urgent, action needed, FYI, newsletter), and posts a summary of anything that needs your attention.
The Script
"""
inbox_triage.py
Categorizes unread emails using OpenClaw and posts urgent items to Slack.
"""importosimportjsonimportasyncioimportrequestsfromopenclaw_sdkimportOpenClawClientfromopenclaw_sdk.core.configimportClientConfigGATEWAY_URL = os.environ["OPENCLAW_GATEWAY_URL"]API_KEY = os.environ["OPENCLAW_API_KEY"]SLACK_WEBHOOK = os.environ["SLACK_WEBHOOK_URL"]asyncdeftriage_inbox():
config = ClientConfig(gateway_ws_url=GATEWAY_URL,api_key=API_KEY,timeout=180,)asyncwithOpenClawClient.connect(**config.model_dump())asclient:
agent = client.get_agent("email-triage-bot")result = awaitagent.execute("Check my Gmail inbox for unread messages from the last hour. ""For each email, classify it as one of: ""URGENT (needs response today), ""ACTION (needs response this week), ""FYI (informational, no response needed), ""NEWSLETTER (marketing or subscriptions). ""Return only URGENT and ACTION items with sender, subject, ""and a one-line summary of what's needed. ""If there are no urgent or action items, say 'Inbox clear.'")ifresult.successand"Inbox clear"notinresult.content:
requests.post(SLACK_WEBHOOK,json={"text": f"*📬 Inbox Triage*\n\n{result.content}"},timeout=10,)print("Triage results sent to Slack.")else:
print("No urgent items. Skipping Slack notification.")if__name__ == "__main__":
asyncio.run(triage_inbox())
"""
inbox_triage.py
Categorizes unread emails using OpenClaw and posts urgent items to Slack.
"""importosimportjsonimportasyncioimportrequestsfromopenclaw_sdkimportOpenClawClientfromopenclaw_sdk.core.configimportClientConfigGATEWAY_URL = os.environ["OPENCLAW_GATEWAY_URL"]API_KEY = os.environ["OPENCLAW_API_KEY"]SLACK_WEBHOOK = os.environ["SLACK_WEBHOOK_URL"]asyncdeftriage_inbox():
config = ClientConfig(gateway_ws_url=GATEWAY_URL,api_key=API_KEY,timeout=180,)asyncwithOpenClawClient.connect(**config.model_dump())asclient:
agent = client.get_agent("email-triage-bot")result = awaitagent.execute("Check my Gmail inbox for unread messages from the last hour. ""For each email, classify it as one of: ""URGENT (needs response today), ""ACTION (needs response this week), ""FYI (informational, no response needed), ""NEWSLETTER (marketing or subscriptions). ""Return only URGENT and ACTION items with sender, subject, ""and a one-line summary of what's needed. ""If there are no urgent or action items, say 'Inbox clear.'")ifresult.successand"Inbox clear"notinresult.content:
requests.post(SLACK_WEBHOOK,json={"text": f"*📬 Inbox Triage*\n\n{result.content}"},timeout=10,)print("Triage results sent to Slack.")else:
print("No urgent items. Skipping Slack notification.")if__name__ == "__main__":
asyncio.run(triage_inbox())
"""
inbox_triage.py
Categorizes unread emails using OpenClaw and posts urgent items to Slack.
"""importosimportjsonimportasyncioimportrequestsfromopenclaw_sdkimportOpenClawClientfromopenclaw_sdk.core.configimportClientConfigGATEWAY_URL = os.environ["OPENCLAW_GATEWAY_URL"]API_KEY = os.environ["OPENCLAW_API_KEY"]SLACK_WEBHOOK = os.environ["SLACK_WEBHOOK_URL"]asyncdeftriage_inbox():
config = ClientConfig(gateway_ws_url=GATEWAY_URL,api_key=API_KEY,timeout=180,)asyncwithOpenClawClient.connect(**config.model_dump())asclient:
agent = client.get_agent("email-triage-bot")result = awaitagent.execute("Check my Gmail inbox for unread messages from the last hour. ""For each email, classify it as one of: ""URGENT (needs response today), ""ACTION (needs response this week), ""FYI (informational, no response needed), ""NEWSLETTER (marketing or subscriptions). ""Return only URGENT and ACTION items with sender, subject, ""and a one-line summary of what's needed. ""If there are no urgent or action items, say 'Inbox clear.'")ifresult.successand"Inbox clear"notinresult.content:
requests.post(SLACK_WEBHOOK,json={"text": f"*📬 Inbox Triage*\n\n{result.content}"},timeout=10,)print("Triage results sent to Slack.")else:
print("No urgent items. Skipping Slack notification.")if__name__ == "__main__":
asyncio.run(triage_inbox())
Bolt Schedule Configuration
Setting
Value
Name
inbox-triage-hourly
Commands
poetry install → poetry run python scripts/inbox_triage.py
Trigger
Cron: 0 * * * * (top of every hour)
Notifications
Email on failure (hourly jobs shouldn't spam Slack with failure alerts)
Use Case 3: Calendar Cleanup and Conflict Detection
Once a week, your agent audits the coming week's calendar: flags double-bookings, identifies meetings without agendas, and suggests slots for deep work.
The Script
"""
calendar_cleanup.py
Weekly calendar audit: conflicts, missing agendas, deep work suggestions.
"""importosimportasyncioimportrequestsfromdatetimeimportdatetimefromopenclaw_sdkimportOpenClawClientfromopenclaw_sdk.core.configimportClientConfigGATEWAY_URL = os.environ["OPENCLAW_GATEWAY_URL"]API_KEY = os.environ["OPENCLAW_API_KEY"]SLACK_WEBHOOK = os.environ["SLACK_WEBHOOK_URL"]asyncdefaudit_calendar():
config = ClientConfig(gateway_ws_url=GATEWAY_URL,api_key=API_KEY,timeout=180,)asyncwithOpenClawClient.connect(**config.model_dump())asclient:
agent = client.get_agent("calendar-bot")result = awaitagent.execute("Review my Google Calendar for the upcoming 7 days. ""Find and report:\n""1. CONFLICTS: Any overlapping events (list both events and times)\n""2. NO AGENDA: Meetings that have no description or agenda attached\n""3. OVERLOADED DAYS: Days with more than 5 hours of meetings\n""4. DEEP WORK: Suggest 2-hour blocks where I have no meetings ""that could be reserved for focused work\n\n""Format each section clearly. If everything looks good, say so.")ifresult.success:
requests.post(SLACK_WEBHOOK,json={"text": f"*📅 Weekly Calendar Audit*\n\n{result.content}"},timeout=10,)print("Calendar audit sent to Slack.")if__name__ == "__main__":
asyncio.run(audit_calendar())
"""
calendar_cleanup.py
Weekly calendar audit: conflicts, missing agendas, deep work suggestions.
"""importosimportasyncioimportrequestsfromdatetimeimportdatetimefromopenclaw_sdkimportOpenClawClientfromopenclaw_sdk.core.configimportClientConfigGATEWAY_URL = os.environ["OPENCLAW_GATEWAY_URL"]API_KEY = os.environ["OPENCLAW_API_KEY"]SLACK_WEBHOOK = os.environ["SLACK_WEBHOOK_URL"]asyncdefaudit_calendar():
config = ClientConfig(gateway_ws_url=GATEWAY_URL,api_key=API_KEY,timeout=180,)asyncwithOpenClawClient.connect(**config.model_dump())asclient:
agent = client.get_agent("calendar-bot")result = awaitagent.execute("Review my Google Calendar for the upcoming 7 days. ""Find and report:\n""1. CONFLICTS: Any overlapping events (list both events and times)\n""2. NO AGENDA: Meetings that have no description or agenda attached\n""3. OVERLOADED DAYS: Days with more than 5 hours of meetings\n""4. DEEP WORK: Suggest 2-hour blocks where I have no meetings ""that could be reserved for focused work\n\n""Format each section clearly. If everything looks good, say so.")ifresult.success:
requests.post(SLACK_WEBHOOK,json={"text": f"*📅 Weekly Calendar Audit*\n\n{result.content}"},timeout=10,)print("Calendar audit sent to Slack.")if__name__ == "__main__":
asyncio.run(audit_calendar())
"""
calendar_cleanup.py
Weekly calendar audit: conflicts, missing agendas, deep work suggestions.
"""importosimportasyncioimportrequestsfromdatetimeimportdatetimefromopenclaw_sdkimportOpenClawClientfromopenclaw_sdk.core.configimportClientConfigGATEWAY_URL = os.environ["OPENCLAW_GATEWAY_URL"]API_KEY = os.environ["OPENCLAW_API_KEY"]SLACK_WEBHOOK = os.environ["SLACK_WEBHOOK_URL"]asyncdefaudit_calendar():
config = ClientConfig(gateway_ws_url=GATEWAY_URL,api_key=API_KEY,timeout=180,)asyncwithOpenClawClient.connect(**config.model_dump())asclient:
agent = client.get_agent("calendar-bot")result = awaitagent.execute("Review my Google Calendar for the upcoming 7 days. ""Find and report:\n""1. CONFLICTS: Any overlapping events (list both events and times)\n""2. NO AGENDA: Meetings that have no description or agenda attached\n""3. OVERLOADED DAYS: Days with more than 5 hours of meetings\n""4. DEEP WORK: Suggest 2-hour blocks where I have no meetings ""that could be reserved for focused work\n\n""Format each section clearly. If everything looks good, say so.")ifresult.success:
requests.post(SLACK_WEBHOOK,json={"text": f"*📅 Weekly Calendar Audit*\n\n{result.content}"},timeout=10,)print("Calendar audit sent to Slack.")if__name__ == "__main__":
asyncio.run(audit_calendar())
Bolt Schedule Configuration
Setting
Value
Name
calendar-cleanup-weekly
Commands
poetry install → poetry run python scripts/calendar_cleanup.py
Trigger
Cron: 0 9 * * 1 (Monday at 9:00 AM)
Notifications
Slack #calendar-alerts on failure
Use Case 4: Weekly Status Digest to Slack
Every Friday afternoon, your agent compiles a digest of the week — meetings attended, emails sent, tasks completed, and a summary of key decisions — then posts it to your team's Slack channel.
The Script
"""
weekly_digest.py
Compiles a weekly activity summary and posts to Slack.
"""importosimportasyncioimportrequestsfromdatetimeimportdatetimefromopenclaw_sdkimportOpenClawClientfromopenclaw_sdk.core.configimportClientConfigGATEWAY_URL = os.environ["OPENCLAW_GATEWAY_URL"]API_KEY = os.environ["OPENCLAW_API_KEY"]SLACK_WEBHOOK = os.environ["SLACK_WEBHOOK_URL"]asyncdefgenerate_digest():
config = ClientConfig(gateway_ws_url=GATEWAY_URL,api_key=API_KEY,timeout=240,)asyncwithOpenClawClient.connect(**config.model_dump())asclient:
agent = client.get_agent("digest-bot")result = awaitagent.execute("Compile my weekly summary for the past 5 business days:\n\n""1. MEETINGS: How many meetings did I attend? ""List the 3 most important with key outcomes.\n""2. EMAIL VOLUME: How many emails sent vs received? ""Highlight any threads that are still unresolved.\n""3. KEY DECISIONS: Summarize any decisions or commitments ""made this week based on email and calendar context.\n""4. NEXT WEEK PREVIEW: What's the biggest thing on the ""calendar for next week?\n\n""Keep it under 300 words. Tone: concise and professional.")ifresult.success:
requests.post(SLACK_WEBHOOK,json={"text": f"*📊 Weekly Digest — Week of {datetime.now().strftime('%B %d')}*\n\n{result.content}"},timeout=10,)print("Weekly digest sent to Slack.")if__name__ == "__main__":
asyncio.run(generate_digest())
"""
weekly_digest.py
Compiles a weekly activity summary and posts to Slack.
"""importosimportasyncioimportrequestsfromdatetimeimportdatetimefromopenclaw_sdkimportOpenClawClientfromopenclaw_sdk.core.configimportClientConfigGATEWAY_URL = os.environ["OPENCLAW_GATEWAY_URL"]API_KEY = os.environ["OPENCLAW_API_KEY"]SLACK_WEBHOOK = os.environ["SLACK_WEBHOOK_URL"]asyncdefgenerate_digest():
config = ClientConfig(gateway_ws_url=GATEWAY_URL,api_key=API_KEY,timeout=240,)asyncwithOpenClawClient.connect(**config.model_dump())asclient:
agent = client.get_agent("digest-bot")result = awaitagent.execute("Compile my weekly summary for the past 5 business days:\n\n""1. MEETINGS: How many meetings did I attend? ""List the 3 most important with key outcomes.\n""2. EMAIL VOLUME: How many emails sent vs received? ""Highlight any threads that are still unresolved.\n""3. KEY DECISIONS: Summarize any decisions or commitments ""made this week based on email and calendar context.\n""4. NEXT WEEK PREVIEW: What's the biggest thing on the ""calendar for next week?\n\n""Keep it under 300 words. Tone: concise and professional.")ifresult.success:
requests.post(SLACK_WEBHOOK,json={"text": f"*📊 Weekly Digest — Week of {datetime.now().strftime('%B %d')}*\n\n{result.content}"},timeout=10,)print("Weekly digest sent to Slack.")if__name__ == "__main__":
asyncio.run(generate_digest())
"""
weekly_digest.py
Compiles a weekly activity summary and posts to Slack.
"""importosimportasyncioimportrequestsfromdatetimeimportdatetimefromopenclaw_sdkimportOpenClawClientfromopenclaw_sdk.core.configimportClientConfigGATEWAY_URL = os.environ["OPENCLAW_GATEWAY_URL"]API_KEY = os.environ["OPENCLAW_API_KEY"]SLACK_WEBHOOK = os.environ["SLACK_WEBHOOK_URL"]asyncdefgenerate_digest():
config = ClientConfig(gateway_ws_url=GATEWAY_URL,api_key=API_KEY,timeout=240,)asyncwithOpenClawClient.connect(**config.model_dump())asclient:
agent = client.get_agent("digest-bot")result = awaitagent.execute("Compile my weekly summary for the past 5 business days:\n\n""1. MEETINGS: How many meetings did I attend? ""List the 3 most important with key outcomes.\n""2. EMAIL VOLUME: How many emails sent vs received? ""Highlight any threads that are still unresolved.\n""3. KEY DECISIONS: Summarize any decisions or commitments ""made this week based on email and calendar context.\n""4. NEXT WEEK PREVIEW: What's the biggest thing on the ""calendar for next week?\n\n""Keep it under 300 words. Tone: concise and professional.")ifresult.success:
requests.post(SLACK_WEBHOOK,json={"text": f"*📊 Weekly Digest — Week of {datetime.now().strftime('%B %d')}*\n\n{result.content}"},timeout=10,)print("Weekly digest sent to Slack.")if__name__ == "__main__":
asyncio.run(generate_digest())
Bolt Schedule Configuration
Setting
Value
Name
weekly-digest-friday
Commands
poetry install → poetry run python scripts/weekly_digest.py
Trigger
Cron: 0 17 * * 5 (Friday at 5:00 PM)
Notifications
Slack #team-updates on success; email on failure
Use Case 5: Client Onboarding Workflow
When a new client signs on, trigger a workflow that creates a project folder, sends a welcome email, schedules a kickoff call, and adds follow-up reminders — all in one run.
The Script
"""
client_onboarding.py
Automated onboarding: folder + welcome email + calendar invite + reminders.
Pass client details via environment variable overrides per run.
"""importosimportasynciofromopenclaw_sdkimportOpenClawClientfromopenclaw_sdk.core.configimportClientConfigGATEWAY_URL = os.environ["OPENCLAW_GATEWAY_URL"]API_KEY = os.environ["OPENCLAW_API_KEY"]# Per-run overrides (set via Bolt env var overrides or API trigger)CLIENT_NAME = os.environ.get("CLIENT_NAME","New Client")CLIENT_EMAIL = os.environ.get("CLIENT_EMAIL","client@example.com")PROJECT_TYPE = os.environ.get("PROJECT_TYPE","Standard")asyncdefonboard_client():
config = ClientConfig(gateway_ws_url=GATEWAY_URL,api_key=API_KEY,timeout=300,)asyncwithOpenClawClient.connect(**config.model_dump())asclient:
agent = client.get_agent("onboarding-bot")result = awaitagent.execute(f"Onboard a new client with these details:\n"f"- Name: {CLIENT_NAME}\n"f"- Email: {CLIENT_EMAIL}\n"f"- Project type: {PROJECT_TYPE}\n\n"f"Complete these steps in order:\n"f"1. Create a new folder in Google Drive named "f"'Client - {CLIENT_NAME}' with subfolders: "f"Contracts, Deliverables, Meeting Notes\n"f"2. Send a welcome email to {CLIENT_EMAIL} with next steps "f"and a link to the shared folder\n"f"3. Schedule a 30-minute kickoff call for next week "f"(find an open slot on my calendar)\n"f"4. Create a follow-up reminder for 3 days after the "f"kickoff call\n\n"f"Confirm each step as you complete it.")ifresult.success:
print(f"✅ Onboarding complete for {CLIENT_NAME}")print(result.content)else:
print(f"❌ Onboarding failed for {CLIENT_NAME}")print(result.content)raiseSystemExit(1)# Triggers Bolt failure notificationif__name__ == "__main__":
asyncio.run(onboard_client())
"""
client_onboarding.py
Automated onboarding: folder + welcome email + calendar invite + reminders.
Pass client details via environment variable overrides per run.
"""importosimportasynciofromopenclaw_sdkimportOpenClawClientfromopenclaw_sdk.core.configimportClientConfigGATEWAY_URL = os.environ["OPENCLAW_GATEWAY_URL"]API_KEY = os.environ["OPENCLAW_API_KEY"]# Per-run overrides (set via Bolt env var overrides or API trigger)CLIENT_NAME = os.environ.get("CLIENT_NAME","New Client")CLIENT_EMAIL = os.environ.get("CLIENT_EMAIL","client@example.com")PROJECT_TYPE = os.environ.get("PROJECT_TYPE","Standard")asyncdefonboard_client():
config = ClientConfig(gateway_ws_url=GATEWAY_URL,api_key=API_KEY,timeout=300,)asyncwithOpenClawClient.connect(**config.model_dump())asclient:
agent = client.get_agent("onboarding-bot")result = awaitagent.execute(f"Onboard a new client with these details:\n"f"- Name: {CLIENT_NAME}\n"f"- Email: {CLIENT_EMAIL}\n"f"- Project type: {PROJECT_TYPE}\n\n"f"Complete these steps in order:\n"f"1. Create a new folder in Google Drive named "f"'Client - {CLIENT_NAME}' with subfolders: "f"Contracts, Deliverables, Meeting Notes\n"f"2. Send a welcome email to {CLIENT_EMAIL} with next steps "f"and a link to the shared folder\n"f"3. Schedule a 30-minute kickoff call for next week "f"(find an open slot on my calendar)\n"f"4. Create a follow-up reminder for 3 days after the "f"kickoff call\n\n"f"Confirm each step as you complete it.")ifresult.success:
print(f"✅ Onboarding complete for {CLIENT_NAME}")print(result.content)else:
print(f"❌ Onboarding failed for {CLIENT_NAME}")print(result.content)raiseSystemExit(1)# Triggers Bolt failure notificationif__name__ == "__main__":
asyncio.run(onboard_client())
"""
client_onboarding.py
Automated onboarding: folder + welcome email + calendar invite + reminders.
Pass client details via environment variable overrides per run.
"""importosimportasynciofromopenclaw_sdkimportOpenClawClientfromopenclaw_sdk.core.configimportClientConfigGATEWAY_URL = os.environ["OPENCLAW_GATEWAY_URL"]API_KEY = os.environ["OPENCLAW_API_KEY"]# Per-run overrides (set via Bolt env var overrides or API trigger)CLIENT_NAME = os.environ.get("CLIENT_NAME","New Client")CLIENT_EMAIL = os.environ.get("CLIENT_EMAIL","client@example.com")PROJECT_TYPE = os.environ.get("PROJECT_TYPE","Standard")asyncdefonboard_client():
config = ClientConfig(gateway_ws_url=GATEWAY_URL,api_key=API_KEY,timeout=300,)asyncwithOpenClawClient.connect(**config.model_dump())asclient:
agent = client.get_agent("onboarding-bot")result = awaitagent.execute(f"Onboard a new client with these details:\n"f"- Name: {CLIENT_NAME}\n"f"- Email: {CLIENT_EMAIL}\n"f"- Project type: {PROJECT_TYPE}\n\n"f"Complete these steps in order:\n"f"1. Create a new folder in Google Drive named "f"'Client - {CLIENT_NAME}' with subfolders: "f"Contracts, Deliverables, Meeting Notes\n"f"2. Send a welcome email to {CLIENT_EMAIL} with next steps "f"and a link to the shared folder\n"f"3. Schedule a 30-minute kickoff call for next week "f"(find an open slot on my calendar)\n"f"4. Create a follow-up reminder for 3 days after the "f"kickoff call\n\n"f"Confirm each step as you complete it.")ifresult.success:
print(f"✅ Onboarding complete for {CLIENT_NAME}")print(result.content)else:
print(f"❌ Onboarding failed for {CLIENT_NAME}")print(result.content)raiseSystemExit(1)# Triggers Bolt failure notificationif__name__ == "__main__":
asyncio.run(onboard_client())
Bolt Schedule Configuration
This one is different — it's not cron-triggered. It runs on demand via Paradime's Bolt API.
Setting
Value
Name
client-onboarding
Commands
poetry install → poetry run python scripts/client_onboarding.py
Trigger
Bolt API (triggered externally) or Manual
Environment Override
Set CLIENT_NAME, CLIENT_EMAIL, PROJECT_TYPE per run
To trigger a run with custom client details, use the Paradime Python SDK:
Chaining Multiple Automations in a Single Schedule
Some workflows benefit from running multiple scripts in sequence. Paradime's Bolt scheduler executes commands one after another — if any step fails, the sequence stops and your notification fires.
Example: Full Morning Automation
A single schedule that runs at 7 AM and handles your entire morning prep:
The order matters. The briefing script can reference the fact that triage and calendar cleanup already ran — your inbox is categorized and your calendar is conflict-free before the summary goes out.
Example: End-of-Week Wrap
Monitoring and Debugging
Where Logs Live
Every Bolt run captures three levels of logs, accessible from the schedule's run history in the Bolt UI:
Log Level
What It Shows
Use It For
Summary
AI-generated overview with warnings
Quick health checks after each run
Console
Full stdout and stderr from each command
Standard debugging — your print() statements appear here
Debug
System-level operations and internal details
Deep analysis when something is subtly wrong
Run History
Navigate to your schedule in Bolt and click any run to see status (pass/fail), duration, and a command-by-command breakdown. If your morning briefing took 3 minutes yesterday but 45 seconds today, you can compare runs side by side.
Proactive Alerting
Beyond per-schedule notifications, use SLA alerts to catch performance degradation. If your inbox triage normally takes 30 seconds but one run takes 5 minutes, that's a signal your OpenClaw gateway or AI provider is under pressure — and you want to know before it becomes a full outage.
Troubleshooting Common Issues
ModuleNotFoundError: No module named 'openclaw_sdk'
Cause:poetry install didn't run, or the SDK isn't in pyproject.toml.
Fix: Confirm openclaw-sdk is listed under [tool.poetry.dependencies] in pyproject.toml, and ensure poetry install is the first command in your Bolt schedule. If the problem persists, delete poetry.lock, run poetry lock to regenerate it, and commit the new lock file.
KeyError: 'OPENCLAW_API_KEY'
Cause: The variable is set in Code IDE but not in Bolt Schedules (or vice versa). They're completely independent stores.
Fix: Go to Settings → Workspaces → Environment Variables → Bolt Schedules and add the missing key. Double-check both sections side by side — this is the most common gotcha.
ConnectionRefusedError or WebSocket connection failed
Cause: Your OpenClaw gateway is unreachable from Paradime's infrastructure.
Fix: If your gateway has an IP allowlist, add Paradime's static IPs:
Region
IP Address
EU - Frankfurt
18.198.76.50
EU - Ireland
3.248.153.24
EU - London
3.8.231.109
US East - N. Virginia
52.4.225.182
If you're running the gateway on localhost — that's the problem. Paradime can't reach your laptop. Either deploy the gateway to a cloud server or switch to direct API key usage with the SDK.
TimeoutError: Agent did not respond within 120s
Cause: The agent task is too complex for the default timeout, or the AI provider is slow.
Fix: Increase the timeout in your ClientConfig (e.g., timeout=300 for 5 minutes), or break the task into smaller sequential prompts instead of one monolithic request. For long-running operations, use agent.execute_stream() — streaming keeps the connection alive.
Script Works in Code IDE but Fails in Bolt
Cause: Environment variable mismatch. The Code IDE and Bolt Schedules sections have separate variable stores.
Fix: Compare both sections side by side in Settings → Environment Variables. The most common gap: a variable exists in Code IDE but was never copied to Bolt Schedules.
Wrapping Up
Running OpenClaw automations in Paradime means your agents work around the clock without you babysitting a Mac Mini or praying your VPS stays up. Here's what you've built:
✅ A repository of OpenClaw automation scripts — morning briefings, inbox triage, calendar cleanup, weekly digests, and client onboarding
✅ Reproducible dependencies managed with Poetry
✅ Secrets stored in Paradime's encrypted environment variable store — not on any machine
✅ Tested end-to-end in the Code IDE before going to production
✅ Bolt schedules with cron triggers, API triggers, failure notifications, and full run history
✅ Chained automations that run in sequence with automatic failure stopping
No always-on laptop. No plaintext tokens. No silent failures at 3 AM. Just scripts, schedules, and automations that run reliably every single time.
*dbt® and dbt Core® are federally registered trademarks of dbt Labs, Inc. in the United States and various jurisdictions around the world. Paradime is not a partner of dbt Labs. All rights therein are reserved to dbt Labs. Paradime is not a product or service of or endorsed by dbt Labs, Inc.
*dbt® and dbt Core® are federally registered trademarks of dbt Labs, Inc. in the United States and various jurisdictions around the world. Paradime is not a partner of dbt Labs. All rights therein are reserved to dbt Labs. Paradime is not a product or service of or endorsed by dbt Labs, Inc.
*dbt® and dbt Core® are federally registered trademarks of dbt Labs, Inc. in the United States and various jurisdictions around the world. Paradime is not a partner of dbt Labs. All rights therein are reserved to dbt Labs. Paradime is not a product or service of or endorsed by dbt Labs, Inc.