Memoosea dual-path memory system for proactive agents

Source on GitHub

Tools

The deterministic half of Memoose, reachable two ways: as a shell command, or as a tool call on any MCP host. Same engine, same store, same payloads.

The CLI

Prefer this where a shell is available. An MCP server puts its tool schemas in the model’s context on every turn whether or not memory is touched (about 4,250 tokens here, measured), while a command costs nothing until it is run. memoose --help and memoose <command> --help list everything; memoose status prints the invocation for this machine when the binary is not on PATH.

commanddoes
memoose recall "who owns billing"Search memory. --mode, --limit, --hops, --superseded, --no-user
memoose remember "bao:Person --owns--> auth:System"Store a fact. --desc, -e/--evidence, --valid-from, --summary; --stdin takes the full JSON payload. Between two Procedures the fact is a transition: --when, --do, --avoid
memoose guidance "run the test suite"What memory says comes next from a Procedure: its outgoing transitions two hops out, with condition, advice, pitfall and how past runs ended. Memory, not an instruction
memoose history auth-serviceThe provenance ledger for an entity or a fact
memoose contradictions [names]Hotspots and open contradictions to judge
memoose ontologyEntity types, functional relations, store stats
memoose datasets · memoose contextMemory scopes on this machine · the global-context buckets
memoose session start|turn|context|get|timeline|lessons|endSession lifecycle. turn --at <Procedure> declares your position and prints the guidance from there; end --outcome succeeded|failed|abandoned counts the outcome on every transition the session took
memoose maintainThe periodic pass: hotspots, open contradictions, duplicate names, missing summaries and undistilled sessions, in one worklist
memoose dismiss <key> --reason "..."Decline a candidate from maintain or contradictions so it is not proposed again; the reason is shown next time
memoose viewThe knowledge graph in your browser as one self-contained HTML file: colour is the entity type, a diamond is a Procedure, click a node for its facts. --superseded draws history dashed
memoose forget --entity XDelete an entity, a fact, a session (--all for the dataset)
memoose tool <name> --stdinAny remaining tool, keyword arguments as JSON on stdin

A fact is written source[:Type] --relation_name--> target[:Type]. The :Type declares an entity Memoose has not seen; leave it off for one it knows and the endpoint is resolved, or rejected with a message saying so. Output is compact text, --json returns the exact payload the MCP tool would, and anything longer than --max-inline (2000 characters) is written to a file whose path is printed instead. A failed command exits non-zero and explains what to fix on stderr.

The MCP tools

Started with memoose serve, which install wires into the host. Use these where the shell is restricted, or where a tool UI is wanted.

Every tool takes an optional dataset. Omit it and Memoose uses the dataset for the directory the host launched the server in. Pass "user" for facts that hold across every project. See scopes.

Ontology

Call describe_ontology once per session before writing: extraction is constrained by the types it returns, and a write against an unknown type is rejected with a message telling the model which type to use instead.

describe_ontology(dataset?)
Entity types, functional relations, imported ontologies, and store stats for a dataset.
add_entity_type(name, description, parent?, aliases?, dataset?)
Add a type when nothing in describe_ontology fits. PascalCase name; an optional parent collapses onto a basic type.
import_ontology(text, name?, format?, dataset?)
Import an OWL/RDF/Turtle ontology as text. Classes become entity types with parents collapsing onto basic types; labels become aliases.
declare_functional_relations(names, dataset?)
Declare relation names that hold a single current value per subject, such as owned_by, deployed_in or current_owner. New assertions then supersede older ones automatically, and nothing is deleted.

Write

