How to Run OpenClaw in Paradime

Feb 26, 2026

Table of Contents

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.

OpenClaw Access

You need one of the following:

Setup

What You Need

Best For

OpenClaw Python SDK

pip install openclaw-sdk + AI provider API key

Scripting agent tasks directly (our recommendation)

Self-hosted Gateway

Gateway URL + token

Teams with a shared OpenClaw deployment

Google Workspace CLI (gog)

OAuth credentials for Gmail/Calendar/Drive

Calendar and email automations via the gog CLI

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.

Create Your pyproject.toml

[tool.poetry]
name = "openclaw-automations"
version = "1.0.0"
description = "Scheduled OpenClaw automations running on Paradime Bolt"
authors = ["Your Team"]

[tool.poetry.dependencies]
python = "^3.9"
openclaw-sdk = "^2.1.0"
google-api-python-client = "^2.100.0"
google-auth-oauthlib = "^1.2.0"
requests = "^2.31.0"
slack-sdk = "^3.27.0"

[build-system]
requires = ["poetry-core"]

[tool.poetry]
name = "openclaw-automations"
version = "1.0.0"
description = "Scheduled OpenClaw automations running on Paradime Bolt"
authors = ["Your Team"]

[tool.poetry.dependencies]
python = "^3.9"
openclaw-sdk = "^2.1.0"
google-api-python-client = "^2.100.0"
google-auth-oauthlib = "^1.2.0"
requests = "^2.31.0"
slack-sdk = "^3.27.0"

[build-system]
requires = ["poetry-core"]

[tool.poetry]
name = "openclaw-automations"
version = "1.0.0"
description = "Scheduled OpenClaw automations running on Paradime Bolt"
authors = ["Your Team"]

[tool.poetry.dependencies]
python = "^3.9"
openclaw-sdk = "^2.1.0"
google-api-python-client = "^2.100.0"
google-auth-oauthlib = "^1.2.0"
requests = "^2.31.0"
slack-sdk = "^3.27.0"

[build-system]
requires = ["poetry-core"]

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)

  1. Go to Settings → Workspaces → Environment Variables.

  2. In the Bolt Schedules section, click Add New.

  3. 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.

Accessing Variables in Your Scripts

import os
import json

# Simple string secrets
api_key = os.environ["ANTHROPIC_API_KEY"]
webhook_url = os.environ["SLACK_WEBHOOK_URL"]

# JSON-encoded secrets (like Google OAuth credentials)
google_creds = json.loads(os.environ["GOOGLE_CREDENTIALS_JSON"])
google_token = json.loads(os.environ["GOOGLE_TOKEN_JSON"])
import os
import json

# Simple string secrets
api_key = os.environ["ANTHROPIC_API_KEY"]
webhook_url = os.environ["SLACK_WEBHOOK_URL"]

# JSON-encoded secrets (like Google OAuth credentials)
google_creds = json.loads(os.environ["GOOGLE_CREDENTIALS_JSON"])
google_token = json.loads(os.environ["GOOGLE_TOKEN_JSON"])
import os
import json

# Simple string secrets
api_key = os.environ["ANTHROPIC_API_KEY"]
webhook_url = os.environ["SLACK_WEBHOOK_URL"]

# JSON-encoded secrets (like Google OAuth credentials)
google_creds = json.loads(os.environ["GOOGLE_CREDENTIALS_JSON"])
google_token = json.loads(os.environ["GOOGLE_TOKEN_JSON"])

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.
"""
import os
import json
import asyncio
import requests
from datetime import datetime, timedelta
from openclaw_sdk import OpenClawClient
from openclaw_sdk.core.config import ClientConfig

GATEWAY_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")

def get_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"
    )

async def build_briefing() -> str:
    """Use OpenClaw to compile calendar + email summary."""
    config = ClientConfig(
        gateway_ws_url=GATEWAY_URL,
        api_key=API_KEY,
        timeout=120,
    )

    async with OpenClawClient.connect(**config.model_dump()) as client:
        agent = client.get_agent("briefing-bot")

        result = await agent.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."
        )

        return result.content if result.success else "⚠️ Agent failed to generate briefing."

def send_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.
"""
import os
import json
import asyncio
import requests
from datetime import datetime, timedelta
from openclaw_sdk import OpenClawClient
from openclaw_sdk.core.config import ClientConfig

