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
| Method | Purpose | When to reach for it |
|---|---|---|
remember() | Default write path for a single logical memory item | Storing 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 call | Before any prompt where memory matters |
archive() | Store an exact artifact with a stable reference_id | Anything you'll need recovered byte-for-byte later |
dereference() | Fetch the exact content for a reference_id | Recover an archived artifact |
reflect() | Extract reusable lessons from session evidence | End of a run/session, or on demand |
lessons() | List lessons with optional filtering | Audit, debugging, surfacing strategies |
checkpoint() | Snapshot memory state with a label | Before compaction or risky transitions |
record_outcome() | Tag a reference_id (and any contributing entry_ids) with success / failure and a rationale | RL-style reinforcement signal |
Minimal usage
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_idandentry_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:
| Mode | Returns | Use when |
|---|---|---|
"full" | Single concatenated context_block string | You want to drop the result straight into a system message |
"summary" | section_summaries[] with top_item_preview per section | You want to render structured context (e.g., a card UI) |
"sectioned" | Sections + per-section text | You 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.