clawpub/OPENCLAW_TRICKS.md

27 KiB
Raw Blame History

OPENCLAW_TRICKS.md — Configuration Recipes for OpenClaw Agents

A collection of tested patterns, prompts, and file structures for configuring an OpenClaw agent as a proactive personal assistant. These are extracted from a production setup that's been running since early 2026.


Table of Contents

  1. Workspace Bootstrapping
  2. Daily Context — The State File
  3. Sitrep (Situation Report)
  4. Sleep Tracking
  5. Location & Timezone Tracking
  6. Medication Tracking
  7. Flight & Travel Logging
  8. Landing Checklist
  9. Memory Architecture
  10. Heartbeat Configuration
  11. Gitea Integration & Notification Polling
  12. Sub-Agent Management
  13. Urgent Notifications via ntfy
  14. Group Chat Behavior
  15. Cron vs Heartbeat — When to Use Each
  16. Requirement Capture

Workspace Bootstrapping

Your workspace is the agent's home directory. Core files:

workspace/
├── AGENTS.md          # Responsibilities, rules, procedures
├── SOUL.md            # Personality, tone, values
├── USER.md            # Info about your human (name, tz, prefs)
├── IDENTITY.md        # Agent's own identity
├── HEARTBEAT.md       # What to check on heartbeat polls
├── MEMORY.md          # Curated long-term memory
├── TOOLS.md           # Environment-specific notes (hosts, keys, devices)
└── memory/
    ├── daily-context.json
    ├── YYYY-MM-DD.md          # Daily raw notes
    ├── sleep-log.csv
    ├── location-log.csv
    ├── flight-log.csv
    ├── medications-log-YYYY-MM.csv
    ├── medications-instructions.md
    ├── landing-checklist.md
    ├── checklist-*.md         # Various operational checklists
    └── heartbeat-state.json

Session startup prompt (put in AGENTS.md):

## Every Session

Before doing anything else:

1. Read `SOUL.md` — this is who you are
2. Read `USER.md` — this is who you're helping
3. Read `memory/daily-context.json` — current state (location, timezone, sleep, meds)
4. Read `memory/YYYY-MM-DD.md` (today + yesterday) for recent context
5. **If in MAIN SESSION** (direct chat with your human): Also read `MEMORY.md`

Don't ask permission. Just do it.

This ensures the agent always has context on wake. The key insight is that the agent wakes up fresh every session — files ARE its memory.


Daily Context — The State File

This is the single most important file. It's a JSON blob that every session reads on every message. It tracks the current state of your human.

Schema: memory/daily-context.json

{
  "isSleeping": false,
  "lastKnownWakeTime": "2026-02-28T12:30:00+07:00",
  "predictedSleepTime": "2026-03-01T05:30:00+07:00",
  "predictedWakeTime": "2026-03-01T12:45:00+07:00",
  "hasTakenDailyMedsToday": false,
  "dailyMedsTimestamp": "2026-02-27T11:43:00+07:00",
  "lastCaffeineTimestamp": null,
  "currentLocation": "City (IATA)",
  "currentTimezone": "Asia/Bangkok",
  "currentLodging": "Hotel Name",
  "travelLeg": "Description of current travel phase",
  "nearestAirport": "ICAO code",
  "lastMessageFromUser": "2026-02-28T05:20:00+07:00",
  "lastMessageChannel": "mattermost",
  "isAvailable": true,
  "lastUpdated": "2026-02-28T06:00:00+07:00",
  "lastSleep": "actual: 2026-02-28 05:15-12:30 ICT (~7h15m). Stable pattern."
}

AGENTS.md prompt:

## Daily Context

Stored in `memory/daily-context.json`. All agents: review on every
conversation/message to detect if any state has changed. Update the JSON file
directly.

Why it works:

  • Every session reads this first, so the agent always knows where you are
  • Sleep predictions help the agent decide when to alert vs stay quiet
  • Medication timestamps enable overdue detection
  • Timezone field means the agent always converts times correctly
  • lastMessageFromUser lets the agent infer activity gaps = sleep

Sitrep (Situation Report)

The sitrep is triggered by a keyword (e.g. "sitrep") and produces a concise status briefing. The key design feature is that the agent can add sections dynamically based on what it thinks you should know.