GATEWAY_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")

def get_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"
    )

async def build_briefing() -> str:
    """Use OpenClaw to compile calendar + email summary."""
    config = ClientConfig(
        gateway_ws_url=GATEWAY_URL,
        api_key=API_KEY,
        timeout=120,
    )

    async with OpenClawClient.connect(**config.model_dump()) as client:
        agent = client.get_agent("briefing-bot")

        result = await agent.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."
        )

        return result.content if result.success else "⚠️ Agent failed to generate briefing."

def send_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.
"""
import os
import json
import asyncio
import requests
from datetime import datetime, timedelta
from openclaw_sdk import OpenClawClient
from openclaw_sdk.core.config import ClientConfig

GATEWAY_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")

def get_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"
    )

async def build_briefing() -> str:
    """Use OpenClaw to compile calendar + email summary."""
    config = ClientConfig(
        gateway_ws_url=GATEWAY_URL,
        api_key=API_KEY,
        timeout=120,
    )

    async with OpenClawClient.connect(**config.model_dump()) as client:
        agent = client.get_agent("briefing-bot")

        result = await agent.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."
        )

        return result.content if result.success else "⚠️ Agent failed to generate briefing."

def send_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 installpoetry 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.
"""
import os
import json
import asyncio
import requests
from openclaw_sdk import OpenClawClient
from openclaw_sdk.core.config import ClientConfig

GATEWAY_URL = os.environ["OPENCLAW_GATEWAY_URL"]
API_KEY = os.environ["OPENCLAW_API_KEY"]
SLACK_WEBHOOK = os.environ["SLACK_WEBHOOK_URL"]

async def triage_inbox():
    config = ClientConfig(
        gateway_ws_url=GATEWAY_URL,
        api_key=API_KEY,
        timeout=180,
    )

    async with OpenClawClient.connect(**config.model_dump()) as client:
        agent = client.get_agent("email-triage-bot")

        result = await agent.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.'"
        )

        if result.success and "Inbox clear" not in result.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.
"""
import os
import json
import asyncio
import requests
from openclaw_sdk import OpenClawClient
from openclaw_sdk.core.config import ClientConfig

GATEWAY_URL = os.environ["OPENCLAW_GATEWAY_URL"]
API_KEY = os.environ["OPENCLAW_API_KEY"]
SLACK_WEBHOOK = os.environ["SLACK_WEBHOOK_URL"]

async def triage_inbox():
    config = ClientConfig(
        gateway_ws_url=GATEWAY_URL,
        api_key=API_KEY,
        timeout=180,
    )

    async with OpenClawClient.connect(**config.model_dump()) as client:
        agent = client.get_agent("email-triage-bot")

        result = await agent.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.'"
        )

        if result.success and "Inbox clear" not in result.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.
"""
import os
import json
import asyncio
import requests
from openclaw_sdk import OpenClawClient
from openclaw_sdk.core.config import ClientConfig

GATEWAY_URL = os.environ["OPENCLAW_GATEWAY_URL"]
API_KEY = os.environ["OPENCLAW_API_KEY"]
SLACK_WEBHOOK = os.environ["SLACK_WEBHOOK_URL"]

async def triage_inbox():
    config = ClientConfig(
        gateway_ws_url=GATEWAY_URL,
        api_key=API_KEY,
        timeout=180,
    )

    async with OpenClawClient.connect(**config.model_dump()) as client:
        agent = client.get_agent("email-triage-bot")

        result = await agent.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.'"
        )

        if result.success and "Inbox clear" not in result.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 installpoetry 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.
"""
import os
import asyncio
import requests
from datetime import datetime
from openclaw_sdk import OpenClawClient
from openclaw_sdk.core.config import ClientConfig

GATEWAY_URL = os.environ["OPENCLAW_GATEWAY_URL"]
API_KEY = os.environ["OPENCLAW_API_KEY"]
SLACK_WEBHOOK = os.environ["SLACK_WEBHOOK_URL"]

async def audit_calendar():
    config = ClientConfig(
        gateway_ws_url=GATEWAY_URL,
        api_key=API_KEY,
        timeout=180,
    )

    async with OpenClawClient.connect(**config.model_dump()) as client:
        agent = client.get_agent("calendar-bot")

        result = await agent.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."
        )

        if result.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.
"""
import os
import asyncio
import requests
from datetime import datetime
from openclaw_sdk import OpenClawClient
from openclaw_sdk.core.config import ClientConfig

