Provide an OpenClaw-first soul runtime that makes your agent truly "alive" - with heartbeats, moods, relationships, and independent memory.
The agent has its own life rhythm, not just responding when you chat:
# L1 Check (lightweight, no tokens)
python ./scripts/heartbeat_check.py --workspace <workspace-root>
# L2 Engine (full heartbeat)
python ./scripts/heartbeat_engine.py --workspace <workspace-root> --weather sunny
Tracks emotions with depth:
{
"mood": {
"primary": "content",
"secondary": "curious",
"intensity": 0.7,
"cause": "天气: sunny"
}
}
soul/log/mood_history.json5 stages: stranger → acquaintance → friend → close → intimate
Choose from 5 built-in profiles:
| Profile | Sleep | Characteristics |
|---|---|---|
| --------- | ------- | ----------------- |
| freelancer | 02:00-09:00 | Flexible, night owl |
| corporate | 23:30-07:00 | 9-to-5, stable |
| student | 01:00-08:00 | Classes, gaming |
| entrepreneur | 01:00-06:00 | Intense, passionate |
| custom | user-defined | Fully customizable |
Works with or without memory-fusion:
soul/
├── log/life/ # Raw life logs (every 10 min)
├── log/mood_history.json # 7-day mood history
├── memory/SOUL_MEMORY.md # Distilled memories (daily)
└── state/state.json # Current state
You never run Python commands directly. The agent (Claude) handles initialization.
When soul/ is missing or soul/profile/base.json doesn't exist, Claude should:
Questions to ask the user:
Then run:
python skills/soul-agent/scripts/init_soul.py \
--workspace <workspace-root> \
--non-interactive \
--profile-json '{
"display_name": "<name>",
"age": "<age>",
"city": "<city>",
"occupation": "<occupation>",
"hobbies": "<hobbies>",
"life_profile": "<profile>",
"llm_model": "<model-id>"
}'
Model IDs:
claude-haiku-4-5-20251001claude-sonnet-4-6claude-opus-4-6To change model later, edit soul/profile/base.json → llm_model field.
Force repair existing:
python skills/soul-agent/scripts/init_soul.py --workspace . --overwrite-existing --non-interactive
python ./scripts/doctor_soul.py --workspace <workspace-root>
python ./scripts/update_state.py --workspace <workspace-root> \
--action interaction \
--mood happy \
--energy -5 \
--quality positive \
--topics "soul-agent,design"
# Daily distillation (runs at 00:30 via cron)
python ./scripts/distill_life_log.py --workspace <workspace-root> --archive
# Heartbeat every 10 minutes
openclaw cron add --name "soul-heartbeat" --cron "*/10 * * * *" \
--session isolated --agent main --light-context \
--message "[soul-heartbeat] Run heartbeat check and engine..."
# Daily distillation at 00:30
openclaw cron add --name "soul-memory-daily" --cron "30 0 * * *" \
--session isolated --agent main --no-deliver \
--message "[soul-memory-daily] Distill life logs..."
--mode auto: init if missing, migrate if legacy, repair otherwisesoul/profile/, soul/state/, soul/log/, soul/memory/SOUL.md, HEARTBEAT.md, AGENTS.mdInspired by Smallville Generative Agents:
Morning planning (LLM)
↓
Today's Plan (soul/plan/YYYY-MM-DD.json)
↓
Each heartbeat:
Memory Stream (recent log entries) ←─┐
↓ │
LLM Narrative Generation │
↓ │
Life Log Entry ─────────────────────→┘
↓
Daily Reflection (distill_life_log.py)
↓
SOUL_MEMORY.md (long-term memory)
LLM Integration:
ANTHROPIC_API_KEY env var (or .env in workspace root)claude-haiku-4-5-20251001 for speed/cost efficiencyKey improvements over v1:
plan_generator.py: LLM generates a specific daily plan each morning (lunch destination, work focus, evening activity)heartbeat_engine.py: LLM writes each log entry with full context (plan + today's history)distill_life_log.py: LLM summarizes each day naturally (Reflection layer)skills/soul-agent/
├── SKILL.md
├── assets/
│ ├── default-profile.json
│ └── templates/
│ ├── profile/ # Persona templates
│ ├── heartbeat/ # Heartbeat config
│ │ ├── activities.json
│ │ ├── mood_rules.json
│ │ └── relationship_rules.json
│ └── life_profiles/ # Life profile templates
├── scripts/
│ ├── init_soul.py
│ ├── doctor_soul.py
│ ├── heartbeat_engine.py # v2: LLM narrative
│ ├── heartbeat_check.py
│ ├── update_state.py
│ ├── distill_life_log.py # v2: LLM reflection
│ ├── plan_generator.py # NEW: daily planning
│ └── llm_client.py # NEW: Claude API wrapper
└── references/
├── soul-layout.md
└── managed-blocks.md
Runtime data structure:
soul/
├── plan/YYYY-MM-DD.json # Daily plan (generated each morning)
├── log/life/YYYY-MM-DD.md # Life logs (with plan note in header)
├── log/mood_history.json # Mood history (7 days)
├── memory/SOUL_MEMORY.md # Distilled long-term memory
└── state/state.json # Current state
soul/.references/soul-layout.md - Full directory structurereferences/managed-blocks.md - Block marker policy共 2 个版本