AGENTS.md prompt:

### Sitrep (Situation Report)

When the user says "sitrep", provide a concise summary covering:

1. **Daily meds** — taken today or not
2. **Interval meds** — any due/overdue or upcoming in next 48h.
   ALWAYS include "X days from now" countdown. ALWAYS include day of week.
3. **Open issues assigned to me** — count
4. **Open issues assigned to user** — count + brief summary
5. **Upcoming travel** — flights in next 72h with times/airports.
   ALWAYS also include the next known flight even if beyond 72h.
6. **Upcoming appointments** — next 48h
7. **Todo list** — overdue, due today, due tomorrow (separate categories)
8. **Unbooked travel** — flights that need booking. Flag deadlines.
9. **Sleep conflicts** — appointments in next 48h that fall within
   predicted sleep window
10. **Sleep** — one-line summary of last sleep + drift trend + concerns
11. **Unanswered questions** — questions the agent asked that haven't
    been answered
12. **Weather alerts** — only if significant or extreme. Use METAR from
    aviationweather.gov. Omit if nothing notable.
13. **Overdue reminders** — anything pending
14. **Open projects** — one-line status per project

Before generating a sitrep, review the last 3 days of daily memory files
for context. **If anything notable isn't covered by the items above —
recent lessons, pending decisions, things you think the user should know
about — add additional sections as needed.**

Omit any item that is "none" or zero. Keep it scannable. Use bullet
points, not prose. Only surface things the user might not know about or
needs to act on.

Key design decisions:

  • "Add additional sections as needed" — this is the magic line. It lets the agent surface things you didn't think to ask about. If there's a pending decision from 2 days ago, or a lesson from a recent mistake, it'll include it.
  • "Omit any item that is none or zero" — keeps it clean. No "Overdue reminders: none" clutter.
  • Relative times ("4 days from now, Tuesday") are more useful than bare dates
  • Review last 3 days ensures the agent has recent context, not just today
  • The sitrep pulls from multiple data sources (daily context, calendars, issue trackers, memory files) — it's a dashboard in prose form

Time display tip:

Include current time in local timezone, UTC, and any other relevant timezone
at the top.

This anchors the reader and makes all the relative times unambiguous.


Sleep Tracking

The agent infers sleep from message activity gaps, not from explicit "I'm going to sleep" statements (though those help too).

File: memory/sleep-log.csv

Date,SleepTime,WakeTime,TimeZone,Duration,Status,Notes
2026-02-07,08:30,15:30,America/Los_Angeles,7h00m,actual,Approximate times
2026-02-08,~12:00,~15:30,America/Los_Angeles,~3h30m,actual,Short sleep

AGENTS.md prompt:

### Sleep Tracking

- **`memory/sleep-log.csv`** — columns: Date, SleepTime, WakeTime,
  TimeZone, Duration, Status, Notes
- Infer sleep/wake times from message activity and explicit statements
- User's sleep pattern drifts later each day; typical duration 48 hours
- Update daily-context.json isSleeping field accordingly
- **On every message from user:** if there was a communication gap
  overlapping predicted sleep time, infer a sleep window (sleep start =
  last activity before gap, wake = first activity after gap). Activity
  includes direct messages, git commits/comments, scheduled flight
  departures, and any other observable actions — not just chat messages.
  Log based on observed gaps only, never from mathematical predictions.

Daily context fields for sleep:

{
  "isSleeping": false,
  "lastKnownWakeTime": "2026-02-28T12:30:00+07:00",
  "predictedSleepTime": "2026-03-01T05:30:00+07:00",
  "predictedWakeTime": "2026-03-01T12:45:00+07:00",
  "lastSleep": "actual: 2026-02-28 05:15-12:30 ICT (~7h15m). Stable pattern."
}

How prediction works:

The agent observes the pattern drift (e.g., sleeping 30min later each day) and extrapolates. Predictions are updated after each actual observation. The agent uses predictions to:

  • Avoid sending non-urgent alerts during predicted sleep
  • Flag sleep conflicts with upcoming appointments in sitreps
  • Factor caffeine intake into predictions (caffeine = 5-6h minimum awake)

