openclaw-memory-darwin
Outcome-settled agent memory for OpenClaw, backed by darwin-memo's ledger. Instead of anyone curating which lessons are good, every memory_recall answer opens a ticket in the ledger, and the ticket is settled automatically from the run's measured outcome (agent_end success or failure). Lessons that keep steering runs to success accumulate energy and survive; lessons that keep being recalled into failing runs lose energy and die. Selection pressure replaces curation.
This plugin claims OpenClaw's exclusive memory slot (replacing the built-in
memory_search/memory_get tools and prompt section) and provides:
- Tools:
memory_recall(query),memory_store(question, answer, source?),memory_forget(entryId) - Hook:
agent_endsettles every open ticket for the ending session - Service: periodic
ledger tick(upkeep, deaths, consolidation, ticket expiry) - Prompt section: tells the agent to consult memory before risky/recurring decisions
Zero runtime npm dependencies; the raw TypeScript entry is loaded in-process by the OpenClaw plugin loader (jiti). All ledger operations shell out to the darwin-memo CLI, which prints one JSON object per call.
Requirements
- OpenClaw >= 2026.3.24
- The
darwin-memoCLI (the Python bridge). Either onPATHasdarwin-memoor configured via
command with an absolute path, e.g. ~/darwin-memo-clibridge/.venv/bin/darwin-memo.
Install
From the registry (npm):
openclaw plugins install openclaw-memory-darwin
Linked (development, while iterating on a checkout):
openclaw plugins install --link /path/to/openclaw-memory-darwin
Installing a kind: "memory" plugin automatically claims the memory slot and disables the other memory plugins (memory-core, memory-lancedb). Restart the gateway after install/config changes.
Configuration (~/.openclaw/openclaw.json)
{
"plugins": {
"slots": { "memory": "openclaw-memory-darwin" },
"entries": {
"openclaw-memory-darwin": {
"enabled": true,
"config": {
"command": "/Users/you/darwin-memo-clibridge/.venv/bin/darwin-memo",
"memoryPath": "/Users/you/.openclaw/memory/darwin/memory.json",
"resourceScale": 1.0,
"successDelta": 1.0,
"failureDelta": -1.0,
"tickIntervalHours": 24,
"commandTimeoutMs": 15000
}
}
}
}
}
All config keys are optional; defaults below.
| Key | Default | Meaning | | --- | --- | --- | | command | "darwin-memo" | darwin-memo executable (PATH name or absolute path) | | memoryPath | <stateDir>/memory/darwin/memory.json | Ledger file; created by darwin-memo on first use | | resourceScale | 1.0 | resource_scale passed to every ledger call (scales settle deltas) | | successDelta | 1.0 | Delta applied to each open ticket when the run succeeds | | failureDelta | -1.0 | Delta applied to each open ticket when the run fails | | tickIntervalHours | 24 | Hours between background ledger tick runs; <= 0 disables | | commandTimeoutMs | 15000 | Timeout per darwin-memo invocation (ms) |
<stateDir> is ~/.openclaw (or $OPENCLAW_STATE_DIR). Open tickets are persisted to
<stateDir>/memory/darwin/tickets.json (atomic writes), so they survive gateway restarts.
How settlement works
1. The agent calls memory_recall("how should I deploy X?"). The plugin runs
darwin-memo ledger <memoryPath> --scale <resourceScale> decide "<query>". If memory has nothing relevant it says so (no ticket). Otherwise the answer comes back wrapped in an escaped, clearly-delimited untrusted block, and the returned ticket_id is recorded against the current session key. 2. When the run ends, the agent_end hook fires with a measured success boolean. Every open ticket for that session is settled:
ledger settle <ticket> <successDelta|failureDelta> --detail "agent_end success=... durationMs=... error=...". Tickets are removed from the local book regardless of the settle result (the CLI reports
{"settled": false} for unknown/expired tickets, which is logged). 3. The periodic tick applies upkeep: entries pay to live, starved entries die (with an obituary), stale tickets expire.
Honest limits
- A success boolean is a weak conserved resource.
agent_end.successmeasures "the run did
not error", not "the advice was good". A lesson recalled into a run that succeeded despite it still gets paid. The signal is statistical: over many runs, consistently harmful lessons get more failure settlements than success ones and die. Sharper outcome measures (tests passed, task-level reward) would need a sharper settler.
- Every open ticket of the session gets the same delta. There is no per-recall credit
assignment within a run.
- Deltas are configurable, so the economy is only as honest as your config. Large
successDelta with tiny failureDelta produces grade inflation; symmetric defaults are deliberate.
- Lessons that keep being recalled into failing runs die — even if the failure was someone
else's fault. That is the intended pressure: memory that hangs around failure is, at best, not helping.
- Memory failures never kill an agent run: tool errors come back as tool results, hook errors are
logged warnings.
Development
npm test # unit tests (node:test, type-stripped TS, no deps)
npm run e2e # drives the real darwin-memo CLI through the plugin's shell-out modules
See VERIFICATION.md for the verification log against a real OpenClaw install.
darwin-memo: https://github.com/rogermsc/darwin-memo





