Some checks failed
check / check (push) Failing after 9s
Add failure stories section to OPENCLAW_TRICKS.md covering 10 real production failures and fixes from the first three weeks of operation.
1292 lines
43 KiB
Markdown
1292 lines
43 KiB
Markdown
# 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.
|
||
|
||
---
|
||
|
||
## How This System Evolved
|
||
|
||
This section explains what we built, why, and how the pieces fit together. The
|
||
rest of the document has the specific prompts and schemas — this part gives you
|
||
the big picture so you understand the design decisions.
|
||
|
||
### The Starting Point
|
||
|
||
OpenClaw gives you a persistent workspace directory and the ability to run tools
|
||
(shell, web, browser, messaging). Out of the box, the agent wakes up fresh every
|
||
session with no memory of what happened before. The core challenge is: **how do
|
||
you turn a stateless LLM into a stateful personal assistant that knows who you
|
||
are, where you are, what you need, and what it was working on?**
|
||
|
||
The answer is files. The workspace IS the agent's brain. Every piece of state,
|
||
every rule, every memory lives in files that the agent reads on startup and
|
||
updates as things change.
|
||
|
||
### The Workspace Files — Separation of Concerns
|
||
|
||
We started with one big AGENTS.md that had everything: rules, procedures,
|
||
medication instructions, git workflow, travel preferences. It worked at first
|
||
but quickly became unwieldy. The context window was getting eaten by
|
||
instructions the agent didn't need for most tasks.
|
||
|
||
The solution was **factoring out rulesets into focused files:**
|
||
|
||
- **AGENTS.md** — the master file. Responsibilities, session startup procedure,
|
||
high-level rules. Think of it as the table of contents that points to
|
||
everything else.
|
||
- **SOUL.md** — personality, tone, values. Separated because it's philosophical,
|
||
not procedural. Also: it's fun to let the agent evolve this one over time.
|
||
- **USER.md** — info about the human. Timezone, communication preferences,
|
||
basics the agent needs every session.
|
||
- **MEMORY.md** — curated long-term memory. Only loaded in private sessions
|
||
(security — prevents leaking personal context in group chats).
|
||
- **HEARTBEAT.md** — what to check on periodic heartbeat polls. Kept small
|
||
intentionally to minimize token burn on frequent checks.
|
||
- **TOOLS.md** — environment-specific notes (hostnames, device names, channel
|
||
IDs). Separated from skills because this is YOUR setup, skills are shared.
|
||
|
||
Then the procedural rulesets got their own files too:
|
||
|
||
- **`memory/medications-instructions.md`** — full medication protocol. Dosages,
|
||
schedules, safety rules, overdose prevention logic. Only loaded when
|
||
medication tasks come up.
|
||
- **`memory/checklist-pr.md`** — PR quality gate. What to verify before pushing,
|
||
after sub-agent pushes, before assigning to the human for review.
|
||
- **`memory/checklist-flights.md`** — flight time verification, prep block
|
||
creation, landing checklist triggers.
|
||
- **`memory/checklist-medications.md`** — pre-action verification before
|
||
reporting medication status or sending reminders.
|
||
- **`memory/checklist-messaging.md`** — rules for every outgoing message: URL
|
||
verification, timezone conversion, status claim verification.
|
||
- **`memory/landing-checklist.md`** — post-flight procedures (update location,
|
||
timezone, check meds, sync calendar).
|
||
|
||
The key insight: **MEMORY.md has a "checklists" section at the very top** that
|
||
says "before doing X, read file Y." The agent reads MEMORY.md at session start,
|
||
sees the checklist index, and knows which file to consult before any action.
|
||
This way the detailed instructions aren't always in context — they're loaded
|
||
on-demand.
|
||
|
||
```markdown
|
||
## ⛔ CHECKLISTS (read the relevant file before acting)
|
||
|
||
- **Any PR/code work** → `memory/checklist-pr.md`
|
||
- **Any message to the user** → `memory/checklist-messaging.md`
|
||
- **Medications** → `memory/checklist-medications.md`
|
||
- **Flights/travel** → `memory/checklist-flights.md`
|
||
```
|
||
|
||
### The Daily Context State File
|
||
|
||
This was probably the single most impactful addition. It's a JSON file
|
||
(`memory/daily-context.json`) that every session reads on every message. It
|
||
tracks the current state of the human: where they are, what timezone they're in,
|
||
whether they're sleeping, when they last took meds, when they last sent a
|
||
message.
|
||
|
||
Why JSON instead of markdown? Because it's machine-readable. The agent can
|
||
update individual fields programmatically, and the structure is unambiguous.
|
||
Markdown is great for instructions; JSON is great for state.
|
||
|
||
The daily context file means:
|
||
|
||
- The agent always knows the human's timezone (critical for a frequent traveler)
|
||
- Medication reminders fire based on actual timestamps, not guesses
|
||
- Sleep predictions inform when to send alerts vs stay quiet
|
||
- Location tracking happens automatically
|
||
|
||
### The Two-Tier Memory System
|
||
|
||
Daily files (`memory/YYYY-MM-DD.md`) are raw logs — what happened each day.
|
||
Topic tables, decisions, lessons, notes. Think of these as a daily journal.
|
||
|
||
MEMORY.md is curated long-term memory — the distilled essence. Standing rules,
|
||
key facts, lessons learned. Think of this as what a human would "just know"
|
||
about their life.
|
||
|
||
During heartbeats, the agent periodically reviews recent daily files and
|
||
promotes significant items to MEMORY.md, and removes stale info. It's explicitly
|
||
modeled on how human memory works: raw experience gets processed into lasting
|
||
knowledge, and irrelevant details fade.
|
||
|
||
The security model: MEMORY.md is only loaded in private (1:1 DM) sessions. In
|
||
group chats, the agent works from daily files and daily-context.json only. This
|
||
prevents personal context from leaking into shared channels.
|
||
|
||
### Medication Tracking
|
||
|
||
This is a safety-critical system. The design is deliberately paranoid:
|
||
|
||
- **CSV as source of truth.** Not the daily-context boolean, not the agent's
|
||
memory — the CSV log file is authoritative.
|
||
- **Double-verification before any action.** The daily context has a
|
||
`hasTakenDailyMedsToday` boolean AND a `dailyMedsTimestamp`. A midnight cron
|
||
resets the boolean. But if the human is in a timezone ahead of the server, the
|
||
reset happens at the wrong time. So the rule is: always verify the timestamp
|
||
falls on today's date in the human's timezone. The boolean is a convenience
|
||
hint, never the source of truth.
|
||
- **Interval medications anchored to actual doses.** Some meds are "every 5
|
||
days" or "every 14 days." The next dose date is calculated from the last
|
||
actual dose timestamp, not from the intended schedule. If a dose is missed,
|
||
the next date is unknown until the missed dose is taken and logged.
|
||
- **Overdose prevention.** The agent blocks logging if it detects a same-day
|
||
duplicate batch. This is the highest-priority safety rule — a duplicate daily
|
||
batch of certain medications could cause cardiac arrest.
|
||
- **Escalating alerts.** If daily meds are >26h since last dose, the agent
|
||
escalates aggressively — ntfy push notification if chat messages go
|
||
unacknowledged.
|
||
|
||
The medication instructions file is loaded on-demand (not every session),
|
||
keeping context costs low for non-medication conversations.
|
||
|
||
### Sleep Tracking
|
||
|
||
The agent infers sleep from activity gaps rather than requiring explicit "I'm
|
||
going to sleep" statements. On every message, it checks: was there a gap since
|
||
the last message that overlaps with the predicted sleep window? If so, log sleep
|
||
start = last activity before gap, wake = first activity after.
|
||
|
||
Activity isn't just chat messages — it includes Gitea commits, comments,
|
||
scheduled flight departures, and any other observable actions.
|
||
|
||
Sleep predictions drift over time (the human in this setup tends to sleep ~30min
|
||
later each day), so the agent tracks the trend and extrapolates. Caffeine intake
|
||
adjusts predictions forward. The predictions feed into:
|
||
|
||
- When to send alerts vs stay quiet
|
||
- Sitrep "sleep conflict" warnings (appointment during predicted sleep)
|
||
- General awareness of the human's schedule
|
||
|
||
### Location & Timezone Tracking
|
||
|
||
The agent always knows where the human is. This matters because:
|
||
|
||
- Times must always be displayed in the human's local timezone, not the server's
|
||
timezone
|
||
- "Today" and "tomorrow" mean different things in different timezones
|
||
- Medication timing needs to account for timezone changes
|
||
- Flight prep needs local airport info
|
||
|
||
The landing checklist (triggered automatically after every flight) updates
|
||
location, timezone, nearest airport, and lodging in the daily context file. It
|
||
also checks if any cron jobs have hardcoded timezones that need updating.
|
||
|
||
### The Gitea Notification Poller
|
||
|
||
OpenClaw has heartbeats, but those are periodic (every ~30min). For Gitea issues
|
||
and PRs, we wanted near-realtime response. The solution: a tiny Python script
|
||
that polls the Gitea notifications API every 2 seconds and wakes the agent via
|
||
OpenClaw's `/hooks/wake` endpoint when new notifications arrive.
|
||
|
||
Key design decisions:
|
||
|
||
- **The poller never marks notifications as read.** That's the agent's job after
|
||
it processes them. This prevents the poller and agent from racing.
|
||
- **It tracks notification IDs, not counts.** This way it only fires on
|
||
genuinely new notifications, not re-reads of existing ones.
|
||
- **The wake message tells the agent to route output to Gitea/Mattermost, not to
|
||
DM.** This prevents chatty notification processing from disturbing the human.
|
||
- **Zero dependencies.** Just Python stdlib (`urllib`, `json`, `time`). Runs
|
||
anywhere.
|
||
|
||
Here's the full source:
|
||
|
||
```python
|
||
#!/usr/bin/env python3
|
||
"""
|
||
Gitea notification poller.
|
||
Polls for unread notifications and wakes OpenClaw when the count
|
||
changes. The AGENT marks notifications as read after processing —
|
||
the poller never marks anything as read.
|
||
|
||
Required env vars:
|
||
GITEA_URL - Gitea instance URL
|
||
GITEA_TOKEN - Gitea API token
|
||
HOOK_TOKEN - OpenClaw hooks auth token
|
||
|
||
Optional env vars:
|
||
GATEWAY_URL - OpenClaw gateway URL (default: http://127.0.0.1:18789)
|
||
POLL_DELAY - Delay between polls in seconds (default: 2)
|
||
"""
|
||
|
||
import json
|
||
import os
|
||
import sys
|
||
import time
|
||
import urllib.request
|
||
import urllib.error
|
||
|
||
GITEA_URL = os.environ.get("GITEA_URL", "").rstrip("/")
|
||
GITEA_TOKEN = os.environ.get("GITEA_TOKEN", "")
|
||
GATEWAY_URL = os.environ.get("GATEWAY_URL", "http://127.0.0.1:18789").rstrip(
|
||
"/"
|
||
)
|
||
HOOK_TOKEN = os.environ.get("HOOK_TOKEN", "")
|
||
POLL_DELAY = int(os.environ.get("POLL_DELAY", "2"))
|
||
|
||
|
||
def check_config():
|
||
missing = []
|
||
if not GITEA_URL:
|
||
missing.append("GITEA_URL")
|
||
if not GITEA_TOKEN:
|
||
missing.append("GITEA_TOKEN")
|
||
if not HOOK_TOKEN:
|
||
missing.append("HOOK_TOKEN")
|
||
if missing:
|
||
print(
|
||
f"ERROR: Missing required env vars: {', '.join(missing)}",
|
||
file=sys.stderr,
|
||
)
|
||
sys.exit(1)
|
||
|
||
|
||
def gitea_unread_ids():
|
||
"""Return set of unread notification IDs."""
|
||
req = urllib.request.Request(
|
||
f"{GITEA_URL}/api/v1/notifications?status-types=unread",
|
||
headers={"Authorization": f"token {GITEA_TOKEN}"},
|
||
)
|
||
try:
|
||
with urllib.request.urlopen(req, timeout=10) as resp:
|
||
notifs = json.loads(resp.read())
|
||
return {n["id"] for n in notifs}
|
||
except Exception as e:
|
||
print(
|
||
f"WARN: Gitea API failed: {e}", file=sys.stderr, flush=True
|
||
)
|
||
return set()
|
||
|
||
|
||
def wake_openclaw(count):
|
||
text = (
|
||
f"[Gitea Notification] {count} new notification(s). "
|
||
"Check your Gitea notification inbox via API, process them, "
|
||
"and mark as read when done. "
|
||
"Route all output to Gitea comments or Mattermost #git/#claw. "
|
||
"Do NOT reply to this session — respond with NO_REPLY."
|
||
)
|
||
payload = json.dumps({"text": text, "mode": "now"}).encode()
|
||
req = urllib.request.Request(
|
||
f"{GATEWAY_URL}/hooks/wake",
|
||
data=payload,
|
||
headers={
|
||
"Authorization": f"Bearer {HOOK_TOKEN}",
|
||
"Content-Type": "application/json",
|
||
},
|
||
method="POST",
|
||
)
|
||
try:
|
||
with urllib.request.urlopen(req, timeout=5) as resp:
|
||
status = resp.status
|
||
print(f" Wake responded: {status}", flush=True)
|
||
return True
|
||
except Exception as e:
|
||
print(
|
||
f"WARN: Failed to wake OpenClaw: {e}",
|
||
file=sys.stderr,
|
||
flush=True,
|
||
)
|
||
return False
|
||
|
||
|
||
def main():
|
||
check_config()
|
||
print(
|
||
f"Gitea notification poller started (delay={POLL_DELAY}s)",
|
||
flush=True,
|
||
)
|
||
|
||
last_seen_ids = gitea_unread_ids()
|
||
print(
|
||
f"Initial unread: {len(last_seen_ids)} notification(s)", flush=True
|
||
)
|
||
|
||
while True:
|
||
time.sleep(POLL_DELAY)
|
||
|
||
current_ids = gitea_unread_ids()
|
||
new_ids = current_ids - last_seen_ids
|
||
|
||
if not new_ids:
|
||
last_seen_ids = current_ids
|
||
continue
|
||
|
||
ts = time.strftime("%H:%M:%S")
|
||
print(
|
||
f"[{ts}] {len(new_ids)} new notification(s) "
|
||
f"({len(current_ids)} total unread), waking agent",
|
||
flush=True,
|
||
)
|
||
|
||
wake_openclaw(len(new_ids))
|
||
last_seen_ids = current_ids
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|
||
```
|
||
|
||
Run it as a background service (launchd on macOS, systemd on Linux) with the env
|
||
vars set. It's intentionally simple — no frameworks, no async, no dependencies.
|
||
|
||
### The Daily Diary
|
||
|
||
Every day gets a `memory/YYYY-MM-DD.md` file. The agent appends a topic summary
|
||
to a table after every meaningful conversation:
|
||
|
||
```markdown
|
||
## Topics
|
||
|
||
| Time (TZ) | Topic |
|
||
| --------- | ------------------------------------------------ |
|
||
| 14:30 | Discussed PR review workflow |
|
||
| 16:00 | Medication logged |
|
||
| 18:45 | Flight prep blocks created for tomorrow's flight |
|
||
```
|
||
|
||
This serves multiple purposes:
|
||
|
||
- Any session can see what's been discussed today without loading full
|
||
conversation history
|
||
- The agent can use `sessions_history` to get details on a specific topic if
|
||
needed
|
||
- During memory maintenance, the agent reviews these to decide what's worth
|
||
promoting to MEMORY.md
|
||
- It's a simple audit trail of what happened
|
||
|
||
### The Requirement Capture Rule
|
||
|
||
One of the most important rules: **every single requirement, preference, or
|
||
instruction the human provides MUST be captured in a file immediately.** Not
|
||
"mentally noted" — written to disk. Because the agent wakes up fresh every
|
||
session, a "mental note" is worthless. If it's not in a file, it didn't happen.
|
||
|
||
This applies to everything: project rules ("no mocks in tests"), workflow
|
||
preferences ("fewer PRs, don't over-split"), corrections, new policies.
|
||
Immediate write to the daily file, and to MEMORY.md if it's a standing rule.
|
||
|
||
### PII-Aware Output Routing
|
||
|
||
A lesson learned the hard way: **the audience determines what you can say, not
|
||
who asked.** If the human asks for a medication status report in a group
|
||
channel, the agent can't just dump it there — other people can read it. The
|
||
rule: if the output would contain PII and the channel isn't private, redirect to
|
||
DM and reply in-channel with "sent privately."
|
||
|
||
This is enforced at multiple levels:
|
||
|
||
- AGENTS.md has a warning banner at the top
|
||
- The checklist system catches it before action
|
||
- Channel-specific rule files (like our `memory/JAMES_CHAT.md`) define what's
|
||
shareable per-channel
|
||
|
||
### Sub-Agent Isolation
|
||
|
||
When spawning coding sub-agents for PR work, each one MUST clone to a fresh
|
||
temporary directory. Never share git clones between agents — dirty working
|
||
directories cause false CI results, merge conflicts, and wrong file state. The
|
||
rule: `cd $(mktemp -d) && git clone <url> . && ...`
|
||
|
||
### The Heartbeat System
|
||
|
||
OpenClaw polls the agent periodically with a configurable prompt. The agent
|
||
reads HEARTBEAT.md and decides what to do. We keep HEARTBEAT.md small (focused
|
||
checklist) to minimize token burn on these frequent checks.
|
||
|
||
The heartbeat handles:
|
||
|
||
- Gitea inbox triage (check for new assignments)
|
||
- Flight prep block creation (look ahead 7 days)
|
||
- Open project review (can I take a step on anything?)
|
||
- Workspace sync (commit and push changes)
|
||
- Periodic memory maintenance
|
||
|
||
State tracking in `memory/heartbeat-state.json` prevents redundant checks (e.g.,
|
||
don't re-check email if you checked 10 minutes ago).
|
||
|
||
The key output rule: heartbeats should either be `HEARTBEAT_OK` (nothing to do)
|
||
or a direct alert. Work narration goes to a designated status channel, never to
|
||
the human's DM.
|
||
|
||
### Putting It All Together
|
||
|
||
The system works as a loop:
|
||
|
||
1. **Session starts** → read SOUL, USER, daily-context, today's daily file
|
||
2. **Message arrives** → check daily-context for state changes (sleep gap?
|
||
location change? meds overdue?), respond to the message, update state
|
||
3. **Heartbeat fires** → check inbox, projects, flights, sync workspace
|
||
4. **External event** (Gitea poller wake) → process notification, respond via
|
||
appropriate channel
|
||
5. **Session ends** → state persists in files for next session
|
||
|
||
The files are the continuity. The agent is stateless; the workspace is not.
|
||
|
||
---
|
||
|
||
## Table of Contents
|
||
|
||
1. [Workspace Bootstrapping](#workspace-bootstrapping)
|
||
2. [Daily Context — The State File](#daily-context--the-state-file)
|
||
3. [Sitrep (Situation Report)](#sitrep-situation-report)
|
||
4. [Sleep Tracking](#sleep-tracking)
|
||
5. [Location & Timezone Tracking](#location--timezone-tracking)
|
||
6. [Medication Tracking](#medication-tracking)
|
||
7. [Flight & Travel Logging](#flight--travel-logging)
|
||
8. [Landing Checklist](#landing-checklist)
|
||
9. [Memory Architecture](#memory-architecture)
|
||
10. [Heartbeat Configuration](#heartbeat-configuration)
|
||
11. [Gitea Integration & Notification Polling](#gitea-integration--notification-polling)
|
||
12. [Sub-Agent Management](#sub-agent-management)
|
||
13. [Urgent Notifications via ntfy](#urgent-notifications-via-ntfy)
|
||
14. [Group Chat Behavior](#group-chat-behavior)
|
||
15. [Cron vs Heartbeat — When to Use Each](#cron-vs-heartbeat)
|
||
16. [Requirement Capture](#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):
|
||
|
||
```markdown
|
||
## 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`
|
||
|
||
```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:
|
||
|
||
```markdown
|
||
## 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:
|
||
|
||
```markdown
|
||
### 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:
|
||
|
||
```markdown
|
||
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`
|
||
|
||
```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:
|
||
|
||
```markdown
|
||
### 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 4–8 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:
|
||
|
||
```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",
|
||
"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:
|
||
|
||
```json
|
||
{
|
||
"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`
|
||
|
||
```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):
|
||
|
||
```markdown
|
||
## 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`
|
||
|
||
```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`):
|
||
|
||
```markdown
|
||
# 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`):
|
||
|
||
```markdown
|
||
# 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:
|
||
|
||
```markdown
|
||
**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:
|
||
|
||
```csv
|
||
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):
|
||
|
||
```markdown
|
||
## 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`
|
||
|
||
```markdown
|
||
# 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:
|
||
|
||
```markdown
|
||
### 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.
|
||
|
||
```markdown
|
||
# 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
|
||
|
||
```markdown
|
||
## 🧠 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):
|
||
|
||
```markdown
|
||
### 🔄 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:
|
||
|
||
```markdown
|
||
### 📝 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:
|
||
|
||
```markdown
|
||
# 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`
|
||
|
||
```json
|
||
{
|
||
"lastChecks": {
|
||
"email": 1703275200,
|
||
"calendar": 1703260800,
|
||
"weather": null,
|
||
"gitea": 1703280000
|
||
},
|
||
"lastWeeklyDocsReview": "2026-02-24"
|
||
}
|
||
```
|
||
|
||
### Heartbeat vs Cron:
|
||
|
||
```markdown
|
||
**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):
|
||
|
||
```markdown
|
||
## 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:
|
||
|
||
```markdown
|
||
### 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):
|
||
|
||
```markdown
|
||
## 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:
|
||
|
||
```markdown
|
||
### 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:
|
||
|
||
```markdown
|
||
### 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:
|
||
|
||
```markdown
|
||
## 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:
|
||
|
||
```markdown
|
||
### 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
|
||
|
||
```markdown
|
||
## 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
|
||
|
||
```markdown
|
||
## 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._
|