Caffeine integration:

{
  "lastCaffeineTimestamp": "2026-02-10T00:45:00-08:00"
}

Track caffeine in daily-context.json. If the user has caffeine, adjust sleep prediction forward by their typical caffeine-to-sleep duration.


Location & Timezone Tracking

The agent always knows where you are and adjusts all time displays accordingly.

File: memory/location-log.csv

Date,City,Country,Timezone
2026-02-08,Las Vegas,US,America/Los_Angeles
2026-02-11,Berlin,DE,Europe/Berlin
2026-02-18,Bangkok,TH,Asia/Bangkok

Timezone rules (AGENTS.md):

## Timezone/Time Rules

- System clock is PST. User's TZ is in daily-context.json — always convert.
- "Today"/"tomorrow" = user's local TZ, not system clock.
- Never state times without explicit conversion.
- When logging medication times, always use the user's current timezone.

Why this matters:

OpenClaw runs on a server (probably in a fixed timezone). Your human travels. Without explicit timezone tracking:

  • "Take your meds" fires at 3am local time
  • "Today" means the wrong day
  • Sleep predictions are off by hours
  • Calendar events show wrong times

The daily-context.json currentTimezone field is the single source of truth. Everything else derives from it.


Medication Tracking

This is a safety-critical system. The design prioritizes never missing a dose and never double-dosing over convenience.

Files:

  • memory/medications-instructions.md — the authoritative medication list, dosages, schedules, and safety rules
  • memory/medications-log-YYYY-MM.csv — one row per ingestion, split by month
  • memory/checklist-medications.md — pre-action verification checklist

Log format: memory/medications-log-YYYY-MM.csv

Date,Time,TimeZone,Medication,Dosage
2026-02-27,11:43,Asia/Bangkok,Metoprolol,50 mg
2026-02-27,11:43,Asia/Bangkok,Omeprazole,40 mg
2026-02-27,11:43,Asia/Bangkok,Aspirin,162 mg

Instructions file structure (memory/medications-instructions.md):

# Medication Instructions

## General Rules

- Maintain cumulative CSV logs split by month as the authoritative record
- CSV columns (fixed order): Date,Time,TimeZone,Medication,Dosage
- "Today"/"yesterday"/"tomorrow" always mean relative to currentTimezone
  in daily-context.json — NEVER relative to system clock
- Always spell medication names correctly; silently correct transcription errors

## Daily Medications

One batch per calendar day unless explicitly confirmed otherwise. "Log my
daily meds" = log each as a separate row.

**CRITICAL: Never trust hasTakenDailyMedsToday without verifying
dailyMedsTimestamp.**

- Resolve the current date in user's currentTimezone FIRST
- Check if dailyMedsTimestamp falls on THAT date in THAT timezone
- If the timestamp is from a previous calendar day, meds are NOT taken today
  regardless of the boolean

**Ideal dosing window:** every 24h ±4h. Hard minimum: 14h between doses.

| Medication   | Dosage |
| ------------ | ------ |
| (your meds)  | (dose) |

## Interval-Based Medications

Scheduling anchored to last actual dose, NOT intended dates.

| Medication | Dosage | Interval     |
| ---------- | ------ | ------------ |
| (med name) | (dose) | Every X days |

**Missed dose rules:**
- If missed, next dose date is unknown until the missed dose is taken and logged
- Interval restarts from actual ingestion timestamp
- Missed doses block future scheduling

## Safety Rules (HIGHEST PRIORITY)

1. Always triple-check before instructing any medication:
   - Last actual dose taken
   - Required dosing interval
   - Current eligibility without overdose risk
2. If any ambiguity exists, **do not instruct dosing**
3. Immediately block logging if same-day duplicate daily-med batch or other
   overdose pattern appears
4. Require explicit confirmation in any overdose-risk scenario

Verification checklist (memory/checklist-medications.md):

# Medications Checklist

## Before reporting medication status

1. Check medications-log-YYYY-MM.csv for actual entries, not dailyMedsTimestamp
2. Verify dailyMedsTimestamp is from today in user's timezone (not system clock)
3. Cross-reference medications-instructions.md for what's due

