AutoGen Integration
Attach Mubit as an AutoGen Memory provider. Recall is injected before every model turn; outcomes credit the exact memories that helped.
The mubit-autogen adapter exposes two integration surfaces:
MubitMemory— an implementation ofautogen_core.memory.Memory, so it attaches directly to anAssistantAgent(memory=[...]). AutoGen callsupdate_context()before each model turn: Mubit recalls relevant context and injects it as aSystemMessage, and new assistant/user content is persisted viaadd().MubitGroupChatHook— forwards multi-agent handoff and feedback signals into Mubit so team activity is queryable alongside memory.
The adapter targets the current AutoGen API — autogen-core / autogen-agentchat 0.7.x (AssistantAgent, autogen_core.memory.Memory). It does not work with the legacy pyautogen 0.2 line (ConversableAgent and friends); migrate to AgentChat first if you are still on 0.2.
pip install "mubit-autogen[autogen]"
# AutoGen over-pins protobuf<6 while mubit-sdk needs >=6.33 — apply after install:
pip install -U "protobuf>=6.33.4"Minimal usage
import asyncio
from autogen_agentchat.agents import AssistantAgent
from autogen_ext.models.openai import OpenAIChatCompletionClient
from mubit_autogen import MubitMemory
memory = MubitMemory(
endpoint="https://api.mubit.ai",
api_key="mbt_...",
session_id="support-1", # the Mubit run that backs this memory
agent_id="support-assistant",
)
agent = AssistantAgent(
name="support",
model_client=OpenAIChatCompletionClient(model="gpt-4o"),
memory=[memory], # Mubit recall is injected before every model turn
)
async def main() -> None:
result = await agent.run(task="Customer says checkout 500s on Safari.")
print(result.messages[-1].content)
asyncio.run(main())What gets captured and injected
- Injected — before each model turn,
update_context()recalls memory relevant to the latest message and appends it to the model context as a singleSystemMessage. Recalled lessons, facts, and prior traces arrive without any prompt plumbing on your side. - Captured —
add()persists content via Mubitremember. User-role content lands with acontextintent, everything else as atrace, unless you setmetadata["intent"]explicitly. Pass a stablemetadata["idempotency_key"]so a retried write is deduplicated server-side instead of double-counting reinforcement. - Attributable — every recalled
MemoryContentkeeps its sourcereference_idinmetadata. Pull those IDs off a query result withextract_entry_ids()and feed them intorecord_outcome(entry_ids=...)so the memories that actually helped get credited. See The learning loop for why this matters.
Reinforcement is explicit, not implicit: the adapter emits no neutral per-reply signal. You close the loop yourself when you know the real outcome.
Cross-session recall
session_id maps to the Mubit run — the memory scope. Reuse the same session_id across processes and days and the agent recalls what earlier sessions stored; use a fresh session_id for isolated memory. clear() deletes the backing run entirely.
Full example: Support assistant with the attribution loop
Recall prior tickets, answer a new one grounded in them, then credit the recalled entries with the real outcome.
import asyncio
import os
from autogen_agentchat.agents import AssistantAgent
from autogen_core.memory import MemoryContent, MemoryMimeType
from autogen_ext.models.openai import OpenAIChatCompletionClient
from mubit_autogen import MubitMemory, extract_entry_ids
NEW_TICKET = (
"Checkout fails with a 500 error on Safari. Works fine in Chrome. "
"I'm on a Pro plan and need to renew today."
)
async def main() -> None:
memory = MubitMemory(
endpoint=os.environ.get("MUBIT_ENDPOINT", "https://api.mubit.ai"),
api_key=os.environ["MUBIT_API_KEY"],
session_id="support-assistant", # stable -> cross-session recall
agent_id="support-assistant",
)
model_client = OpenAIChatCompletionClient(model="gpt-4o-mini")
# 1. RECALL — query directly so we can capture the reference IDs.
# (The same recall is auto-injected into the model context during agent.run.)
recalled = await memory.query(NEW_TICKET, limit=5)
entry_ids = memory.extract_entry_ids(recalled)
# 2. ACT — the attached memory injects recalled context as a SystemMessage.
agent = AssistantAgent(
name="support_assistant",
model_client=model_client,
memory=[memory],
system_message="Use recalled prior tickets to give a concrete resolution.",
)
result = await agent.run(task=NEW_TICKET)
answer = result.messages[-1].content
# Persist the new resolution so future sessions can recall it (idempotent).
await memory.add(MemoryContent(
content=f"[safari-500] Resolution: {answer}",
mime_type=MemoryMimeType.TEXT,
metadata={"intent": "trace", "idempotency_key": "resolution-safari-500"},
))
# 3. RECORD — credit every recalled entry that contributed.
memory.record_step_outcome(
step_id="answer-ticket", step_name="draft-resolution", outcome="success",
)
memory.record_outcome(
outcome="success",
entry_ids=entry_ids, # credit the recalled entries
verified_in_production=True, # boost lessons confirmed in live use
rationale="Resolved the Safari 500 using prior gateway lessons.",
)
await model_client.close()
await memory.close()
asyncio.run(main())On the first run there is nothing to recall yet; on the second, the agent recalls the stored resolution and the reinforced entries rank higher.
Full example: Multi-agent handoffs
Two agents — a researcher and a reviewer — share one Mubit run. MubitGroupChatHook forwards the handoff and the reviewer's verdict into Mubit so they are queryable by diagnose and the MAS surface.
import asyncio
import os
from autogen_agentchat.agents import AssistantAgent
from autogen_ext.models.openai import OpenAIChatCompletionClient
from mubit_autogen import MubitMemory, MubitGroupChatHook
endpoint = os.environ.get("MUBIT_ENDPOINT", "https://api.mubit.ai")
api_key = os.environ["MUBIT_API_KEY"]
SESSION = "autogen-team-1"
researcher_mem = MubitMemory(
endpoint=endpoint, api_key=api_key, session_id=SESSION, agent_id="researcher",
)
reviewer_mem = MubitMemory(
endpoint=endpoint, api_key=api_key, session_id=SESSION, agent_id="reviewer",
)
hook = MubitGroupChatHook(endpoint=endpoint, api_key=api_key, session_id=SESSION)
async def main() -> None:
model_client = OpenAIChatCompletionClient(model="gpt-4o-mini")
researcher = AssistantAgent(
name="researcher", model_client=model_client, memory=[researcher_mem],
)
reviewer = AssistantAgent(
name="reviewer", model_client=model_client, memory=[reviewer_mem],
)
findings = await researcher.run(
task="Investigate why billing discrepancies spiked this week."
)
handoff = hook.emit_handoff(
from_agent_id="researcher", to_agent_id="reviewer",
task_id="billing-review-1",
content=str(findings.messages[-1].content)[:1000],
requested_action="review",
)
review = await reviewer.run(task="Review the researcher's billing findings.")
hook.emit_feedback(
handoff_id=handoff.get("handoff_id", "billing-review-1"),
from_agent_id="reviewer",
verdict="approve",
comments=str(review.messages[-1].content)[:1000],
)
await model_client.close()
asyncio.run(main())Extended Mubit features
Beyond the five Memory methods (update_context, query, add, clear, close), MubitMemory exposes the reinforcement surface:
ids = memory.extract_entry_ids(result, cited_only=False) # reference_ids off a query result
memory.extract_citations(result) # 0-based indices of cited evidence
memory.record_outcome(outcome="success", entry_ids=ids,
verified_in_production=True, rationale="...")
memory.record_step_outcome(step_id="...", step_name="...", outcome="success",
signal=0.8, directive_hint="...")extract_entry_ids accepts a MemoryQueryResult or a raw recall dict; pass cited_only=True to credit only the evidence the answer was grounded in. See step-level outcomes for when per-step credit is worth it.
Configuration
| Parameter | Default | Purpose |
|---|---|---|
endpoint | http://127.0.0.1:3000 | Mubit HTTP endpoint |
api_key | "" | Mubit API key |
session_id | "default" | Mubit run that backs this memory |
user_id | "" | Optional per-user scoping |
agent_id | "autogen-agent" | Agent identity for ingest/recall |
limit | 10 | Max memories recalled per turn |
entry_types | None | Restrict recall to specific entry types |
Gotchas
memory=[...]takes a list. AutoGen accepts multiple memory providers; passMubitMemoryas one element.- The
Memorymethods are async; the reinforcement methods are not.query/add/clear/closemust be awaited, whilerecord_outcome,record_step_outcome,emit_handoff, andemit_feedbackare plain synchronous calls. clear()deletes the run. It is AutoGen's reset semantics, but on Mubit it removes the whole backing run — don't call it to "tidy up" a session you want to recall later.- Recall and persistence fail open. A Mubit hiccup returns empty recall or skips the write rather than breaking the agent turn.
- protobuf pin. AutoGen pins
protobuf<6;mubit-sdkneeds>=6.33. Runpip install -U "protobuf>=6.33.4"after installing both.
Version compatibility
mubit-autogen | mubit-sdk | autogen-core / autogen-agentchat |
|---|---|---|
0.6.x | >= 0.9.0, < 1.0 | >= 0.7.5, < 0.8 |