PLUR1BUS turns OpenClaw into an agent with long-term memory: a per-agent isolated LanceDB store as the source of truth, a mirrored Obsidian vault as a human-readable view, and a small set of background jobs that classify, consolidate, and (when warranted) notify.
PLUR1BUS 7.4.0 — evidence the agent can stand behind
Current version: 7.4.0 — package metadata and the OpenClaw manifest are aligned to the GitHub tag v7.4.0. See the changelog for the full history.
By default, each agent gets its own LanceDB store under {baseDbPath}/{agentId}/ and a matching Obsidian vault folder for browsing. An explicit named-namespace configuration can read the same validated agent from multiple storage namespaces while keeping one active writer. The plugin captures conversation-derived memory cards automatically, runs a daily consolidator and a critical-push classifier as cron-driven background jobs, and exposes a small set of Telegram commands so the user can inspect, edit, or toggle behaviour without leaving the chat.
- An epistemic status every write earns. New user captures are recorded as
observed, every other new write as explicituntrusted; nothing inventstrustedany more. The skill miner clustersobserved | corroborated | trustedplus valid pre-cutoff legacy rows and no longer applies a 30-day lookback, so an existing install keeps mining its history instead of reportingscanned: 0. The cutoff marker is written once, at the first upgrade, before the first write. - Skill approval survives a crash.
SKILL.mdis written first (tmp + fsync + rename), then the evidence transitions; a partial failure staysactivation_partialand can be re-applied idempotently. - Forgotten stays forgotten. Every reachable card re-insert — store, content
update,
updateCard, compaction, auto-capture, light-dream rewrite — checks the tombstone registry beforetable.add. Same-text replay by the user is still allowed. - A global inject budget (
recall.globalInjectMaxChars, default 17000) trims memories before time and reminder context, so a large recall can no longer crowd the rest of the prompt out. - Two new curation commands.
/plur1bus curation resolve <keep|drop>ends a neoconflictwithout any hard filter, and/plur1bus curation drop-injecteddemotes only injected behaviour conflicts after a preview and a nonce — genuine conflicts are never touched. - Derived records carry visibility. Pattern and dream writers stamp scope; readers filter by requester. Legacy records without a stamp stay own-agent only.
- The host patch is optional.
PLUR1BUS_SKIP_HOST_PATCH=1is honoured by bothscripts/setup-feature-crons.mjsandscripts/install-memory-system.sh; the install completes without writing into the OpenClaw dist tree.
Condensed summary of 7.3.0–7.3.5; see the changelog for detail.
- Valid-time and trust state (7.3.0) — memories carry temporal validity, and epistemic trust became a first-class field alongside a batch of audit fixes.
- Security and scope hardening (7.3.1) — bound episode-graph endpoints, ownership-partitioned compaction, fail-closed skill scans.
- The classifier stopped rejecting its own default (7.3.2) —
faktwas missing from the type enum, so every classification run failed validation. - GC got a trigger and a policy (7.3.3) — an eighth feature cron at 04:45 plus
a configurable
maxMemoryCount; before this, garbage collection had no scheduler at all. importance = 1.0works again (7.3.4) — the value is the agent's reserved manual core marker; it was silently ignored because the core score also demanded an emotional intensity the agent cannot set. Core scores are now normalised to the features that actually exist.- REM dreaming finds patterns again (7.3.5) — similarity was compared on two different scales, so even an identical vector fell below the threshold: zero edges, zero clusters, ever. Feature crons are also staggered per agent now.
- Complete, version-bound deploy verification — repair checks cover all static and literal dynamic runtime imports, bind package and manifest identity to one immutable source snapshot, and roll back the complete deployment if any copy or final validation fails.
- Safe promoted-memory reindex bridge — the replacement maintenance CLI is configuration-aware, namespace-aware, idempotent, dry-run by default, and compatible with predecessor marker state without forwarding redacted credentials.
- Staggered daily consolidation — exact PLUR1BUS-owned per-agent jobs are scheduled 15 minutes apart, avoiding simultaneous consolidation pressure; custom or look-alike jobs remain untouched.
- Explicit recovery tooling — deploy verification and repair accept an expected release version and report missing source/preflight reasons instead of producing a mixed installation.
- Six high-frequency jobs reduced by about 83% — Afterthought and Critical Push now run every three hours instead of every 30 minutes.
- Safe schedule migration — only PLUR1BUS's shipped 30-minute cadence is migrated; custom operator intervals and delivery targets remain untouched.
- No active-memory recursion — active-memory child sessions cannot trigger another PLUR1BUS recall or capture pass.
- Agent-scoped semantic discovery — scheduled discovery processes only the triggering agent's configured Obsidian workspaces.
- Slow healthy gateways no longer miss reconciliation — the redacted effective-config snapshot used by feature-cron setup now has a focused 30-second budget; live measurements were approximately 12.5–18 seconds.
- Narrow compatibility fix — the fail-closed result contract, single snapshot, shared CLI defaults, schedules, delivery, model routing, and thinking policy remain unchanged.
- No outer carrier model for Afterthought or Critical Push — exact internal commands are finalized through OpenClaw's normal delivery path before the carrier agent/model executor.
- Scoped fail-closed recovery — if the host dispatcher is unavailable, only exact PLUR1BUS-owned feature jobs are paused and marked; custom prompts and unrelated jobs are never claimed.
- Schedules and delivery remain intact — existing jobs migrate idempotently while keeping their 30-minute cadence and validated targets.
- Native internal LLM policy — actual Afterthought composition and
classification still inherit the target agent's OpenClaw model and thinking
policy; PLUR1BUS does not force
thinking: off.
- Complete high/medium audit remediation (B1–B15) — durable memory writes, timeout settlement, cancellation barriers, diagnostics, installer paths, operational maintenance, Obsidian mutations, and background jobs were hardened and regression-tested.
- Strict memory ownership — private, workspace, and user data use canonical agent/workspace/user request contexts. Sharing is explicit, confirmation-bound, owner-bound, and isolated in separate storage pools; unbound or conflicting rows fail closed.
- Recall and namespace closure — B12 Core and B12-P add secure read-only legacy access, globally bounded multi-namespace recall, adaptive budgets, compression, decision traces, and strict graph/provider authorization.
- OpenClaw owns the LLM choice — PLUR1BUS feature routes inherit the effective target agent model unless a feature has a complete explicit direct-provider override. Hard-coded chat-model defaults were removed.
- Exact LLM result cache — deterministic internal transforms can reuse validated, bounded, agent-scoped results without leaking prompts or credentials.
- Dependency and runtime baseline — patched transitive dependencies and
sharp@0.35.3close the dependency audit; PLUR1BUS now requires Node.js 22.5 or newer. - Release verification — the release baseline contains 3,260 tests (3,259 passed, 0 failed, 1 skipped) and
npm auditreports 0 vulnerabilities.
- Candidate status updates survive content dedupe — promote/demote/prune/tombstone updates are append-preserved while ordinary candidate captures remain content-deduped.
- Capped memory dynamics are resumable — retrieval-ledger caps store partial entry progress, and daily decay rotates with a persisted cursor instead of repeatedly touching the first rows.
- LanceDB vector wrappers normalize safely — Arrow-style vector wrappers are converted before update writes to avoid schema failures during consolidation.
- REM-Dream cron provisioning — New installs provision
rem-dreamwhenmerging.enabled: trueis explicitly authored, instead of shipping an enabled handler without a scheduler binding. /statecommand fix — The top-level status command no longer crashes on an out-of-scopectxreference.- Emotion config-schema sync — The strict schema now accepts the documented emotional-dynamics keys used by 6.9.x configs.
- Generic temperament defaults — Shipped defaults no longer bake in agent-specific personalities; per-agent temperament belongs in user config.
- Emotional dynamics — Mood persistence, temperament presets, decay modulation, and stronger mood-congruent recall boosts landed in the 6.9.0 line.
- i18n sync — 752 missing translation keys added for new OpenClaw channel wizards (IRC, Feishu, NextcloudTalk, Google Chat).
- TypeScript optional dep —
typescriptis now declared as anoptionalDependencyso the code-index feature works out of the box without forcing TS on all users. - Installer fixes —
buildInstallLogEventnow correctly passesfeatureModeinstead of hardcoding"preserve"; dry-run vs. remote-target warnings are properly distinguished; dead code removed. - Installer performance — 9 sequential
jqsubprocess calls consolidated into batcheval+@shextracts. - Neo worker drain — Missing
awaitondrainEmbeddingQueue()caused the unresolved Promise to be serialised as{}inpostMessage; callers now receive correct drain results. - Auto-capture robustness —
statSyncrace condition fixed (file deleted betweenreaddirSyncandstatSync);addQueryVectornull-return guard added. - ts-source-indexer — O(n)
symbols.find()in AST visitor replaced with aMapfor O(1) lookup. - Manifest sync —
openclaw.plugin.jsonversion aligned withpackage.json. - Security hardening —
scope: "user"writes now require an authenticated user identity (userscope is owner-bound) and are filtered in recall/visibility checks.
- Media diarization context — Async diarization merge pipeline, manual speaker mapping, contextual speaker-name proposals, and no biometric enrollment.
- Emotional-state injector packaged — Tracked
.openclaw/extensions/emotional-state-injector/files are included in the npm tarball; runtime activation still requires the OpenClaw plugin entry/allow config and a gateway restart. - Performance follow-up — Legacy auto-capture duplicate checks are batched, duplicate lookup can use ANN multi-query search when available, JSON hot-path writes are queued asynchronously, and high-cost prompt work is narrowed.
- Optional code index — Local JS/TS index generation writes
.plur1bus/code-index.jsonand can render bounded<code-context>query output.
PLUR1BUS can build a local JS/TS code index without CocoIndex:
npm run code-index -- /path/to/workspace
npm run code-index -- /path/to/workspace --query "/plur1bus code-index"The index is written to .plur1bus/code-index.json and contains normalized files, symbols, import/call/register edges, and symbol chunks. --query prints a bounded <code-context> block from the generated index. It uses the TypeScript Compiler API through the optional typescript dependency and keeps the PLUR1BUS schema independent of the parser implementation.
- Multi-Namespace Pool — One validated agent can opt into recall across named LanceDB storage namespaces; this never selects another agent and is not cross-agent sharing.
- Temporal Continuity Context — Auto-injected time-anchor block lets the agent orient itself after gaps or compactions without hallucinating dates.
- Conflict Summary Management — Contradiction detector now emits structured conflict summaries;
/plur1bus obsidian conflicts buildrenders them as Obsidian pages. /plur1bus startonboarding — Read-only status and onboarding guidance for feature profiles and vault setup.- Auto-capture schema sync —
scripts/auto-capture-lancedb.mjsgainsworkspaceKeyfield; schema migration is backward-compatible and idempotent. - Internal-turn skip guard —
shouldSkipAutoRecallForInternalTurnprevents feedback loops when the gateway injects synthetic cron messages.
- Self-reflection on recall quality — Precision, Recall, F1 computed from user feedback (
/mf +/-/~). Coverage-gap detection finds topics with few or weak memories. - Threshold-based reflection trigger — Auto-runs when
sessionThreshold(default: 50) orintervalDays(default: 7) is reached. Optional LLM-generated natural-language report. - Persistent state — Reflection state stored in
_meta-cognition-state.jsonper workspace.
- Embedding-based pattern detection — Clusters similar turns by cosine similarity over embedding centroids.
- Cluster persistence — Clusters survive restarts, stored per workspace/agent.
- Cooldown mechanism — Rate-limited to avoid spam (default: 24h per workspace).
- Configurable thresholds —
minClusterSize,similarityThreshold,maxNudgesPerDay.
- Budget-Gate per tier — Tier-1 (regex), Tier-2 (heuristic), Tier-3 (LLM) independently enable/disable.
- Configurable model per tier — An absent model uses the effective OpenClaw agent model;
gpt-4o-miniis only an explicit override example. - Feature-Toggle — Lock
emotionTierto a specific tier or useautofor dynamic escalation. - Graceful degradation — Falls back from Tier-3 to Tier-2 when neither a native OpenClaw route nor a complete direct override is available.
- Explainability (
--explainflag for/memory) — Human-readable rationale per result: score breakdown, boost factors, temporal relevance. - Garbage Collection job — Background cleanup of expired/stale memories with configurable retention policies.
- Feedback Analyzer — Background analysis of
/mffeedback for recall-quality improvement.
/correcttreated as recall event — AftersafeUpdate()inserts the corrected card,applyRetrievalReinforcementrefresheslastRetrievedAt, incrementsretrievalCount, and boostsmemoryStrength.- Null guard — If
getById(newId)races or fails, reinforcement is silently skipped; the correction itself is never rolled back.
- ACL / Access Control — Agent- and workspace-scoped memory access.
searchByTopic,getCard, and recall pipeline filter by ACL. Unauthorized access is logged. - Feedback loop (
/mf) — Thumbs-up/down/neutral feedback on any memory result. Persisted per workspace. - Temporal reasoning — Queries like "last month", "3 days ago", "Q2 2026" parsed to concrete date ranges before boost/rerank.
- Collaborative memory (
/share) — Copy any card into a workspace-shared pool with ACL protection. - Query refinement — Automatic query rewrite on poor first results, merged and deduplicated.
- Recall hardening —
maxPromptMemories(default 12), dedup threshold 0.78, acronym recognition,canonicalMaxItems(default 5). - Typ-based half-life —
halfLifeDaysMap: transient (60d), episodic (180d), longContext/project (600d). - Performance — LRU+TTL embedding cache, semantic recall compression, adaptive recall tiers, graph-index traversal, reinforcement loop.
- Security — SQL-escaping, ACL hardening for destructive commands, path-traversal protection, filter-parser injection resistance.
- Semantic long-input handling —
/memory,/forget,/correctaccept any length. >6k chars are semantically compressed; >100k chars prompts for file/vault source. - Feature activation profiles — On first start proposes a
recommendedprofile (all features active, Obsidian/reviews markedpending_setup). Core memory works immediately; advanced features require explicit confirmation. - Proposal-only merging — Daily compaction detects duplicates, generates merge proposals in
merge-proposals.jsonl, never auto-applies. - Conflict resolver — Scans for contradictions, emits
recommendation(review_onlyorapply_via_safe_reconsolidation), never modifies memory directly. - Reranker timeout & fallback — Configurable timeout (default 5s) with automatic fallback to vector-only ranking.
- schicht15 deduplication — KNOWLEDGE.md promotions tracked per workspace+agent. Double-promotion prevented via
memoryId+ optionalcontentHash. - Obsidian bridge apply mode (safe) —
mode: "apply"creates per-file backups, manifest (beforeHash/afterHash), and audit-log entry. Vault path confirmation required before first write. - Rate-limited background jobs — Daily consolidation capped at 1×/day/agent; REM dreaming at 1×/week.
These features run after normal recall and only append results; they never replace the primary recall result and never write memory data.
Reads a precomputed .plur1bus/semantic-lens-index.json from the workspace and adds a small number of community/bridge/faded memories that normal recall may have missed.
- Default:
enabled: falsein schema. - Caps:
maxLensMemories: 3,maxBridgeMemories: 2,maxFadedMemories: 1,maxCommunities: 2. - Hard timeout: 50 ms; fallback returns base recall unchanged.
- No live graph recompute, no second recall path, no writes.
MVP reactivation hook that appends a <memory-reactivation> block when a conversation appears to resume after an idle gap, a compaction, or a continuation signal.
- Default:
enabled: falsein schema;visibleHints: false. - Triggers: idle threshold (45 min), continuation signal, first substantive message, or post-compaction gap.
- Caps:
maxReactivationMemories: 3,maxFadedReactivationMemories: 1,maxOpenThreads: 3,maxCommunities: 2. - Hard timeout: 50 ms; silent fallback on error.
- State is module-level in-memory only; no writes to cards, tags, graph links, records, or quarantine.
Record notes can contain an idempotent managed block (id="graph-links") with wikilink edges. The block is regenerated, not appended, and conflicts with manual edits are reported.
- Tiers:
explicit(memoryIds/sourceRefs),type(type-based rules),semantic(precomputed link index). - Default semantic threshold: 0.78.
semanticDiscoverybuilds.plur1bus/link-index.jsonfrom memory mirrors + vectors behind a confirmation gate; it is not auto-applied.
Memory mirrors use technical filter tags, not semantic memory tags:
plur1bus/memoryplur1bus/agent/<id>plur1bus/workspace/<id>plur1bus/category/<cat>plur1bus/scope/<scope>
These tags are used for vault filtering and graph grouping; they do not carry semantic memory content.
| Command | What it does |
|---|---|
/state |
Status snapshot: memory card count, sync state, last plausibility run, any open issues with reason + fix hint. |
/memory <query> |
Search the agent's memory via the recall pipeline. Accepts queries of any length. Add --explain for result rationale. |
/forget <text> |
Forget a memory card. Archive-first guarantee — the card is JSON-archived before deletion. |
/correct <old> zu <new> |
Update a memory card. Archive-first guarantee. Accepts zu, →, or -> as separator. |
/mf <id> + / - / ~ |
Feedback on a memory result: 👍 positive, 👎 negative, ~ neutral. Persisted per workspace. |
/share <id> |
Copy a memory card into the workspace-shared pool. ACL-protected. |
/enable <feature> |
Turn on a whitelisted feature (vaultSync, kritischPush, dailyConsolidation). |
/disable <feature> |
Turn off the same. Writes atomically into openclaw.json; gateway restart required. |
/plur1bus setup |
List the available profile choices without changing configuration. |
/plur1bus setup safe |
Explicitly apply the Safe profile; core capture/recall stays usable and additional mutators remain off. |
/plur1bus setup recommended |
Explicitly apply Recommended while preserving existing opt-outs and write-safety gates. |
/plur1bus start |
Show read-only status and onboarding guidance; it does not change configuration. |
| Command | What it does |
|---|---|
/plur1bus skills review |
Show open skill proposals. |
/plur1bus skills approve <id> |
Approve a skill proposal. |
/plur1bus skills reject <id> |
Reject a skill proposal. |
/plur1bus skills list |
Show active skills. |
/plur1bus skills show <id> |
Show proposal details. |
/plur1bus reminders list |
List active reminders. |
/plur1bus reminders cancel <id> |
Cancel a reminder. |
/plur1bus obsidian dashboards build |
Build Obsidian dashboard pages. |
/plur1bus obsidian conflicts build |
Build conflict report pages. |
/plur1bus doctor |
Run diagnostics and show runtime status. |
/plur1bus internal proactive-check |
Run proactive nudge detection manually. |
/plur1bus internal meta-reflect |
Run meta-cognition reflection manually. |
/plur1bus internal afterthought |
Run the delayed follow-up job manually (see below). |
When the last conversation ended 30–120 minutes ago with an open outcome (the user asked for details, or the topic was dropped mid-thread), the plugin can compose a short, casual follow-up message ("Mir ist zu … noch eingefallen…"). This is gated by the shared proactive governor budget, capped at one per day, and skipped for any topic already surfaced as an open thread today. Recommended cron: every 3 hours, run the exact command /plur1bus internal afterthought with announce delivery. The plugin command itself returns either the composed text or OpenClaw's NO_REPLY suppression token. The shipped host patch is applied or verified during gateway registration and again before automatic cron provisioning; it finalizes this exact feature command through OpenClaw's normal delivery path before executeCronRun(). If the OpenClaw runtime cannot be patched, a registration-time before_agent_reply admission guard claims the two exact feature commands, their shipped legacy carrier contracts, and the precise [PLUR1BUS] result envelope added by the previous dispatcher with NO_REPLY before model resolution. This closes the pre-gateway_start race and pauses only those automatic feature runs without spending outer-model tokens. The gateway hook then safety-disables the same known jobs through OpenClaw's in-process cron service, and CLI setup reconciles and retries. Jobs are marked in their names while preserving delivery configuration. Once the boundary is healthy, only marked jobs inside the current bound-agent plan, with a validated delivery and a still-enabled feature, are atomically migrated, renamed, and re-enabled after restart. Other custom prompts, surrounding whitespace, prefixes, and suffixes are never claimed by the admission guard.
Setting this cron up is automatic when its raw feature gates are explicitly enabled — see below.
node scripts/setup-feature-crons.mjs installs or verifies the host dispatcher first. When healthy, it loads exactly one validated configuration snapshot with openclaw gateway call config.get --json, discovers bound agents, and idempotently plans up to seven jobs per agent plus one install-wide GC job. It fails closed without normal cron planning when the gateway call fails, JSON is invalid, valid !== true, or sourceConfig/runtimeConfig is not a plain object. If the host patch is unavailable, the safety path does not depend on configuration: it reads cron state only to disable active jobs whose raw payload and canonical PLUR1BUS identity exactly match the two direct feature jobs; custom prompts and unrelated jobs remain untouched. It never falls back to local config files or alternate raw/resolved fields.
The two configuration views have separate roles: sourceConfig alone controls explicit raw feature gates and the raw skillMiner schedule; runtimeConfig alone controls effective bindings, accounts, and delivery. Runtime defaults cannot enable jobs. The eligible jobs are:
persona-evolve:personaVoice.enabled && skillMiner.enabled; Sunday 04:15 local time, staggered five minutes per agent; no delivery.afterthought:afterthought.enabled && (skillMiner.enabled || merging.enabled); every 3 hours; exact-command announce delivery with a direct text/NO_REPLYresult.consolidate-daily:dailyConsolidation.enabled; daily 04:00 inEurope/Berlin; no delivery.classify-recent:criticalPush.enabled; every 3 hours; safe announce delivery of approved pushes orNO_REPLY.rem-dream:merging.enabled; daily 01:15 inEurope/Berlin; no delivery.skill-miner:skillMiner.enabled; raw Croner-compatible cron/timezone after conservative syntax validation, defaulting to Sunday 03:00 inEurope/Berlin(timezone: nullmeans local time). Invalid literals, descending ranges (including named month/day ranges), names, modifiers, or literal-step forms are ineligible.discover-semantic-links:obsidianBridge.enabled && obsidianBridge.graphLinks.semanticDiscovery.enabled; daily 02:00 inEurope/Berlin; no delivery.gc-run:gc.enabled; daily 04:45 inEurope/Berlin, afterconsolidate-dailyhas produced the candidates; no delivery. This one is a singleton —runGcJobiterates over every agent database itself, so exactly one job is planned regardless of how many agents the install has.
Every job runs with --agent <agentId> --session isolated. Provisioning does not set model, fallback, token, auth, API, or other credential overrides, so OpenClaw's default LLM and per-agent credentials remain authoritative. The script remains idempotent and exit-0 for install safety, so it can run from any of these channels:
npm install/npm postinstall— fires when the plugin is installed vianpm install(e.g.npm install -g @cyb3rb1ade/plur1bus-memory).- Gateway startup (deferred bootstrap) — a registration-time
before_agent_replyguard blocks known PLUR1BUS direct-feature cron payloads before model resolution whenever host-patch registration failed, so even a cron firing beforegateway_startcannot invoke the outer model. Agateway_starthandler inindex.jsthen schedules a one-off, non-blocking run 90 seconds after every healthy gateway start (long enough for theopenclawCLI to be able to talk to the now-running gateway). If host-patch registration fails, the awaited startup hook first disables exact active shipped direct jobs throughgatewayContext.getCron()before scheduling the CLI attempt at 0 ms, even when automatic provisioning is disabled. CLI/config/list/edit and safety-recovery failures are retried in the same gateway process with bounded backoff (1s, 5s, 30s, 2m, 10m). This channel covers the documented install path (git clone+rsyncinto~/.openclaw/extensions/..., which never runsnpm install) as well as ClawHub installs. Healthy runs are throttled to at most once per ~20h; pending work and plugin version changes retry earlier. Disable normal provisioning with"featureCronSetup": { "auto": false }; the fail-closed safety run remains active. - Manual —
/plur1bus setup crons(optionally--agent <id>/--account <acct>to force single-agent mode).
The /plur1bus doctor and /plur1bus status feature-cron hint is condition-derived, not "have we shown this before": it reads the marker file and only surfaces a hint when setup has never run, ran under an older plugin version, or ran but couldn't create everything it planned (some crons are still pending — e.g. no delivery target could be derived). It's silent once a current-version run reports nothing left to create.
- Bound-agent rule: only agents with
bindings > 0(i.e. an actual chat channel routes to them) get feature crons. Subagents (bindings === 0— researchers, deep-divers, and other internal-use-only agents) are deliberately excluded; they have no chat to receive an automatic persona evolution or an afterthought delivery, and running these jobs against them would be pure compute waste. - One agent per workspace: PLUR1BUS state for these jobs (persona voice, proactive-governor budget, afterthought dedup state, …) is keyed by workspace directory, not agent id. If two bound agents share a workspace, only one gets the crons (tiebreak:
isDefaultfirst, then most bindings, then alphabetically-first id) to avoid two crons double-firing against the same state files. - Per-agent identity: all per-agent canonical names use
plur1bus <feature> <agentId>. An existing job is owned only by an exact, case-sensitive agent id plus either its exact canonical name or exact first command line; missing or different agents are untouched. Every exact owned duplicate is inspected and reconciled, even when another duplicate is already safe. - Safe delivery: outbound targets never come from
allowFrom. Delivery-required jobs use only a conservatively validated Telegram bindingmatch.peer.id(includingt.me/<handle>) or effective account/rootdefaultTo. Every relevant non-ACP binding must agree on channel, and an account inherits only whenmatch.accountIdis truly absent. Omitted accounts resolve in order from an explicit validdefaultAccount,accounts.default, one sole named account, or a root account proven by configuredbotToken/tokenFile; routing fields alone never invent a root default account. Unsupported providers, wildcard, placeholder, redaction, zero-id, disabled-account, explicit empty/missing account, mixed-account, and conflicting target/channel/account states are rejected. Existing delivery seeds require exactmode: "announce"; case or whitespace variants are unsafe. A job without a validated target is created disabled with--no-deliver; every unsafe owned delivery job is disabled and stripped of delivery. Non-delivery jobs retain only missing delivery or exactmode: "none"; every other delivery object is removed. - Agent discovery/input failure: if
openclaw agents list --jsonfails, is unparseable, or yields no bound agents, no cron is mutated. Passing a validated--agent <id>forces one explicit agent; missing, option-like, or invalid--agent/--accountvalues fail closed, and--accountwithout--agentis rejected.
PLUR1BUS requires Node.js 22.5 or newer.
Install the immutable GitHub Release package:
openclaw plugins install \
https://github.com/Cyb3rb1ade/openclaw-plur1bus-memory/releases/download/v7.1.8/cyb3rb1ade-plur1bus-memory-7.1.8.tgzOr install the exact ClawHub release:
openclaw plugins install \
clawhub:@cyb3rb1ade/plur1bus-memory@7.1.8 \
--acknowledge-clawhub-riskGitHub Packages requires an authenticated GitHub npm registry. After
authenticating @cyb3rb1ade for https://npm.pkg.github.com, install and pin
the exact package:
npm login --scope=@cyb3rb1ade --auth-type=legacy \
--registry=https://npm.pkg.github.com
openclaw plugins install @cyb3rb1ade/plur1bus-memory@7.1.8 --pinFor a source checkout, clone into the OpenClaw extensions folder and restart the gateway:
git clone https://github.com/Cyb3rb1ade/openclaw-plur1bus-memory.git \
~/.openclaw/extensions/memory-lancedb-namespaced
cd ~/.openclaw/extensions/memory-lancedb-namespaced
npm install --omit=dev
systemctl --user restart openclaw-gatewayThe package includes patches/apply-cron-plugin-direct-dispatch.mjs. Gateway
registration reapplies it on every start so OpenClaw upgrades cannot silently
restore the model-backed carrier. The patcher writes an atomic, source-hash
bound rollback copy beside the changed runtime bundle. It discovers the active
OpenClaw package from the running entry point or the openclaw executable on
PATH (with OPENCLAW_DIST_DIR as an explicit override), so global prefixes,
NVM, Homebrew-style layouts, and user installs are not tied to /usr/lib.
When the runtime is not writable or its audited structure cannot be recognized,
automatic setup disables exact owned direct jobs rather than allowing them to
fall back to the model carrier. Set PLUR1BUS_SKIP_HOST_PATCH=1 to skip the
install-time host rewrite (Atlas supply-chain objection); feature crons then
need a native dispatcher.
Then add a plugins.entries["memory-lancedb-namespaced"] block to your openclaw.json (see below).
Minimal config block in openclaw.json. This is an explicit override example:
the named gpt-4o-mini value and its credential are illustrative user choices,
not PLUR1BUS defaults.
{
"plugins": {
"entries": {
"memory-lancedb-namespaced": {
"enabled": true,
"hooks": {
"allowConversationAccess": true
},
"config": {
"baseDbPath": "~/.openclaw/memory/lancedb-namespaced",
"obsidianBridge": {
"enabled": true,
"mode": "augment",
"vaultPath": "~/.openclaw/vault",
"backupBeforeApply": true,
"auditLog": true,
"requireVaultPathConfirmation": true
},
"emotion": {
"tier": "auto",
"t2": { "enabled": true },
"t3": {
"enabled": true,
"model": "gpt-4o-mini",
"apiKey": "${OPENAI_API_KEY}",
"escalationConfidence": 0.85,
"timeoutMs": 4000
},
"moodInfluence": 0.3,
"intensityHalfLifeFactor": 1.0,
"temperaments": {
"bernhardine": { "preset": "warm", "baseline": { "joy": 0.35, "trust": 0.5 }, "sensitivity": 1.5, "decayMultiplier": 1.3 }
}
},
"dailyConsolidation": {
"enabled": true
},
"merging": {
"enabled": true,
"mode": "safe-versioned",
"autoApply": false
},
"reranker": {
"enabled": true,
"timeoutMs": 5000,
"fallbackOnError": true
},
"security": {
"allowChatConfigCommands": true,
"allowModelDestructiveMemoryOps": true,
"allowedUserIds": [],
"allowedChatIds": []
},
"runtime": {
"embeddingCacheEnabled": true,
"embeddingCacheMaxEntries": 128,
"embeddingCacheTtlMs": 300000,
"embeddingCacheScope": "agent",
"llmResultCacheEnabled": true,
"llmResultCacheTtlMs": 86400000,
"llmResultCacheMaxEntries": 256,
"llmResultCachePersist": false,
"llmResultCacheMaxBytes": 67108864,
"llmResultCacheMetrics": true
}
}
}
}
}
}hooks.allowConversationAccess: true is mandatory for this trusted memory
plugin. OpenClaw otherwise rejects the before_agent_reply admission fallback;
if the independently installed host patch then becomes unavailable, a direct
feature cron could reach the outer model before startup reconciliation. The
installer enforces this single permission even in preserve mode while keeping
all unrelated hook and feature choices unchanged.
All paths default to $HOME/.openclaw/... if omitted. OPENCLAW_CONFIG_PATH and OPENCLAW_HOME env vars override the lookup of the gateway config file used by the toggle commands.
Omitting namespaces preserves the legacy-flat layout exactly:
{baseDbPath}/{agentId}. Named routing is enabled only by supplying the strict
object explicitly:
{
"baseDbPath": "~/.openclaw/memory",
"namespaces": {
"activeWriteNamespace": "lancedb-local",
"activeRecallNamespaces": ["lancedb-local"],
"legacyReadOnlyNamespaces": ["lancedb-namespaced"],
"crossNamespaceRecall": true
}
}An explicit baseDbPath may be the named root, as above, or the active writer
leaf (~/.openclaw/memory/lancedb-local); both forms resolve to the same
layout. Namespace identifiers must match
^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$. The writer must occur in active recall,
and active namespaces must be disjoint from legacy read-only namespaces.
Legacy namespaces participate only when crossNamespaceRecall is exactly
true; they are opened without table creation, schema migration, or mutation.
Every recalled table must use the configured embedding dimensions. Each table runs the existing recall pipeline. When multiple live tables participate, PLUR1BUS waits for all of them and performs one stable global score merge; the one-table path remains direct. Duplicate IDs and canonical heading/text are collapsed, canonical plus memory results share the configured output cap, and child decision traces are replayed through the existing trace caps. A namespace changes storage routing for the current agent only. Sharing between agents, workspaces, or users is separate ACL work owned by B13.
Chat models are selected per owning feature. If an optional feature model is
absent, PLUR1BUS uses the effective OpenClaw agent model and sends no model
property. Features never inherit merging.model, its endpoint, credential, or
headers. Existing feature/profile activation, budgets, confirmation gates,
rate limits, and fail-soft behavior remain unchanged; Safe produces zero
PLUR1BUS native/direct chat calls.
The four selection modes are openclaw-default (native with no model),
openclaw-override (feature-local model through OpenClaw), direct-override
(feature-local model plus direct transport), and unavailable. failed is the
stable diagnostic outcome when a selected transport rejects. Provider/model
metadata returned by OpenClaw may be recorded without credentials, prompts, or
headers. Native routes bypass the PLUR1BUS result cache; complete direct routes
retain exact caching.
Direct transport without a feature-local model fails closed and sends no
request. A configured credential that is unresolved is unavailable; it never
falls through to native OpenClaw host credentials and does not abort plugin
registration. runtime.llm.complete missing or unavailable is fail-soft and
does not select a hard-coded model.
A session-bound command capability omits agentId. Global hook, tool, and
background calls retain the target agent and require entry-level
llm.allowAgentIdOverride:true. A model-only native override requires
llm.allowModelOverride:true and obeys allowedModels. Installer preserve
never grants LLM trust, and neither Safe nor Recommended adds those entry-level
bits.
runtime.llm.complete resolves the effective primary selection and does not
execute the configured model fallback array in the installed runtime. PLUR1BUS
neither claims nor emulates a host fallback chain.
PLUR1BUS caches only exact, agent-scoped results from an explicit allowlist of deterministic internal LLM transformations. The default in-memory cache uses a 24-hour absolute TTL (llmResultCacheTtlMs: 86400000, clamped to 60 s–7 d) and holds 256 entries per plugin registration (llmResultCacheMaxEntries, clamped to at most 10,000). Optional prompt-free SQLite persistence is off by default; when enabled with llmResultCachePersist, it stores hashed keys, results, usage metadata, and timestamps under the memory database path without storing plaintext prompts, credentials, or headers. llmResultCacheMaxBytes defaults to 67,108,864 bytes and is clamped to at most 1 GiB; clamped values log a warning.
The six runtime settings are llmResultCacheEnabled (default true), llmResultCacheTtlMs (default 86400000), llmResultCacheMaxEntries (default 256), llmResultCachePersist (default false), llmResultCacheMaxBytes (default 67108864), and llmResultCacheMetrics (default true). Missing values come from the manifest; an explicit false remains authoritative.
Operational notes:
- Persistence uses the built-in
node:sqlitemodule available throughout the supported Node.js runtime range; if SQLite initialization is unavailable, the cache falls back to memory-only. - Persistence stores LLM response text as plaintext (directory
0o700, file0o600under the memory database path). Responses may contain condensed memory content — enable persistence only where that is acceptable. - Integrated call sites send
temperature: 0for determinism, andllm-call.jsnow actually forwardstemperatureto the provider (previously the setting was silently ignored). Existing configs that settemperaturetherefore change their effective provider behavior.
Non-goals and bypasses:
- Ordinary main-chat/model responses and calls with a missing or unknown cache purpose always remain live. That includes weather requests such as
wie wird das Wetter morgen?. - Live or creative wiki, critical classifier/push, dream narrative, dream echo, afterthought, persona voice, and overlay paths are not cached.
- Direct Tier-3 API-client calls and emotion calls without a real agent scope are not cached.
- The cache does not perform semantic matching, share results across agents, cache rejected upstream calls, or replace provider-side prompt caching.
The /state status section reports cache hit rate, memory/persistent hits, persistence state, and avoided input/output tokens. It intentionally reports token counts, not money.
emotion.t3 — the tier-3 emotion classifier uses the effective OpenClaw
agent model when its model is absent. A complete feature-local direct override
may instead provide its own model and transport. If neither route is available,
the classifier falls back to Tier-2 heuristics: it does not label cards, so
it never poisons results by marking everything fakt.
emotion.temperaments — per-agent emotional temperament. Ships with generic defaults only (main slightly more sensitive, everyone else balanced). Pick a preset via /plur1bus temperament <preset> (ausgewogen, warm, kühl, feurig, stoisch) — requires a gateway restart. Mood always derives from conversation content; the temperament only shapes how strongly and how long it swings. The current mood is written to .emotional-state.json (machine-readable, survives restarts) and .current-mood.txt (human-readable) in the agent workspace, injected as a mood line into the recall context, stamped on every memory card (moodContextAtCapture), and emotionally intense memories decay slower (intensityHalfLifeFactor).
security.allowedUserIds / security.allowedChatIds — identity-aware authorization for commands and destructive flows.
- If both lists are empty, non-destructive commands can run in private 1:1 contexts; destructive commands are denied in groups/unknown channels.
- If either list is configured, destructive commands require
userIdmembership inallowedUserIds(chatId alone is never sufficient), plusallowedChatIdswhen that list exists. - Whitelists remain stable with
/enable,/disable,/plur1bus setup,/forget,/correctand confirmation flows.
security.allowChatConfigCommands (default true) — disables operator-level config mutating commands (/enable, /disable, /plur1bus setup) when set to false. Use this in shared channels if you want a hard stop on chat-driven writes. Writes are still guarded by a file lock.
security.allowModelDestructiveMemoryOps (default true) — keeps model-facing tools memory_forget and knowledge_update available unless you explicitly disable them.
scope values now support agent-private (default), workspace and user.
agent-privateremains per-agent.workspaceshares by workspace.useris owner-bound: der aufrufendeuserIdwird gespeichert und bei Sichtbarkeit/Mutation geprüft.
/share <id> kopiert eine sichtbare Karte nach bestätigter, an Benutzer und
Chat gebundener Bestätigung in den Workspace-Pool. /share <id> --user nutzt
dieselbe Bestätigung, erzeugt aber einen nur für denselben Kanal, Account und
Benutzer sichtbaren User-Pool. Die Grammatik ist strikt: nur ein vollständiges
UUID-id, optional genau --user, oder /share confirm <nonce> sind gültig;
unbekannte oder doppelte Optionen werden vor jedem Store-, DB-, Embedding- oder
Provider-Zugriff abgelehnt. Eine Freigabe ist copy, never move: die private
Ursprungskarte bleibt unverändert, und die autorisierte Shared-Kopie enthält
einen kanonischen Origin-Verweis. Recall darf die optionalen Shared-Quellen
ergänzend lesen und dedupliziert den kanonischen Ursprung; sie ersetzen weder
primären Recall noch dessen ACL.
Physische Routen sind kein benutzergesteuerter Pfad: ihre Segmente sind höchstens
64 Zeichen lang und werden als .plur1bus-shared/workspaces/w-<62hex> oder
.plur1bus-shared/users/u-<62hex> abgelegt. Die Berechtigung bindet den
kanonischen Workspace konfliktablehnend (keine versteckte Alias-Priorität) und
den vollständigen Kanal+Account+Benutzer-Prinzipal. Fehlende oder abweichende
Bindungen sind nicht sichtbar und nicht mutierbar; fehlend und verweigert
werden gleich behandelt. /memory und /share --user verwenden den direkt
vom Host gelieferten Account.
Der aktuelle OpenClaw-Hook kann die optionale automatische User-Shared-Recall
Quelle ausschließlich bei aktiviertem autoRecall verwenden. Er benötigt
einen account-tragenden Session-Key, ein exaktes Host-Run-Ticket oder eine
konservative default-only Account-Topologie. Native und Slash-Kommandos prägen
absichtlich kein Route-Ticket, weil behandelte Kommandos den Prompt-Hook nicht
erreichen. Bei mehrdeutigen benannten/multi-account Main-, Group- oder
Channel-Turns wird nur diese optionale Quelle ausgelassen; andere Recall-Quellen
bleiben unberührt. Ein zuletzt gespeicherter Session-Route-Wert ist kein
turn-gebundener Account-Beweis.
Legacy rows that used the old workspace_shared scope remain in their
authoritative private table until an operator explicitly migrates them. Start
with the non-mutating audit:
/plur1bus migrate-legacy-shared
Use --report <name.json> for a fixed private report name, and resume a bounded
dry run with the opaque --cursor <token> returned by the previous run. After
reviewing the report, run --apply without a dry-run cursor; apply re-reads each
source row, writes and verifies an idempotent workspace copy, and only then
marks the legacy source. The command never deletes or re-scopes the source row:
workspace_shared legacy rows are not reinterpreted. The operation is bounded
per run to 250 rows, 4 MiB source bytes, 100 provider calls, and 60 seconds.
The opaque cursor pins source versions and dry-run mode; an unavailable or
changed pinned version, mode mismatch, checksum/binding failure, timeout, or
uncertain commit aborts the run and requires the documented continuation or a
restart without the cursor. Apply never accepts a dry-run cursor.
It is operator-destructive, so it requires the same user authorization as
/forget; cron identity does not bypass that gate. Reports are no-clobber
0600 JSON files below .plur1bus/migrations/ and exclude memory content,
vectors, evidence, and provenance.
The migration runs only through the destructively authorized initialized runtime command; there is no standalone DB/config/credential bootstrap. Multi-Namespace, Neo/Obsidian aliases, Semantic Lens, CRR, the OpenClaw default LLM, and per-agent credentials do not change under sharing or migration.
security.allowModelDestructiveMemoryOps (default true) — the model-facing tools memory_forget and knowledge_update mutate persistent memory/knowledge state. Set this flag to false if you want a hard opt-out for model-driven destructive memory writes.
Core memory (capture, recall, search) works from manifest-safe defaults without profile confirmation. Argument-less setup only lists the choices, and start is read-only status/onboarding guidance:
# In Telegram
/plur1bus setup
/plur1bus startApply a profile only by naming it explicitly:
/plur1bus setup safe
/plur1bus setup recommendedAn explicit selection records setupProfile and featuresConfirmedAt. Recommended enables additional features while retaining merge and Obsidian safety gates; vault discovery alone never counts as confirmation.
LanceDB is the authoritative store: every memory card lives there first, indexed per agent for isolation. The Obsidian bridge mirrors cards into a Markdown vault so the user can read, link, and edit them with normal tools; LanceDB stays the source of truth and the bridge re-syncs on changes.
A daily consolidation job detects duplicates and generates merge proposals (never auto-applies). A critical-push classifier (run via the OpenClaw-managed cron as the exact command /plur1bus internal classify-recent) labels recently captured cards by sensitive entity type (person, relationship, birthday, money/account, health, access/password) using the configured chat model, and — when a per-agent daily threshold (maxPerDay) is not yet exceeded — emits a short confirmation message per critical card. The plugin SDK currently exposes no outbound send API, so the command handler converts returned pushMessages directly into the cron reply. The installed host patch passes that complete reply, including confirmation buttons, into OpenClaw's normal finalization/delivery path and returns before the carrier-agent model executor. Multiple push texts are combined in their original order; partial classifier failures are reported alongside successfully produced pushes. The per-day counter is enforced across runs, and each card is classified exactly once, so no card is pushed twice.
The recall pipeline runs embedding → LanceDB vector search → optional query refinement → temporal filter → canonical KNOWLEDGE.md search → score/status processing → graph spread and hydration → budget allocation → optional rerank → deduplication → ACL filtering → finalization. The caller may then append bounded Semantic Lens and Conversation Reactivation Recall results; neither replaces the primary recall.
npm install
npm test # node --test, 1,931 testsNo build step. ESM-only. Tests are unit-level and DB-free; the LanceDB adapter is mocked behind a thin interface.
Recalled memories are rendered as historical evidence, not as current user requests. A memory that contains an old imperative such as a download, send, write, delete, install, purchase, network action, or command must not trigger that action unless the current visible user turn asks for the same action.
The recall block uses escaped metadata attributes and wraps recalled text in quoted-evidence elements, so prompt boundaries stay explicit even when old memory text contains tool-like markup.
Version 6.x is a major upgrade. If you ran 5.x:
- Schema migration — LanceDB table schema is auto-migrated on first
init(). New columns:status,versionNumber,previousVersion,supersededBy,updateSource,updateEvidence,reconsolidationConfidence,versionCreatedAt,updatedAt. Migration is idempotent and non-destructive. - Explicit profile selection — Missing values use manifest-safe defaults. Use
/plur1bus setup safeor/plur1bus setup recommendedonly when you intentionally want to persist a profile;/plur1bus setupand/plur1bus startare non-mutating. - Merging is proposal-only —
merging.autoApplydefaults tofalse. Merge candidates are written tomerge-proposals.jsonlinstead of being applied automatically. SetautoApply: trueto restore 5.x behavior. - Obsidian bridge apply mode — New
mode: "apply"with safety gates (backups, audit log, vault path confirmation). Default ismode: "augment"(read-only). Confirm vault path explicitly before first write. - Command input handling — Hard length limits removed. Very long inputs are semantically compressed; beyond 100k chars use a file or vault source.
- Config keys added —
reranker.timeoutMs,reranker.fallbackOnError,merging.autoApply,merging.mode,obsidianBridge.backupBeforeApply,obsidianBridge.auditLog,obsidianBridge.requireVaultPathConfirmation,obsidianBridge.morningReview.status,obsidianBridge.eveningReview.status,emotion.tier,emotion.t2.enabled,emotion.t3.enabled,emotion.t3.model,emotion.t3.apiKey,emotion.t3.escalationConfidence,emotion.t3.timeoutMs,emotion.moodInfluence,emotion.intensityHalfLifeFactor,emotion.temperaments.<agentId>.
See v5_TO_v6_MIGRATION.md for the full migration guide.
MIT — see LICENSE.