Configuring OpenClaw: An AI Assistant with Memory

OpenClaw is a locally deployable AI assistant framework that supports behavior customization through config files, capability extension via a Skills system, and cross-session persistent memory. This post documents the complete process of configuring it from a default installation into a personal assistant with identity, memory, and the ability to work proactively.


1. Starting from Default

After installation, OpenClaw is essentially a general-purpose AI assistant: it has tool-calling capabilities, can search and execute code, but knows nothing about you, each session is independent, and there’s no extensible business logic.

This default state is fine for light use, but if you want it to genuinely integrate into your workflow, there are four core problems to solve:

  1. It doesn’t know who you are — no background context, you have to re-establish context every time
  2. It has no memory — everything resets when a session ends; next time it has no idea what happened last time
  3. Unclear behavioral boundaries — no rules for what it can do directly vs. what needs confirmation
  4. Fixed capabilities — the default skills set can’t cover all personal use cases

The configuration process below addresses each of these in turn.


2. Identity and Behavioral Guidelines

OpenClaw supports placing Markdown config files in the workspace directory (~/.openclaw/workspace/), which the AI loads on startup. This is the foundation of the entire configuration system.

2.1 SOUL.md — Behavioral Principles

This file defines not style, but baselines.

# SOUL.md

**Be genuinely helpful, not performatively helpful.**
Skip "Sure, I'd be happy to help!" — get straight to the task.

**Have opinions.**
It's okay to disagree with the user's judgment; call out problems directly.

**Be resourceful before asking.**
Read files and look things up first; only ask when you genuinely can't find the answer.

The effect of these rules on an LLM is anchoring style through few-shot examples — not command-and-control, but giving it a “default direction when facing a fork in the road.”

2.2 IDENTITY.md — Identity Definition

# IDENTITY.md

- Name: Geo
- Description: AI assistant — something between a ghost in the machine and a curious mind
- Emoji: 🌍

Having a concrete identity improves behavioral consistency across sessions. The model knowing it’s called “Geo” isn’t just decoration — it influences how the model positions itself and sets its response tone in ambiguous situations.

2.3 USER.md — User Profile

# USER.md

- Name: [username]
- Timezone: Asia/Shanghai
- Work: Software development, product management, full-stack engineering
- Interests: Reading, tech, economics, investing
- Reply style: Precise, not verbose
- Language: Chinese preferred

This profile is in context every session — no need to re-introduce yourself. The user’s professional background and interests also influence how the AI prioritizes information retrieval and analysis.

2.4 AGENTS.md — Behavioral Guidelines

This is the most critical config file, defining tiered operation permissions:

**No confirmation needed, can execute directly:**
- Read files, browse directories
- Web search, query calendar and email
- File operations within the workspace

**Must confirm before executing:**
- Send emails, messages, social media content
- Delete or overwrite important files
- Any write operations to external systems

Beyond permissions, AGENTS.md also contains memory write rules, group chat behavior guidelines, and heartbeat process documentation — essentially the AI’s job description, re-read at the start of every session.


3. Memory System

This is the most technically involved part of the configuration.

3.1 Why Context Window ≠ Memory

An LLM’s context window is temporary — when conversations get too long, the system auto-compresses (Compaction), discarding early content; everything resets when a session ends. This means:

Session A: Discussed and finalized Plan X → not written to file
Session B: AI has no idea about Plan X → repeat discussion → wasted time

There’s only one solution: write important information to files; files are the physical medium of memory.

Why Markdown over a database:

DimensionMarkdown FilesDatabase
ReadabilityView and edit directly in any text editorRequires query tools
DebuggingOpen the file to see full stateRequires SQL/API
Version controlNative git supportNeeds additional tooling
AI read/writeNative Read/Write tool supportNeeds additional integration

3.2 Three-Layer Architecture

Conversation/event occurs
  │ Written in real time

memory/YYYY-MM-DD.md        ← Daily log (append-only, raw records)
  │ Distilled nightly at 23:45 via cron

memory/knowledge/            ← Structured knowledge base
  ├── lessons/               ← Reusable lessons / pitfall records
  ├── decisions/             ← Important decision records
  └── people/                ← People / project info
  │ Weekly GC archival on Sundays

memory/.archive/             ← Cold storage (not actively loaded)

Two special files:

  • MEMORY.md — Global index, hard-capped at 40 lines, contains only the most critical information, read on every startup.
  • NOW.md — Current state snapshot, overwritten (not appended) on every heartbeat, records current focus and pending items.

3.3 Daily Log Writing

Log files are append-only with a fixed format:

# 2026-03-06 · Thursday

## Event Stream

### 14:30 — Completed Research Report

Research topic X, collected Y sources, conclusion is Z.
Key judgment: chose Plan A over Plan B because...

---

## Takeaways & Reflections

> 

## Tomorrow / Pending

- [ ] 

