You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Professor Mari has no persistent memory of a user's preferences across sessions. Every new conversation, the user re-explains the same things: how they like lorebooks and character cards formatted, their naming/workflow conventions, and how eager (or cautious) they want Mari to be when making changes.
Two concrete gaps:
Preferences don't persist. "I always want lorebook entries keyed on both the character name and their nickname," "structure my cards personality-first," etc. — the user has to restate these every time.
Constraint: users pay for their own model usage, so whatever we build must be token-efficient — it can't dump a pile of stored text into every prompt, and irrelevant stored memories must not dilute/poison the context.
Proposed solution
A persistent, per-install store of user "instructions/memories" (markdown), with retrieval rather than always-on injection. Scoped as v1 below; embeddings/scale left for later.
Two entry paths (both in v1):
User-deposited — the user authors/uploads memory entries (reusing the existing .md upload surface Mari already has for Skills).
Mari-authored — a new instructions.remember / instructions.forget app-data action so "remember that I…" persists a memory. The write is surfaced through the existing Keep/Restore review card (exact text shown before it persists), so a self-written memory is never invisible.
Retrieval — index-and-fetch (token-efficient):
Always inject only a compact index of available memories — title + one-line description + id — not their bodies.
Mari evaluates the index against the current task/turn and pulls a full memory with a new instructions.get <id> read-action only when it's relevant. Irrelevant memories cost ~nothing and can't poison the turn.
pinned escape hatch: a memory may opt to always inject its body. Reserved for the rare critical behavioral directive that can't risk a fetch-miss — not the default.
Chosen over pure semantic retrieval because the headline use case ("when I ask how, act instead of just explaining") is a behavioral directive whose trigger is a pattern of interaction, not content overlap — embeddings structurally under-retrieve exactly those. Model-driven relevance over the index catches both behavioral and reference memories because Mari reasons rather than vector-matches.
Precedence:
Injected memory is framed to take precedence over Mari's default behavior where the two conflict (e.g. a memory can re-enable "act on how-to questions" for a user who wants it).
This is prompt-level deference only. It does not alter any code-enforced safety gate: the Keep/Restore card still renders on every edit, and the hard pre-approval gate for sensitive files / dependency installs is untouched and non-overridable.
Architecture (grounded in the current code):
A dedicated file-native table so writes flow through the existing mutation + Keep/Restore pipeline (executeMutation → createAppliedReview) — free undo, audit, and journaling, zero changes to the pipeline.
Injected via a new sibling system block next to the Skills block in buildPromptMessages() (workspace-agent.service.ts), modeled directly on the shipped Professor Mari Custom Skills system, which already does file-backed markdown → per-turn prompt injection.
Targets the Home workspace agent (the runtime that owns edit/approval behavior), not conversation-mode Mari.
Safety: Mari persists a memory only in response to a genuine user instruction, never as a reflex to content she just read — so a shared character / lorebook / preset can't silently plant a standing instruction (the one real injection vector a first-class self-write tool would otherwise open).
Alternatives considered
Always-on injection (clone Skills exactly). Rejected — wastes tokens every turn and lets irrelevant memories dilute context. (This was my first instinct; the token cost killed it.)
Pure semantic / embedding retrieval. Good for reference memories, but structurally weak for behavioral directives (interactional trigger, not content similarity) and a miss is silent. Kept as a v2 scale option: semantically rank the index to a top-N shortlist that Mari then reasons over — semantic in the role it's actually good at (narrowing candidates), model still making the behavioral call.
Literal keyword triggers (lorebook-style). Brittle; forces the user to predict trigger words for every memory.
Reusing the loose-file Skills store directly for self-writes. Rejected — Skills writes bypass review/undo, and the skills write-route resets Mari's session on write.
A single JSON settings blob. Rejected — coarse, clobber-prone undo vs. per-entry diffs on a dedicated table.
Additional context
Naming. The code identifier must avoid the memory_* namespace — "memory" already means four different things in the engine (conversation-RAG memory_chunks, the "Important Memories" prompt block, character scene memories, conversation_notes). Proposed: mari_instructions table / instructions.* actions / <professor_mari_instructions> block. User-facing label TBD (bikesheddable).
Out of scope for v1 (future): semantic-ranked index at scale; per-chat vs. global scoping nuance; embedding auto-retrieval.
Maintainer decisions requested before implementation:
OK to let memory carry behavioral-precedence directives that re-enable "edit without asking"-style behavior, as an explicit user opt-in (prompt-level, still Keep/Restore-reversible)?
Preferred naming.
Global vs. per-chat scope for v1.
I've done a full feasibility pass over the relevant subsystems (prompt assembly, storage, the write/review path, existing precedents, and the security/precedence model) and am happy to implement v1 once scope is signed off. Can share the detailed writeup on request.
Template check
Please uncheck (untick) the box below before submitting so we know you read the template. It is intentionally pre-checked:
I DID NOT read this template and provide the requested details.
What problem does this solve?
Professor Mari has no persistent memory of a user's preferences across sessions. Every new conversation, the user re-explains the same things: how they like lorebooks and character cards formatted, their naming/workflow conventions, and how eager (or cautious) they want Mari to be when making changes.
Two concrete gaps:
Constraint: users pay for their own model usage, so whatever we build must be token-efficient — it can't dump a pile of stored text into every prompt, and irrelevant stored memories must not dilute/poison the context.
Proposed solution
A persistent, per-install store of user "instructions/memories" (markdown), with retrieval rather than always-on injection. Scoped as v1 below; embeddings/scale left for later.
Two entry paths (both in v1):
.mdupload surface Mari already has for Skills).instructions.remember/instructions.forgetapp-data action so "remember that I…" persists a memory. The write is surfaced through the existing Keep/Restore review card (exact text shown before it persists), so a self-written memory is never invisible.Retrieval — index-and-fetch (token-efficient):
instructions.get <id>read-action only when it's relevant. Irrelevant memories cost ~nothing and can't poison the turn.pinnedescape hatch: a memory may opt to always inject its body. Reserved for the rare critical behavioral directive that can't risk a fetch-miss — not the default.Precedence:
Architecture (grounded in the current code):
executeMutation→createAppliedReview) — free undo, audit, and journaling, zero changes to the pipeline.buildPromptMessages()(workspace-agent.service.ts), modeled directly on the shipped Professor Mari Custom Skills system, which already does file-backed markdown → per-turn prompt injection.Safety: Mari persists a memory only in response to a genuine user instruction, never as a reflex to content she just read — so a shared character / lorebook / preset can't silently plant a standing instruction (the one real injection vector a first-class self-write tool would otherwise open).
Alternatives considered
Additional context
memory_*namespace — "memory" already means four different things in the engine (conversation-RAGmemory_chunks, the "Important Memories" prompt block, character scene memories,conversation_notes). Proposed:mari_instructionstable /instructions.*actions /<professor_mari_instructions>block. User-facing label TBD (bikesheddable).Template check
Please uncheck (untick) the box below before submitting so we know you read the template. It is intentionally pre-checked: