Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content
Build with MuBit

SDK Helpers

Explicit helper methods for memory, context assembly, and the learning loop — when you outgrow the mubit.learn drop-in.

The mubit.learn drop-in is the right choice for most readers. Use the helpers below when you need explicit control over what gets stored, when, and under which session/agent identity.

Helper map

MethodPurposeWhen to reach for it
remember()Default write path for a single logical memory itemStoring facts, lessons, or observations
recall()Answer-oriented retrieval (returns a synthesized final_answer plus evidence and citations)Asking the memory a question
get_context()Assemble a token-budgeted context block to inject into your next LLM callBefore any prompt where memory matters
archive()Store an exact artifact with a stable reference_idAnything you'll need recovered byte-for-byte later
dereference()Fetch the exact content for a reference_idRecover an archived artifact
reflect()Extract reusable lessons from session evidenceEnd of a run/session, or on demand
lessons()List lessons with optional filteringAudit, debugging, surfacing strategies
checkpoint()Snapshot memory state with a labelBefore compaction or risky transitions
record_outcome()Tag a reference_id (and any contributing entry_ids) with success / failure and a rationaleRL-style reinforcement signal

Minimal usage

getting_started.py
import os
from mubit import Client
 
run_id = "support:acme:ticket-42"
client = Client(
    api_key=os.environ["MUBIT_API_KEY"],
    run_id=run_id,
    transport=os.getenv("MUBIT_TRANSPORT", "auto"),
)
 
client.remember(
    session_id=run_id,
    agent_id="support-agent",
    content="Customer Taylor prefers concise Friday updates.",
    intent="fact",
    metadata={"customer": "taylor", "source": "quickstart"},
)
 
answer = client.recall(
    session_id=run_id,
    query="What update style does Taylor want?",
    entry_types=["fact", "lesson", "rule"],
)
 
context = client.get_context(
    session_id=run_id,
    query="Draft the next customer update.",
    mode="summary",
    max_token_budget=300,
)
 
print(answer["final_answer"])
print(context["section_summaries"])

The recall() (and query()) response includes a citations array — 0-based indices into evidence marking which items grounded final_answer (empty when the answer cites no specific evidence).

Cross-session recall

recall() queries are scoped to the session by default. To read memory from a different session for the same user:

  • Store the memory as a lesson with lesson_scope="global".
  • On recall, pass the same user_id and entry_types=["lesson"].
client.remember(
    session_id="s1", agent_id="support-agent", user_id="taylor-1",
    content="Taylor prefers concise written updates on Friday afternoons.",
    intent="lesson", lesson_scope="global",
)
 
# Different session, same user_id — recall returns the lesson.
client.recall(
    session_id="s2", agent_id="support-agent", user_id="taylor-1",
    query="how does Taylor like updates?",
    entry_types=["lesson"],
)

intent="fact" memories are session-local even if user_id matches. This trips up almost everyone the first time — call it out in your design doc.

Context modes

get_context(mode=...) returns different shapes:

ModeReturnsUse when
"full"Single concatenated context_block stringYou want to drop the result straight into a system message
"summary"section_summaries[] with top_item_preview per sectionYou want to render structured context (e.g., a card UI)
"sectioned"Sections + per-section textYou want to interleave sections with your own prose

max_token_budget is enforced after assembly. If the budget is too small, the lowest-score evidence is dropped first.

Exact references

archive() and dereference() are the exact-recovery pair. Use them for anything semantic recall is the wrong tool for — original diffs, raw tool outputs, generated SQL you'll re-execute later.

archived = client.archive(
    session_id=run_id,
    agent_id="support-agent",
    content="Original billing diff and remediation note",
    artifact_kind="billing_postmortem",
    labels=["billing", "exact"],
)
 
# Later — possibly in a different session — fetch the exact content back.
exact = client.dereference(
    session_id=run_id,
    reference_id=archived["reference_id"],
)

archive() requires the archive_block write scope; dereference() requires the matching read scope. Register your agent with both if it needs to round-trip artifacts.

Reflection and outcomes

ref = client.reflect(session_id=run_id)
for L in ref["lessons"]:
    print(f"[{L['lesson_type']}] {L['content']}")
 
client.record_outcome(
    session_id=run_id,
    reference_id="ticket-42",
    outcome="success",
    rationale="Customer confirmed the SSO bypass resolved the ticket.",
    entry_ids=["entry-7f3", "entry-9a1"],
)

reflect() extracts new lessons from the session's traces. record_outcome() is the reinforcement signal — recurring success lessons get promoted from run-scoped to session-scoped to global.

Pass entry_ids to attribute the outcome to every recalled entry that contributed, not just the primary reference_id (which is never double-counted). List each contributing entry — for example the evidence items that citations flagged as grounding the answer you acted on.

When to drop down to client.* raw methods

Reach for client.control.* only when you need:

  • Async ingest with explicit job polling (control.ingest + control.get_ingest_job).
  • Raw wire payloads for tooling/observability that needs the full response shape.
  • Direct access to core.* lanes (search, scratch, branching) that the helpers wrap.

Most application code never needs this layer. See the Control HTTP reference for the full surface.