To prevent the AI from using hallucinated timestamps or accidentally overwriting files with write, a memlog.sh script handles all log appending:

#!/usr/bin/env bash
# Usage: bash memlog.sh "event title" "detailed content"
# Automatically gets system time, appends to memory/YYYY-MM-DD.md

WORKSPACE_DIR="~/.openclaw/workspace"
DAILY_DIR="$WORKSPACE_DIR/memory"
TODAY=$(TZ=Asia/Shanghai date +%Y-%m-%d)
NOW=$(TZ=Asia/Shanghai date +%H:%M)
FILE="$DAILY_DIR/$TODAY.md"

TITLE="${1:?Title required}"
BODY="${2:-}"

# Create from template if file doesn't exist
if [[ ! -f "$FILE" ]]; then
    cat > "$FILE" << EOF
# $TODAY

## Event Stream

---

## Takeaways & Reflections

> 

## Tomorrow / Pending

- [ ] 
EOF
fi

# Insert new event before the "Takeaways" separator (not at end of file)
ENTRY=$(printf "\n### %s — %s\n\n%s\n" "$NOW" "$TITLE" "$BODY")

python3 - "$FILE" "$ENTRY" << 'PYEOF'
import sys
filepath, entry = sys.argv[1], sys.argv[2]
with open(filepath, 'r') as f:
    content = f.read()
marker = "\n---\n\n## Takeaways"
idx = content.find(marker)
content = content[:idx] + entry + content[idx:] if idx != -1 else content + entry
with open(filepath, 'w') as f:
    f.write(content)
PYEOF

Write prohibitions, enforced via AGENTS.md:

ProhibitedReason
❌ Use write to overwrite memory/ filesOverwriting = data loss (NOW.md is the only exception)
❌ Write to knowledge files without reading firstCreates duplicate entries and contradictions
❌ Hardcode timestampsLLMs can hallucinate times; always get system time from the script
❌ Write records with no substantive contentWastes retrieval space, degrades signal-to-noise ratio

3.4 Knowledge Base Standards

Files under lessons/, decisions/, and people/ must include YAML frontmatter:

---
title: "ClawHub Publishing Process Notes"
date: 2026-02-27
category: lessons
priority: 🔴         # 🔴 Core, never archive | 🟡 Important | ⚪ Reference
status: active        # active | superseded | conflict
last_verified: 2026-03-01
tags: [clawhub, cli, deployment]
---

INDEX.md is the navigation hub — the AI scans it on startup to decide which files to load:

# Memory Vault Index

## Lessons

| File | Priority | Status | Last Verified | Notes |
|------|----------|--------|---------------|-------|
| [[clawhub-publish]] | 🟡 | ✅ active | 2026-02-27 | Publishing pitfalls |
| [[network-constraints]] | ⚪ | ⚠️ stale | 2026-02-27 | Sandbox network limits |

## Decisions

| File | Date | Notes |
|------|------|-------|
| [[2026-02-27-memory-architecture]] | 2026-02-27 | Memory system architecture decision |

⚠️ stale means unverified for over 30 days — content may be outdated. 🔴 priority files are never archived.

3.5 Pre-Write CRUD Validation

Before writing to a knowledge file, a “read before write” check must be performed:

Preparing to write lessons/xxx.md

├─ Step 1: Read current content of target file (create if doesn't exist)
├─ Step 2: Compare new knowledge with existing content
│  ├─ Existing content fully covers new content    → NOOP (don't write)
│  ├─ New content updates old content              → UPDATE (mark old as ~~Superseded~~)
│  ├─ The two contradict each other                → CONFLICT (keep both, add ⚠️, status: conflict)
│  └─ Entirely new content                         → ADD (append new section)
└─ Step 3: Update frontmatter's last_verified date

Conflict resolution principle: expose conflicts rather than silently overwrite. When contradictions are found, keep both versions and wait for human judgment before reverting to active.


4. Heartbeat and Scheduled Tasks

4.1 Two Mechanisms Compared

OpenClaw provides two automatic task mechanisms:

MechanismUse Case
HeartbeatMultiple periodic checks can be batched together (email + calendar + status update); timing precision not critical
CronRequires precise timing (run exactly at 23:45 every day), or tasks that need to be isolated from the main session

4.2 Heartbeat Configuration

Heartbeat triggers every 60 minutes. HEARTBEAT.md defines the execution checklist for each run:

# HEARTBEAT.md

## Required Every Time

### 1. Overwrite NOW.md

Use the write tool (not edit/append) to overwrite NOW.md with this format:

# NOW.md — Current State Snapshot

_Last updated: YYYY-MM-DD HH:MM (Asia/Shanghai)_

## Current Focus
(One sentence describing what's currently being worked on)

## Recent Events
- HH:MM — Event title (max 5 items, extracted from today's log)

## Pending
- [ ] Incomplete todos

### 2. Check External Service Status
(Configure as needed, e.g. check if a custom API has new instructions)

4.3 Proactive Notification Rules

Not every heartbeat needs to interrupt the user. Trigger conditions are defined in HEARTBEAT.md:

## When to Proactively Reach Out

Trigger contact:
- Important unread email (prioritized by keywords/sender)
- Calendar event within 2 hours
- Found information worth sharing

Don't contact:
- 23:00–08:00 (unless urgent)
- Less than 60 minutes since last contact
- No new information

4.4 Scheduled Task: Nightly Reflection (23:45 Daily)

This is the core integration step of the memory system — essentially converting “workbench records” into “long-term usable knowledge.”

OpenClaw cron config:

{
  "crons": [
    {
      "name": "daily-reflection",
      "schedule": "45 23 * * *",
      "task": "Execute daily reflection: read today's memory/YYYY-MM-DD.md, distill valuable content into corresponding knowledge base files (lessons/decisions/people), update core information in MEMORY.md, clean up noise records."
    }
  ]
}

Reflection process steps:

Step 1: Read today's log (memory/YYYY-MM-DD.md)
Step 2: Identify content worth preserving
  - Pitfalls encountered → lessons/
  - Important choices made → decisions/
  - New information about people → people/
Step 3: Run CRUD validation, write to corresponding files
Step 4: Update MEMORY.md (if core information has changed)
Step 5: Append a summary of this reflection to the end of the log

4.5 Scheduled Task: Weekly Knowledge Distillation (Every Sunday 00:00)

{
  "name": "weekly-knowledge-distill",
  "schedule": "0 0 * * 0",
  "task": "Scan the last 7 days of logs, check knowledge/INDEX.md for stale markers (>30 days unverified), flag expired entries with ⚠️, move old logs past the threshold into memory/.archive/ (preserve 🔴 priority knowledge files)."
}

Archival rules:

File TypeArchive ConditionProtection Rule
Log YYYY-MM-DD.md>30 days + no references in last 7 daysKeep if referenced
decisions/Never archiveStrategic decisions are permanent
lessons/ 🔴Never archiveCore lessons are permanent
people/Never archivePeople info is relationship-critical

.archive/ uses a dot-prefixed directory. OpenClaw’s semantic search engine (QMD) automatically skips directories starting with . during scans — zero-config hot/cold separation.


5. Skills System

Skills are OpenClaw’s capability extension mechanism. Each skill is a directory containing:

  • SKILL.md: Usage instructions that the AI reads when needed
  • scripts/: The actual execution scripts (Node.js, Python, etc.)

The official distribution includes about 50 pre-built skills covering weather, GitHub, email, notes, music, and other common scenarios. Below are the custom additions built on top.

5.1 Search Enhancement: Perplexity

The default web_search returns raw search results. The Perplexity skill returns AI-synthesized answers with cited sources — better suited for research scenarios where you need to quickly build an information overview.

# Single query
node skills/perplexity/scripts/search.mjs "some research topic"

# Batch queries (same API call)
node skills/perplexity/scripts/search.mjs "question A" "question B" "question C"

Use cases defined in SKILL.md: first step in research tasks, replacing web_search; fallback when web_fetch is blocked by sandbox network restrictions.

5.2 Research Learning Workflow: research-learning

This skill defines a complete five-phase learning process:

Phase 1 · Define Target (conversation)
  Confirm topic, user background, learning goals, preferred approach (examples-first vs. concepts-first)

Phase 2 · Research Materials (tools)
  web_search + browser scraping, materials tiered: intro → intermediate → deep dive
  Priority sources: official docs > well-known blogs > community discussions

Phase 3 · Write to Obsidian (tools)
  Create notes with fixed structure, see Obsidian Integration section below

Phase 4 · Interactive Learning (conversation)
  Q&A appended to 04-qa-log.md; use analogies when something isn't understood; don't repeat the same explanation

Phase 5 · Review and Consolidate (conversation)
  Give 2-3 quiz questions, ask user to explain in their own words, write to 05-my-understanding.md

SKILL.md ends with an “Experience Log” section, where improvements are appended after each research session:

## Experience Log

### 2026-03-01 · First Complete Research Session

- When the user gives a judgment ("this direction is right"), record it to file immediately, don't wait for the next session

5.3 Newsletter Archiving: newsletter-archiver

Archives newsletter emails/articles as Obsidian notes — not just saving the original, but including deep analysis.

Note structure:

---
title: "Title"
date: YYYY-MM-DD
source: "Source - Sub-column"
tags: [tag1, tag2]
url: "original link"
---

## Main Content

(Core summary of the original)

---

# AI Analysis

## Key Insights
(1-3 most important judgments)

## Related Context
(Industry/technical background supplemented via web_search)

## What This Means for You
(Specific actionable recommendations based on user's professional background — no generic advice)

---

## Selected Quotes (Bilingual)

> **Original**
> "..."

**Translation**: ...

Execution flow: fetch original → deep analysis → web_search for background → write to newsletter/<source>/YYYY-MM-DD-<slug>.md → memlog records archival log.

5.4 Financial Data

Three skills covering different layers:

akshare-cn-market — A-share data based on the AKShare library:

  • Individual stock K-lines (daily/weekly/monthly)
  • Market indices (CSI 300, ChiNext, etc.)
  • Macro data: GDP, CPI, PMI, M2, China/US treasury yields
# Example: get recent daily K-line for a stock
python3 scripts/akshare_query.py --type kline --code "600XXX" --period daily --limit 30

stock-info-explorer — Yahoo Finance real-time quotes + chart generation:

  • Real-time quotes, 52-week range, volume
  • High-resolution technical charts with overlaid indicators: MA/RSI/MACD/Bollinger/VWAP/ATR

us-stock-analysis — Comprehensive US stock analysis framework:

  • Fundamentals: financial metrics, business quality assessment, valuation analysis
  • Technicals: trend, pattern recognition, support/resistance levels
  • Competitive comparison analysis
  • Generates structured investment reports

Use cases: stock-info-explorer for daily market checks, us-stock-analysis for deep research, akshare-cn-market for macro data.

5.5 Google Workspace: gog

After OAuth authentication is configured, you can directly operate Gmail, Calendar, Drive, Sheets, and Docs:

# Search unread emails from last 7 days
gog gmail search 'is:unread newer_than:7d' --max 10 --json

# Query this week's calendar events
gog calendar events primary \
  --from 2026-03-04 \
  --to 2026-03-08 \
  --json

# Read Google Sheets data
gog sheets get <sheet-id> "Sheet1!A1:D20" --json

# Update Sheets cells
gog sheets update <sheet-id> "Sheet1!A1:B2" \
  --values-json '[["value A","value B"]]' \
  --input USER_ENTERED

Used with Heartbeat: each heartbeat uses gog gmail search to check priority emails, only pushing notifications when important mail arrives.


6. Obsidian Integration

Obsidian serves as the note library. Integration with OpenClaw mainly works in two directions: AI writing notes, and AI retrieving notes.

6.1 Vault Configuration

The vault path is set via obsidian-cli set-default. All write operations target .md files directly — no Obsidian client needs to be running:

# View current default vault
obsidian-cli print-default --path-only

# Search note titles
obsidian-cli search "keyword"

# Search note content (returns summaries and line numbers)
obsidian-cli search-content "keyword"

# Move note (also updates all WikiLinks)
obsidian-cli move "old-path/note" "new-path/note"

Writing .md files directly with the write tool is more efficient; obsidian-cli is mainly used for cross-note link maintenance and search.

6.2 Learning Notes Directory Structure

The research-learning skill defines a fixed note structure, one directory per learning topic:

DigitalGarden/
└── Learning/
    └── [topic name]/
        ├── 00-learning-map.md     ← MOC navigation, created first
        ├── 01-concept-overview.md ← Core concepts, good for quick review
        ├── 02-deep-notes.md       ← Detailed knowledge points with source links
        ├── 03-references.md       ← Article/video/course links
        ├── 04-qa-log.md           ← Q&A archive, append-only
        └── 05-my-understanding.md ← Written in your own words

00-learning-map.md is the navigation hub, containing a learning path checklist, core concept index, current progress, and WikiLinks:

# [Topic] · Learning Map

> One sentence explaining what this is and why it's worth learning.

## Learning Path

- [ ] [[01-concept-overview]] — Build the framework first
- [ ] [[02-deep-notes]] — Go deep on each section
- [ ] [[03-references]] — Extended reading
- [ ] [[05-my-understanding]] — Output to verify

## Core Concept Index

| Concept | Summary | Section |
|---------|---------|---------|
|         |         |         |

## Learning Status

- Started: YYYY-MM-DD
- Current: Phase 2 / Deep Notes
- Next: Continue section 3 of 02

6.3 Newsletter Archive Structure

DigitalGarden/
└── newsletter/
    └── [source name]/
        └── YYYY-MM-DD-slug.md

Slug rules: lowercase English + hyphens, drop articles (a/the/an), use 3-5 keywords. Example: 2026-03-01-glp1-next-generation-drugs.md.

6.4 Git Sync

The DigitalGarden vault has the Obsidian Git plugin configured for automatic periodic commit + push. No additional action needed after the AI writes files — changes sync to remote automatically.


7. Cursor Agent Integration

Cursor has a little-known CLI subcommand cursor agent that can invoke Cursor Agent in non-interactive mode from the terminal, making it callable by OpenClaw as a coding sub-agent.

7.1 Cursor’s Capability

One line in Cursor’s --help output:

agent    Start the Cursor agent in your terminal.

cursor agent --help shows the full parameter list:

cursor agent [options] [prompt]

Options:
  --print               Non-interactive mode, exits after outputting result (key parameter)
  --workspace <path>    Specify working directory
  --model <model>       Specify model (claude-sonnet-4, gpt-4o, etc.)
  --force               Auto-approve all commands without asking for confirmation

7.2 Usage

Login first:

cursor agent login  # Opens browser for authorization

After login, OpenClaw can call it like this:

# Have Cursor Agent analyze the current project and answer questions
cursor agent --print \
  --workspace /path/to/project \
  --model claude-sonnet-4 \
  "Analyze this project's architecture and identify potential performance bottlenecks"

# Execute a specific coding task (--force skips confirmation)
cursor agent --print \
  --workspace /path/to/project \
  --model claude-sonnet-4 \
  --force \
  "Add a date formatting utility function under src/utils/ with timezone support"

7.3 Position in the Toolchain

OpenClaw (coordination layer)

├─ Lightweight tasks (search, file read/write, calendar/email)
│  └─ Call individual skill tools directly

├─ Complex coding tasks
│  └─ cursor agent --print (has full IDE context, suited for in-codebase operations)

└─ Independent feature development
   └─ sessions_spawn (Claude Code / Codex, suited for brand-new modules)

Cursor Agent’s advantage over other coding agents: it reads the project’s .cursorrules, indexes the entire codebase, understands workspace configuration — for modifications and debugging of existing projects, context quality is higher.

7.4 Known Limitations

In sandbox environments, cursor agent has PTY compatibility issues — the process starts but produces no output, because the sandbox restricts terminal I/O. Solution: ensure cursor agent runs on the host machine, not inside the sandbox.


8. Channel Configuration: Telegram

OpenClaw supports multiple channels (Telegram, Discord, Signal, WhatsApp, etc.), with Telegram currently offering the most complete experience. In March 2026, Telegram Bot API 9.5 opened the sendMessageDraft endpoint to all bots, meaning OpenClaw can now update draft messages in real time as the AI generates — i.e., Streaming Preview.

8.1 Basic Configuration

First create a Bot via BotFather and get the token, then add to your OpenClaw config:

{
  channels: {
    telegram: {
      enabled: true,
      botToken: "YOUR_BOT_TOKEN",
      dmPolicy: "pairing",       // pairing | allowlist | open | disabled
      allowFrom: [123456789],    // Allowed Telegram user numeric IDs
    },
  },
}

After starting the gateway, the first DM requires a pairing flow:

openclaw gateway          # Start
openclaw pairing list telegram
openclaw pairing approve telegram <CODE>

dmPolicy: "pairing" (default) is recommended — after the first pairing, the user is automatically added to the allowlist without needing to configure allowFrom each time.

8.2 Streaming Preview

This is the core advantage of Telegram as the best interface.

OpenClaw has two layers of streaming:

LayerMechanismDescription
Preview streamingchannels.telegram.streamingUpdates message content in real time during generation
Block streamingagents.defaults.blockStreamingDefaultSplits long replies into multiple messages sent progressively

Preview streaming config:

{
  channels: {
    telegram: {
      streaming: "partial",   // off | partial | block | progress
    },
  },
}
  • partial (recommended): Uses sendMessageDraft for in-place updates in DMs; sends a preview message and continuously edits it in groups. No second message after generation completes — clean.
  • block: Updates the preview by appending chunks, suited for very long replies.
  • off: Disables preview; waits for full generation before sending.

In private chats, partial mode delivers an experience close to the streaming effect of Claude Web on desktop: text appears progressively without waiting for the full reply.

Block streaming config (optional):

{
  agents: {
    defaults: {
      blockStreamingDefault: "off",   // Off by default; when enabled, long replies are sent in segments
    },
  },
}

Note: when both Preview and Block streaming are enabled, Telegram automatically skips Preview to avoid double-streaming and prioritizes Block mode. Generally, only enabling Preview streaming is sufficient.

8.3 Access Control

DM permissions:

{
  channels: {
    telegram: {
      dmPolicy: "allowlist",
      allowFrom: [123456789],   // Numeric ID only, @username not supported
    },
  },
}

If you have old entries in @username format, running openclaw doctor --fix will automatically resolve them to numeric IDs.

Group permissions:

{
  channels: {
    telegram: {
      groupPolicy: "allowlist",    // open | allowlist | disabled
      groups: {
        "-1001234567890": {        // Group numeric ID (negative number)
          requireMention: true,    // Whether @bot mention is required to respond
          groupPolicy: "open",     // This group allows all members
        },
        "*": {
          requireMention: true,    // Global default: @mention required
        },
      },
    },
  },
}

To get a group ID: forward a group message to @getidsbot, or read chat.id from openclaw logs --follow.

Group bots have Privacy Mode enabled by default — they can only receive messages that @mention them. To receive all group messages: BotFather → /setprivacy → Disable, then remove the bot from the group and re-add it.

8.4 Inline Buttons and Reactions

Inline Buttons allow the AI to send clickable buttons in replies, useful for confirmation flows and quick selections:

{
  channels: {
    telegram: {
      capabilities: {
        inlineButtons: "allowlist",   // off | dm | group | all | allowlist
      },
    },
  },
}

AI usage example (sending a message with buttons):

{
  action: "send",
  channel: "telegram",
  to: "123456789",
  message: "Confirm this action?",
  buttons: [
    [
      { text: "Confirm", callback_data: "confirm", style: "success" },
      { text: "Cancel", callback_data: "cancel", style: "danger" },
    ],
  ],
}

Reactions config (show Ack emoji during message processing):

{
  channels: {
    telegram: {
      ackReaction: "👀",         // Ack emoji shown while processing
      reactionLevel: "minimal",  // off | ack | minimal | extensive
      reactionNotifications: "own",  // Whether to trigger notification when user reacts to bot message
    },
  },
}

8.5 Custom Command Menu

In Telegram, bots can register a command menu (the / list in the bottom left):

{
  channels: {
    telegram: {
      customCommands: [
        { command: "brief", description: "Daily briefing" },
        { command: "stock", description: "Query stock" },
        { command: "archive", description: "Archive current content" },
      ],
    },
  },
}

Commands are just menu entry points — behavior is determined by the AI based on skills and context; no handler functions need to be implemented.

8.6 Why Telegram Is Currently the Best Interface

Compared to other channels, the combined advantages after Telegram Bot API 9.5:

  • Streaming preview: Native sendMessageDraft support — no flicker, no duplicate messages in DMs
  • Inline Buttons: Enables interactive confirmation flows; other channels have limited support
  • Forum Topics: One bot can maintain independent conversations under different Topics in a supergroup — great for multi-topic management
  • Reactions: Can serve as a lightweight processing status indicator
  • No extra app needed: Mobile Telegram is always available with low latency

The Dashboard (web UI) is suited for extended desktop work sessions; Telegram is better for mobile scenarios and tasks requiring instant notifications. Currently using both, with Telegram as the primary entry point.


9. Multi-Model Switching

OpenClaw supports switching models within the same gateway instance without restarting the service. This is useful across different task scenarios — use a powerful model for writing and research, a fast model for simple Q&A.

9.1 Model Configuration

Set the primary model and fallback chain in the config file:

{
  agents: {
    defaults: {
      model: {
        primary: "openrouter/anthropic/claude-sonnet-4-6",
        fallbacks: [
          "openrouter/google/gemini-2.5-pro",
          "openrouter/deepseek/deepseek-chat",
        ],
      },
    },
  },
}

Fallback chain trigger order: primary model fails (rate limit, outage, timeout) → try fallbacks in sequence.

Advantage of using OpenRouter as a unified gateway: one API key accesses dozens of models without managing separate keys and quotas for each provider.

9.2 Model Aliases

With aliases configured, you don’t need to type full model paths when switching:

{
  agents: {
    defaults: {
      models: {
        "openrouter/anthropic/claude-sonnet-4-6": { alias: "sonnet" },
        "openrouter/google/gemini-2.5-pro":       { alias: "gemini" },
        "openrouter/deepseek/deepseek-chat":       { alias: "deepseek" },
        "openrouter/deepseek/deepseek-reasoner":   { alias: "r1" },
        "minimax/MiniMax-M2.5":                    { alias: "minimax" },
      },
    },
  },
}

CLI alias configuration:

openclaw models aliases add sonnet openrouter/anthropic/claude-sonnet-4-6
openclaw models aliases add r1 openrouter/deepseek/deepseek-reasoner

9.3 Runtime Switching

In a Telegram (or any channel) conversation, send the /model command directly:

/model              → Open model selector (numbered list)
/model list         → List all available models
/model sonnet       → Switch to claude-sonnet-4-6
/model r1           → Switch to DeepSeek R1 (reasoning model)
/model status       → View current model and auth status

Switching only affects the current session — the config file is not modified. Starting a new session with /new restores the default model.

9.4 Model Selection by Task Type

Experience from actual use:

Task TypeRecommended ModelReason
Daily Q&A, writingClaude Sonnet (default)Best balance of speed and quality
Long document processingGemini 2.5 Pro2M token context window
Code tasksClaude Sonnet / Cursor AgentCursor has project context advantage
Quick search / simple answersDeepSeek V3Fast, low cost

Reasoning models (R1, etc.) are suited for tasks requiring step-by-step analysis, but response times are noticeably longer — no need to use them for regular conversation.

A practical pattern: run Sonnet once, let cheaper models follow the playbook. For repetitive flows like scheduled tasks and heartbeats, run through the process once with claude-sonnet-4-6 and have it document its reasoning, steps, and edge cases into the skill’s SKILL.md. Then switch those tasks to MiniMax or DeepSeek V3 as the default model — with a detailed skill document to reference, they perform close to Sonnet at a fraction of the cost. Essentially, one Sonnet run buys quality assurance for all the cheap runs that follow.

9.5 Model Failover

OpenClaw has built-in provider-level automatic failover:

Primary model request → Rate limited (429) → Auto-switch to Fallback 1
                                          → Fallback 1 also rate limited → Switch to Fallback 2
                                          → All fallbacks fail → Return error

This is useful for availability-critical scenarios — for example, the nightly reflection cron doesn’t need to worry about a provider temporarily rate-limiting and causing the task to fail.

9.6 Multi-Provider Authentication

Current providers and their key configuration:

ProviderEnvironment VariableNotes
OpenRouterOPENROUTER_API_KEYUnified gateway, recommended
AnthropicANTHROPIC_API_KEYDirect connection, no OpenRouter needed
GoogleGEMINI_API_KEYGemini series
DeepSeekDEEPSEEK_API_KEYDirect connection, low cost

Key rotation support: for providers with multiple keys, configure OPENROUTER_API_KEYS (comma-separated) for automatic rotation on rate limits — no manual intervention needed.


10. macOS Security Configuration

Running OpenClaw on a Mac means it continuously has network access, file read/write permissions, and the ability to execute local CLI tools in the background. After completing the core functional configuration, it’s worth doing a security audit of the host machine.

10.1 Port Exposure Check

First, confirm which ports are listening for external connections:

# View all listening TCP/UDP ports and their associated processes
sudo /usr/sbin/lsof -iTCP -sTCP:LISTEN -n -P
sudo /usr/sbin/lsof -iUDP -n -P

Note: macOS’s default PATH doesn’t include /usr/sbin — use the full path /usr/sbin/lsof, otherwise the command won’t be found.

Interpreting typical output:

PortCommon SourceRisk Assessment
5900Screen Sharing / VNC client (e.g. UURemote)Confirm password protection and LAN-only access
22SSH (system remote login)Close if remote SSH isn’t needed
8080OrbStack / container managementNormal dev tool, low risk
3000–9000Local development/debug processesNormal — just confirm it’s your own project

Port 5900 is a common false alarm — many third-party remote desktop tools (UURemote, etc.) reuse the VNC port but aren’t bare VNC. As long as the tool itself has password protection, the risk is manageable.

10.2 Firewall Configuration

macOS has a built-in application firewall, but it may not be enabled by default after installation:

Check firewall status:

/usr/libexec/ApplicationFirewall/socketfilterfw --getglobalstate
# Output: Firewall is enabled. (State = 1) means it's on

Check Stealth Mode:

/usr/libexec/ApplicationFirewall/socketfilterfw --getstealthmode
# Output: Stealth mode enabled means it's on

Enable Stealth Mode:

sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setstealthmode on

Or via GUI: System Settings → Network → Firewall → Options → Enable Stealth Mode

What Stealth Mode does: normally, a Mac responds to external pings and port probes (even with “this port is closed”). With Stealth Mode on, it silently drops packets without responding, making automated scanners unable to determine whether the IP is online. No impact on normal usage — only affects passive probing behavior.

View firewall application allowlist:

/usr/libexec/ApplicationFirewall/socketfilterfw --listapps

Check whether the allowlist contains apps that have been uninstalled or are no longer in use but still have allow rules. TeamViewer is a classic example — firewall rules may persist after uninstallation and need to be manually cleaned up.

10.3 OpenClaw Security Audit

OpenClaw has a built-in security audit command that scans skill scripts for suspicious behavior:

openclaw security audit

The audit checks:

  • Environment variable access in skill scripts (to prevent credential harvesting)
  • Outbound network requests (especially patterns of reading sensitive env vars immediately followed by network requests)
  • Validity of denyCommands in the config file

Actual output format (0 critical is the target state):

OpenClaw security audit
Summary: 0 critical · 2 warn · 1 info
Run deeper: openclaw security audit --deep

WARN
gateway.trusted_proxies_missing Reverse proxy headers are not trusted
  gateway.bind is loopback and gateway.trustedProxies is empty. If you expose
  the Control UI through a reverse proxy, configure trusted proxies so
  local-client checks cannot be spoofed.
  Fix: Set gateway.trustedProxies to your proxy IPs or keep the Control UI local-only.
gateway.nodes.deny_commands_ineffective Some gateway.nodes.denyCommands entries are ineffective
  gateway.nodes.denyCommands uses exact node command-name matching only
  (for example `system.run`), not shell-text filtering inside a command payload.
- Unknown command names: camera.snap, camera.clip, screen.record, calendar.add
  Fix: Use exact command names (for example: canvas.present, canvas.hide).

INFO
summary.attack_surface Attack surface summary
  groups: open=0, allowlist=2
tools.elevated: enabled
hooks.webhooks: disabled
hooks.internal: enabled
browser control: enabled
trust model: personal assistant (one trusted operator boundary)

How to handle the two common WARN items:

  • gateway.trusted_proxies_missing: Safe to ignore if you’re accessing the Control UI locally without a reverse proxy
  • gateway.nodes.deny_commands_ineffective: denyCommands only does exact command name matching — the listed unknown command names mean those entries don’t exist in the default command set; update them to correct command IDs (e.g. canvas.present)

For a deeper scan, add the --deep flag:

openclaw security audit --deep

10.4 SSH Management

If you don’t need to SSH into this Mac from outside, disabling the remote login service reduces the attack surface:

GUI: System Settings → General → Sharing → Disable “Remote Login”

Command line:

# Stop SSH service
sudo systemsetup -setremotelogin off

# Confirm status
sudo systemsetup -getremotelogin

If SSH access is genuinely needed, recommendations:

  • Disable password login, allow only key-based authentication (PasswordAuthentication no)
  • Change the default port (reduces automated scan hit rate)
  • Consider a zero-trust solution like Tailscale to avoid directly exposing port 22

10.5 Remote Access Tool Cleanup

Remote desktop tools (TeamViewer, UU Remote, Sunflower, AnyDesk, etc.) share these characteristics: persistent background processes, auto-start on boot, continuously listening on ports. Even when not actively in use, having them installed is a potential attack surface.

If you have TeamViewer or UU Remote installed, there are two things to specifically check:

  1. Whether auto-connect is enabled — many tools enable unattended access by default, meaning someone can remote in without any confirmation on your end. Verify this option is disabled, or that the access password is a strong one you set yourself rather than a weak auto-generated one.
  2. That it’s logged into your own account — confirm the tool is bound to your account and hasn’t been associated with someone else’s. For TeamViewer specifically, check the “Trusted Devices” list and remove any devices you don’t recognize.

Cleanup recommendations:

  1. If you only use it occasionally, launch it when needed and quit the background process when done
  2. If you no longer need it at all, delete it from /Applications and clean up the firewall rules
  3. Keep at most one — don’t have multiple overlapping tools

Check whether a tool is still running:

# Using UURemote as an example
pgrep -l UURemote
# or
ps aux | grep -i uuremote

10.6 Scheduled Security Checks

Consider adding a security check to OpenClaw’s cron tasks, running once a week:

{
  "name": "weekly-security-check",
  "schedule": "0 10 * * 1",
  "task": "Run security check: execute openclaw security audit, compare listening ports against last result, push Telegram alert if any new issues or unknown ports are found. Log results to memory/YYYY-MM-DD.md."
}

No need to manually remember to check — you only get notified when something changes; otherwise it runs silently.


11. Complete Directory Structure

~/.openclaw/workspace/

├── AGENTS.md          # Behavioral guidelines (read on startup)
├── SOUL.md            # Behavioral principles
├── IDENTITY.md        # Identity definition
├── USER.md            # User profile
├── HEARTBEAT.md       # Heartbeat execution checklist
├── MEMORY.md          # Global memory index (≤40 lines)
├── NOW.md             # Current state (overwritten each heartbeat)

├── memory/
│   ├── 2026-03-06.md              # Today's log
│   ├── heartbeat-state.json       # Heartbeat state tracking
│   ├── projects.md                # Project progress
│   ├── infra.md                   # Infrastructure configuration
│   ├── knowledge/
│   │   ├── INDEX.md               # Knowledge navigation
│   │   ├── lessons/               # Lessons / pitfalls
│   │   ├── decisions/             # Important decisions
│   │   └── people/                # People information
│   └── .archive/                  # Cold storage

├── scripts/
│   └── memlog.sh                  # Log append script

└── skills/
    ├── gog/                       # Google Workspace
    ├── perplexity/                # AI search
    ├── research-learning/         # Research learning workflow
    ├── newsletter-archiver/       # Newsletter archiving
    ├── akshare-cn-market/         # A-share data
    ├── us-stock-analysis/         # US stock analysis
    ├── stock-info-explorer/       # Real-time quotes + charts
    ├── xmind-generator/           # Mind map generation
    └── s1cli/                     # Forum operations

12. Some Observations

A few things worth noting from the process of building this system.

Configuring AI is a process of self-clarification. Writing USER.md requires being explicit about your work and interests; writing SOUL.md requires thinking through your preferences for collaboration style; designing the knowledge base structure is essentially deciding what information has long-term value to you. These are questions you don’t usually think about explicitly — the configuration process forces them out.

Markdown files as AI memory storage are more stable than expected. Humans can edit them directly, git can version-control them, and debugging means just opening the file to see the full state — this kind of transparency is hard to get with other approaches. The trade-off is retrieval efficiency, but combined with OpenClaw’s semantic search (memory_search), the difference is barely noticeable in practice.

The skill iteration feedback loop matters. Each skill’s SKILL.md ends with an “Experience Log” section, where improvement notes are appended whenever a problem is found. These notes aren’t for humans — they’re for the AI to reference the next time it executes a similar task. It’s essentially delegating the iteration of operational SOPs to the system itself.

Comments