remember(entities, relations?, summary?, source_text?, source?, session_id?, dataset?)
The main write. Stores memory as a typed graph: entities (name, type, description) and relations (source --name--> target, a one-sentence description, evidence, optional valid_from/valid_to). Pass source_text and a summary so recall can find it lexically. It validates against the ontology, merges entities by name, supersedes functional relations, records provenance, and warns about hotspots that may be contradictions.
mark_contradiction(first_relation_id, second_relation_id, reason, confidence?, dataset?)
Record that two stored facts cannot both be true, adding a contradicts edge between their subjects. Use supersede instead when the newer fact simply replaces the older in time.
supersede(old_relation_id, new_relation_id, reason, dataset?)
Mark an older fact as replaced by a newer one. The old fact leaves default recall but stays in history.
merge_entities(keep, drop, dataset?)
Merge two entities that denote the same thing. Relations and chunks move to keep; drop is removed and recorded as an alias.
cross_connect(relations, dataset?)
Add relations between existing entities proposed by memify_candidates("cross_connect").
set_bucket_summary(bucket_id, summary, dataset?)
Write the summary for a global-context bucket returned by memify_candidates("stale_summaries").
forget(entity?, relation_id?, session_id?, dataset?, whole_dataset?)
Remove an entity and its relations by exact name, a relation by id, a session, or a whole dataset. Prefer supersede for anything that was true once, and confirm with the user first.

Read

recall(query, mode?, limit?, datasets?, include_superseded?, hops?, include_user?)
Searches the project dataset and then the user dataset, and returns ranked raw material for the model to synthesise: entities, facts with their evidence, validity and superseded/contested flags, and chunks. Without mode, a regex router picks one.
guidance(procedure, hops?, per_hop?, dataset?)
The outgoing transitions of a Procedure two hops out, grouped by hop, each with condition, advice, pitfall and how past sessions that took it ended. Raw and local; you decide. Superseded transitions are excluded and declined changes to these transitions are listed.
contradiction_candidates(entity_names?, relation_ids?, dataset?)
Facts around given entities or relations, grouped by subject, with hotspots where one subject holds several values for one relation. Judge them with the memoose-upkeep skill.
history(entity?, relation_id?, limit?, dataset?)
The provenance ledger: every create, merge, assert, supersede and forget, with actor and time.
memify_candidates(kind, limit?, dataset?)
Maintenance proposals. cross_connect: entities that co-occur without a relation. consolidate: near-duplicate names. stale_summaries: global-context buckets needing a summary.
global_context(limit?, dataset?)
One bucket per entity type with its summary, and how many are stale.
list_datasets()
The memory scopes on this machine, the default for this project, and the user-global dataset.

recall modes

ModeAnswers
hybridDefault. Lexical and vector channels over chunks, entities and facts, fused by reciprocal rank.
factsRelations about the entities in the query.
neighbourhoodWhat sits around an entity, out to hops.
lexicalAn exact quoted phrase.
summariesBucket and chunk summaries rather than raw facts.
temporalWhat was true when, including validity ranges.
rulesStanding rules, conventions and preferences.
sessionMaterial from sessions and their published lessons.

Pass include_superseded=true to see facts that used to be true alongside the current ones. See Evidence & history.

Sessions

A session is the unit Memoose distils lessons from: turns go into a fast cache, typed context sections accumulate during the work, and at the end the timeline is packed into batches for the model to judge.

session_start(session_id?, dataset?)
Start or resume a session. Returns the standing context to load before work: goals, rules, preferences and lessons.
session_add_turn(session_id, role, text, position?, dataset?)
Append a turn (user, assistant, tool, system) to the session's fast cache. With position, the Procedure you are at, the reply carries the guidance from there and the session's trace grows by one step.
session_set_context(session_id, section, content, confidence?, retire_entry_id?, dataset?)
Write a typed context section (a goal, a rule, a preference) during the work, and retire an entry that no longer holds.
session_get(session_id, sections?, include_turns?, dataset?)
Read a session: turns and context entries, optionally filtered by section.
session_timeline(session_id, batch_chars?, dataset?)
Pack a session into batches for distillation, with prior lessons and the curator/writer rules. Judge them, then call publish_lessons.
publish_lessons(lessons, session_id?, dataset?)
Persist accepted lessons as Lesson entities linked to what they apply to, and mark the session distilled.
session_end(session_id, outcome?, dataset?)
Close a session with its outcome (succeeded, failed, abandoned). Every transition the trace traversed counts it. Returns the trace, what to distil from it, and whether lessons are still owed.

Errors teach. A rejected write returns a message written for the model, saying which type to use and which relation name, because tool errors are the only lever Memoose has on extraction quality.