GATEWAY_URL = os.environ["OPENCLAW_GATEWAY_URL"]
API_KEY = os.environ["OPENCLAW_API_KEY"]
SLACK_WEBHOOK = os.environ["SLACK_WEBHOOK_URL"]

async def audit_calendar():
    config = ClientConfig(
        gateway_ws_url=GATEWAY_URL,
        api_key=API_KEY,
        timeout=180,
    )

    async with OpenClawClient.connect(**config.model_dump()) as client:
        agent = client.get_agent("calendar-bot")

        result = await agent.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."
        )

        if result.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.
"""
import os
import asyncio
import requests
from datetime import datetime
from openclaw_sdk import OpenClawClient
from openclaw_sdk.core.config import ClientConfig

GATEWAY_URL = os.environ["OPENCLAW_GATEWAY_URL"]
API_KEY = os.environ["OPENCLAW_API_KEY"]
SLACK_WEBHOOK = os.environ["SLACK_WEBHOOK_URL"]

async def audit_calendar():
    config = ClientConfig(
        gateway_ws_url=GATEWAY_URL,
        api_key=API_KEY,
        timeout=180,
    )

    async with OpenClawClient.connect(**config.model_dump()) as client:
        agent = client.get_agent("calendar-bot")

        result = await agent.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."
        )

        if result.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 installpoetry 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.
"""
import os
import asyncio
import requests
from datetime import datetime
from openclaw_sdk import OpenClawClient
from openclaw_sdk.core.config import ClientConfig

GATEWAY_URL = os.environ["OPENCLAW_GATEWAY_URL"]
API_KEY = os.environ["OPENCLAW_API_KEY"]
SLACK_WEBHOOK = os.environ["SLACK_WEBHOOK_URL"]

async def generate_digest():
    config = ClientConfig(
        gateway_ws_url=GATEWAY_URL,
        api_key=API_KEY,
        timeout=240,
    )

    async with OpenClawClient.connect(**config.model_dump()) as client:
        agent = client.get_agent("digest-bot")

        result = await agent.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."
        )

        if result.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.
"""
import os
import asyncio
import requests
from datetime import datetime
from openclaw_sdk import OpenClawClient
from openclaw_sdk.core.config import ClientConfig

GATEWAY_URL = os.environ["OPENCLAW_GATEWAY_URL"]
API_KEY = os.environ["OPENCLAW_API_KEY"]
SLACK_WEBHOOK = os.environ["SLACK_WEBHOOK_URL"]

async def generate_digest():
    config = ClientConfig(
        gateway_ws_url=GATEWAY_URL,
        api_key=API_KEY,
        timeout=240,
    )

    async with OpenClawClient.connect(**config.model_dump()) as client:
        agent = client.get_agent("digest-bot")

        result = await agent.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."
        )

        if result.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.
"""
import os
import asyncio
import requests
from datetime import datetime
from openclaw_sdk import OpenClawClient
from openclaw_sdk.core.config import ClientConfig

GATEWAY_URL = os.environ["OPENCLAW_GATEWAY_URL"]
API_KEY = os.environ["OPENCLAW_API_KEY"]
SLACK_WEBHOOK = os.environ["SLACK_WEBHOOK_URL"]

async def generate_digest():
    config = ClientConfig(
        gateway_ws_url=GATEWAY_URL,
        api_key=API_KEY,
        timeout=240,
    )

    async with OpenClawClient.connect(**config.model_dump()) as client:
        agent = client.get_agent("digest-bot")

        result = await agent.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."
        )

        if result.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 installpoetry 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.
"""
import os
import asyncio
from openclaw_sdk import OpenClawClient
from openclaw_sdk.core.config import ClientConfig

GATEWAY_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")

async def onboard_client():
    config = ClientConfig(
        gateway_ws_url=GATEWAY_URL,
        api_key=API_KEY,
        timeout=300,
    )

    async with OpenClawClient.connect(**config.model_dump()) as client:
        agent = client.get_agent("onboarding-bot")

        result = await agent.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."
        )

        if result.success:
            print(f"✅ Onboarding complete for {CLIENT_NAME}")
            print(result.content)
        else:
            print(f"❌ Onboarding failed for {CLIENT_NAME}")
            print(result.content)
            raise SystemExit(1)  # Triggers Bolt failure notification

if __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.
"""
import os
import asyncio
from openclaw_sdk import OpenClawClient
from openclaw_sdk.core.config import ClientConfig

GATEWAY_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")

async def onboard_client():
    config = ClientConfig(
        gateway_ws_url=GATEWAY_URL,
        api_key=API_KEY,
        timeout=300,
    )

    async with OpenClawClient.connect(**config.model_dump()) as client:
        agent = client.get_agent("onboarding-bot")

        result = await agent.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."
        )

        if result.success:
            print(f"✅ Onboarding complete for {CLIENT_NAME}")
            print(result.content)
        else:
            print(f"❌ Onboarding failed for {CLIENT_NAME}")
            print(result.content)
            raise SystemExit(1)  # Triggers Bolt failure notification

if __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.
"""
import os
import asyncio
from openclaw_sdk import OpenClawClient
from openclaw_sdk.core.config import ClientConfig

GATEWAY_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")

async def onboard_client():
    config = ClientConfig(
        gateway_ws_url=GATEWAY_URL,
        api_key=API_KEY,
        timeout=300,
    )

    async with OpenClawClient.connect(**config.model_dump()) as client:
        agent = client.get_agent("onboarding-bot")

        result = await agent.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."
        )

        if result.success:
            print(f"✅ Onboarding complete for {CLIENT_NAME}")
            print(result.content)
        else:
            print(f"❌ Onboarding failed for {CLIENT_NAME}")
            print(result.content)
            raise SystemExit(1)  # Triggers Bolt failure notification

if __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 installpoetry 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:

from paradime import Paradime

paradime = Paradime(
    api_endpoint="YOUR_API_ENDPOINT",
    api_key="YOUR_API_KEY",
    api_secret="YOUR_API_SECRET",
)

run_id = paradime.bolt.trigger_run(
    schedule_name="client-onboarding",
    commands=[
        "poetry install",
        "CLIENT_NAME='Acme Corp' CLIENT_EMAIL='cto@acme.com' "
        "PROJECT_TYPE='Enterprise' poetry run python scripts/client_onboarding.py"
    ]
)
from paradime import Paradime

paradime = Paradime(
    api_endpoint="YOUR_API_ENDPOINT",
    api_key="YOUR_API_KEY",
    api_secret="YOUR_API_SECRET",
)

run_id = paradime.bolt.trigger_run(
    schedule_name="client-onboarding",
    commands=[
        "poetry install",
        "CLIENT_NAME='Acme Corp' CLIENT_EMAIL='cto@acme.com' "
        "PROJECT_TYPE='Enterprise' poetry run python scripts/client_onboarding.py"
    ]
)
from paradime import Paradime

paradime = Paradime(
    api_endpoint="YOUR_API_ENDPOINT",
    api_key="YOUR_API_KEY",
    api_secret="YOUR_API_SECRET",
)

run_id = paradime.bolt.trigger_run(
    schedule_name="client-onboarding",
    commands=[
        "poetry install",
        "CLIENT_NAME='Acme Corp' CLIENT_EMAIL='cto@acme.com' "
        "PROJECT_TYPE='Enterprise' poetry run python scripts/client_onboarding.py"
    ]
)

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.

Further Reading:

Interested to Learn More? Try Out the Free 14-Day Trial

Start free trial →

Interested to Learn More?
Try Out the Free 14-Days Trial
decorative icon

Future of Data Work
Available Today

decorative icon

Future of Data Work
Available Today

decorative icon

Future of Data Work
Available Today

Copyright © 2026 Paradime Labs, Inc.

Made with ❤️ in San Francisco ・ London

*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.

Copyright © 2026 Paradime Labs, Inc.

Made with ❤️ in San Francisco ・ London

*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.

Copyright © 2026 Paradime Labs, Inc.

Made with ❤️ in San Francisco ・ London

*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.