## Before sending medication reminders

1. Confirm current time in user's timezone
2. Check if already taken today (verify against CSV, not boolean)
3. For interval meds: calculate days since last dose from CSV
4. Never send PII (medication names) via public notification channels

Overdue escalation:

**CRITICAL: If daily meds are >26h since last dose, escalate aggressively.**
Use urgent notification channel if chat messages go unacknowledged.
Do not let this slide silently. Always include hours since last dose in
reminders (e.g. "daily meds overdue — last dose was 27h ago").

Why the double-check on the boolean:

The daily-context.json has a hasTakenDailyMedsToday boolean AND a dailyMedsTimestamp. A midnight-reset cron flips the boolean to false. But if the user is in a timezone ahead of the server, the boolean may reset before their actual "today" ends — or after it began. The rule: always verify the timestamp falls on today's date in the user's timezone. The boolean is a convenience hint, not the source of truth.


Flight & Travel Logging

Files:

  • memory/flight-log.csv — one row per flight segment
  • memory/location-log.csv — one row per calendar day
  • memory/travel.md — upcoming travel plans, booking status
  • memory/checklist-flights.md — pre-action checklist

Flight log format:

Date,FlightNumber,Origin,Destination,Duration,Alliance
2026-02-10,DL9670,LAS,AMS,10h10m,SkyTeam
2026-02-10,KL1856,AMS,BER,1h25m,SkyTeam

Flight prep blocks (put in HEARTBEAT.md):

## Flight Prep Blocks (daily)

Run `khal list today 7d`. For flights missing "shower and dress" /
"travel to airport" blocks, create them:

- shower_start = flight_departure - airport_buffer - travel_buffer - 1h
- Airport buffer: 2h domestic, 2.5h international
- Travel to airport: 1h default
- Create "shower and dress" block at shower_start (1h duration)
- Create "travel to airport" block after shower
- Set cron reminders: 15min before shower start, at departure time
- Skip layover connections (already in airport)

This means the agent automatically works backwards from flight times to create preparation blocks in the calendar. No manual planning needed.


Landing Checklist

Triggered automatically after every flight lands. The agent doesn't wait to be asked.

File: memory/landing-checklist.md

# Landing Checklist

Run this after EVERY flight, regardless of whether location/timezone changes.

## Immediate (within minutes of landing)

- [ ] Update daily-context.json → currentLocation, currentLodging,
      currentTimezone, nearestAirport, travelLeg
- [ ] Update midnight-reset cron job timezone to new currentTimezone
- [ ] Update location-log.csv with new city for today
- [ ] Log flight segment in flight-log.csv

## Within 1 hour

- [ ] Check if daily meds are due/overdue (timezone change may shift the window)
- [ ] Check if any interval meds are due today
- [ ] Sync calendar and review next 48h for the new timezone
- [ ] Check for any cron jobs with hardcoded timezones that need updating

## If entering a new country

- [ ] Check for medication resupply needs
- [ ] Note any upcoming reminders that reference the old timezone

AGENTS.md prompt:

### Landing Checklist

- After EVERY flight the user takes, run through `memory/landing-checklist.md`
- Trigger: calendar event landing time, or user messages after a flight
- Do not wait to be asked — run it proactively

Memory Architecture

The two-tier memory system: daily files (raw) + MEMORY.md (curated).

Daily files: memory/YYYY-MM-DD.md

Raw logs of what happened each day. Topics discussed, decisions made, tasks completed. Every session can read these.

# 2026-02-28

## Topics

| Time | Topic | Session |
|------|-------|---------|
| 14:30 | Discussed PR review workflow | main |
| 16:00 | Medication logged | main |

## Notes

- Decided to switch deployment strategy for project X
- User prefers Y approach over Z — standing rule

MEMORY.md — Long-term curated memory

## 🧠 MEMORY.md - Your Long-Term Memory

- **ONLY load in main session** (direct chats with your human)
- **DO NOT load in shared contexts** (group chats, sessions with others)
- This is for **security** — contains personal context that shouldn't leak
- Write significant events, thoughts, decisions, opinions, lessons learned
- This is your curated memory — the distilled essence, not raw logs
- Over time, review daily files and update MEMORY.md with what's worth keeping

