Skip to content

The API surface

Five methods cover ingesting and asking. Everything else this project claims — contradiction, causality, the trust ladder, the memory dynamics — lives on m.session, which is public and is the same object Memory is built on. A feature with no documented entry point is not a feature.

Memory

m = Memory("mind.lmm",
           persona="You are Ada, a warm onboarding coach.",   # the VOICE
           style="One section per course: name, duration, outcomes.",  # the FORMAT
           warmth=0.6,          # temperature of the voice surfaces
           reply_tokens=1200)   # length cap of the voice surfaces

The operator's knobs, each travelling exactly where it belongs — and none of them reaching a verifier, because a judge whose thermostat the caller can turn is not a judge:

  • persona — the voice. Rides in front of the phrasing prompts (chat, answer, refusal) and stops at the document's edge: the composer never sees it.
  • style — the document's shape, the persona's mirror twin. Travels ONLY to the composer's request; headings and ordering are the operator's, every fact beneath them is still the material's.
  • warmth / reply_tokens — temperature and length of the same voice surfaces. Unset, every surface keeps its measured default.
call what it does engine?
m.learn(what) teach it a file or a string no engine for tables
m.ask(q, explain=True) answer, with .sources and .abstainedcannot write memory engine
m.compose(brief, topics=, on_line=) a structured draft from the evidence — per-topic gathering, gated line by line, streamed to on_line as lines survive, returned with its sources engine
m.where(term) which documents mention this — names and counts, the census no engine
m.about(label) the records held on a concept no engine
m.facts how many records exist no engine
m.save(path) graph and evidence, both no engine

Session

call what it does engine?
m.session.respond(msg, teach=True, on_line=) a conversational turn at operator trust — the surface that may teach engine
m.session.respond(msg, teach=False) the CONSULTATION surface — statements are context, questions search the whole conversation, a delivery request routes to the composer; cannot write memory engine
m.session.learn_rows(rows) [{column: value}] straight to the graph no engine
m.session.learn_cause(a, b) record that a causes b no engine
m.session.root_causes(x) walk the causal chain back no engine
m.session.causes_of(x) / .effects_of(x) one step either way no engine
m.session.tension() the contradictions it is holding no engine
m.session.curiosity() what it has been asked and cannot answer no engine
m.session.sleep() fade, reinforce, settle episodic into semantic no engine
m.session.verdict(old, new) arbitrate two rival values engine

A record is a core.memory.Record: .subject, .predicate, .value are concept keys, not strings — one spelling can be two entities, one entity can carry labels in several languages. Read labels through m.session.memory.identities. .sources and .trust are the provenance the gate reads on the way out.

The consultation surface

respond(msg, teach=False) is the customer-facing conversation — it can never write into the operator's memory, and four behaviours exist only there:

  • a statement ("we are a bank, team of ten") is context: it routes to the chat voice, and its terms accumulate in the consultation's brief;
  • a question searches with the whole consultation riding along — "the best three-hour material" still knows the topic named two turns earlier;
  • a delivery request ("you decide, put a programme together") goes straight to the composer and returns a source-stamped catalogue built from the brief;
  • echoing the user's own words back is conversation, not assertion — the gate lets a consultant repeat what the customer just said, while a word the customer never said still answers to the graph.

Pass on_line= to respond or compose and the draft streams: each line is judged the moment its newline arrives and handed to the callback while the engine still writes. A refused line is never seen; a backend that cannot stream degrades to batch by itself.

The no engine column is not a footnote. Those calls are plain Python over a dict — microseconds, no network, no key — which is why a spreadsheet loads in milliseconds and why the reasoning half of this system costs nothing to run.

Over HTTP, and in other runtimes

python -m lmm.serve --root ./stores exposes /ask, /learn, /compose, /where and /health, one memory per user, with the abstention and the source stamps intact on the wire. lmm.adapters.langchain offers a stamped retriever and an agent tool that returns audited answers; sdk/typescript is a dependency-free client whose ask resolves to the same four fields as the Answer object below. See Serving and embedding.

Answer object

ask(..., explain=True) returns a string that additionally carries what the turn knows about itself:

attribute meaning
.abstained did this turn assert anything — the structural stamp, in any language
.sources the provenance stamps the answer rests on
.subject the subject label the turn was about
.from_graph answered by the graph alone (zero model calls)