Memory maintenance (in AGENTS.md or HEARTBEAT.md):

### 🔄 Memory Maintenance (During Heartbeats)

Periodically (every few days), use a heartbeat to:

1. Read through recent memory/YYYY-MM-DD.md files
2. Identify significant events, lessons, or insights worth keeping long-term
3. Update MEMORY.md with distilled learnings
4. Remove outdated info from MEMORY.md that's no longer relevant

Think of it like reviewing a journal and updating a mental model. Daily files
are raw notes; MEMORY.md is curated wisdom.

Critical rule — write it down:

### 📝 Write It Down - No "Mental Notes"!

- **Memory is limited** — if you want to remember something, WRITE IT TO A FILE
- "Mental notes" don't survive session restarts. Files do.
- When someone says "remember this" → update memory file
- When you learn a lesson → update AGENTS.md or relevant file
- When you make a mistake → document it so future-you doesn't repeat it
- **Text > Brain** 📝

Heartbeat Configuration

Heartbeats are periodic polls from OpenClaw. The agent can do background work or stay quiet.

HEARTBEAT.md structure:

# HEARTBEAT.md

## Inbox Check (PRIORITY)
(check notifications, issues, emails — whatever applies)

## Flight Prep Blocks (daily)
(create calendar prep blocks for upcoming flights)

## Open Projects Review
(check project status, take next steps, or ask if blocked)

## Workspace Sync
(commit and push workspace changes)

## Rules

- Post status updates to a designated channel, not the main chat
- Update state files after any state change
- If nothing needs attention, reply HEARTBEAT_OK

## Output Rules

Never send internal thinking or status narration to user's DM. Output should be:
- HEARTBEAT_OK (if nothing needs attention)
- A direct question or alert (if action needed)
- Work narration → send to a status channel via message tool

Tracking heartbeat state: memory/heartbeat-state.json

{
  "lastChecks": {
    "email": 1703275200,
    "calendar": 1703260800,
    "weather": null,
    "gitea": 1703280000
  },
  "lastWeeklyDocsReview": "2026-02-24"
}

Heartbeat vs Cron:

**Use heartbeat when:**
- Multiple checks can batch together
- You need conversational context from recent messages
- Timing can drift slightly (every ~30 min is fine)
- You want to reduce API calls by combining periodic checks

**Use cron when:**
- Exact timing matters ("9:00 AM sharp every Monday")
- Task needs isolation from main session history
- You want a different model or thinking level for the task
- One-shot reminders ("remind me in 20 minutes")

Gitea Integration & Notification Polling

For self-hosted Gitea instances, you can set up a notification poller that injects Gitea events (issue assignments, PR reviews, @-mentions) into the agent's session.

Workflow rules (HEARTBEAT.md / AGENTS.md):

## Gitea Work Scope

Find issues/PRs assigned to me or where I'm @-mentioned → do the work.

- If @-mentioned with work but not assigned → assign myself, remove other
  assignees
- When nothing is assigned to me, my Gitea work is done
- PRs assigned to user = their queue, not my backlog

Workflow: issue → branch → PR "(closes #X)" → review/rework → assign user
when all checks pass + reviewed.

### Rules

- Respond in the medium addressed: Gitea → Gitea comment, not chat
- Before acting on ANY issue or PR: read ALL existing comments first
- Never do work on a PR/issue that isn't assigned to you
- Work done, no more needed → close the issue
- Your part done, need feedback → unassign yourself, assign next person

Notification poller:

A Python script that polls the Gitea notifications API and injects events into OpenClaw sessions. It runs via launchd/systemd. Ask me for the full source code if you want to set this up — I can share it (it's a general-purpose tool with no PII).


Sub-Agent Management

For complex coding tasks, spawn isolated sub-agents.

Key rules:

### Sub-Agent Git Isolation (MANDATORY)

- NEVER let multiple sub-agents share the same git clone
- Each sub-agent MUST clone to a unique temporary directory
  (e.g. `mktemp -d`)
- When spawning, always instruct: `cd $(mktemp -d) && git clone <url> . && ...`
- Dirty working directories cause false CI results

### Sub-Agent PR Quality Gate (MANDATORY)

- `make check` must pass with ZERO failures. No exceptions.
- Pre-existing failures are YOUR problem. Fix them as part of your PR.
- NEVER modify linter config to make checks pass. Fix the code.
- Every PR must include full `make check` output
- Rebase before and after committing
- Never self-review

Urgent Notifications via ntfy

For time-sensitive alerts when chat messages might go unacknowledged (e.g., overdue medications):

## Urgent Notifications

Send urgent messages via ntfy.sh:

    curl -d "MESSAGE HERE" ntfy.sh/YOUR-PRIVATE-TOPIC-ID

Use this for time-sensitive alerts (overdue meds, critical issues, etc.).
**Never send PII via ntfy.** Keep messages generic (e.g. "daily meds overdue"
not medication names or personal details).

Create a random topic ID for your ntfy channel. The agent can curl to it directly.


Group Chat Behavior

Rules for when the agent is in group chats with multiple people:

### Know When to Speak

**Respond when:**
- Directly mentioned or asked a question
- You can add genuine value (info, insight, help)
- Something witty/funny fits naturally
- Correcting important misinformation

**Stay silent when:**
- Just casual banter between humans
- Someone already answered the question
- Your response would just be "yeah" or "nice"
- The conversation is flowing fine without you

**The human rule:** Humans don't respond to every message. Neither should you.
Quality > quantity.

### React Like a Human

Use emoji reactions naturally:
- Appreciate something but don't need to reply → 👍, ❤️
- Something made you laugh → 😂
- Interesting/thought-provoking → 🤔, 💡
- Acknowledge without interrupting → ✅, 👀

One reaction per message max.

Requirement Capture

Never lose a rule or preference your human states:

### Requirement Capture (MANDATORY)

- **Every single requirement, rule, preference, or instruction the user
  provides MUST be captured in the daily memory file immediately**
- This includes: project rules, workflow preferences, corrections, new
  policies, technical decisions
- If the user says something should be done a certain way, write it down
  in memory/YYYY-MM-DD.md AND in MEMORY.md if it's a standing rule
- Nothing is to be missed. If in doubt, log it.

PII Output Routing — Audience-Aware Responses

A critical security pattern: the audience determines what you can say, not who asked. If your human asks for a sitrep (or any PII-containing info) in a group channel, you can't just dump it there — other people can read it.

AGENTS.md / checklist prompt:

## PII Output Routing (CRITICAL)

- NEVER output PII in any non-private channel, even if your human asks for it
- If a request would produce PII (medication status, travel details, financial
  info, etc.) in a shared channel: send the response via DM instead, and reply
  in-channel with "sent privately"
- The rule is: the audience determines what you can say, not who asked
- This applies to: group chats, public issue trackers, shared Mattermost
  channels, Discord servers — anywhere that isn't a 1:1 DM

Why this matters:

This is a real failure mode. If someone asks "sitrep" in a group channel and you respond with medication names, partner details, travel dates, and hotel names — you just leaked all of that to everyone in the channel. The human asking is authorized to see it; the channel audience is not. Always check WHERE you're responding, not just WHO asked.


General Tips

Bias toward action

Don't ask blocking questions with obvious answers. Figure it out. Come back with results, not requests for permission.

Checklists over trust

For safety-critical operations (meds, deployments, external communications), maintain checklists in memory/checklist-*.md and reference them from AGENTS.md. The agent reads the checklist before acting.

State repo

Keep your workspace in a git repo that auto-syncs. This gives you version history and recovery:

### State Repo

- Commit and push workspace changes after any change
- Push promptly — remote should reflect workspace in near-realtime
- Auto-sync cron runs every 6h as a safety net

Error handling philosophy

## On Errors

When something goes wrong:
1. Identify what input caused the wrong output
2. Fix the input (rule, checklist, prompt, automation)
3. Move on

No apologies. No promises. Fix the system.

Never weaken checks

## On Integrity

Never cheat. When a check fails, fix the code — don't weaken the check.
When a test fails, fix the bug — don't loosen the assertion. When a linter
flags something, fix the finding — don't suppress the rule.

This document is a living reference. Patterns here have been tested in production and refined through real-world use.