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

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 of autogen_core.memory.Memory, so it attaches directly to an AssistantAgent(memory=[...]). AutoGen calls update_context() before each model turn: Mubit recalls relevant context and injects it as a SystemMessage, and new assistant/user content is persisted via add().
  • MubitGroupChatHook — forwards multi-agent handoff and feedback signals into Mubit so team activity is queryable alongside memory.
ℹ️Note

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

autogen_minimal.py
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 single SystemMessage. Recalled lessons, facts, and prior traces arrive without any prompt plumbing on your side.
  • Capturedadd() persists content via Mubit remember. User-role content lands with a context intent, everything else as a trace, unless you set metadata["intent"] explicitly. Pass a stable metadata["idempotency_key"] so a retried write is deduplicated server-side instead of double-counting reinforcement.
  • Attributable — every recalled MemoryContent keeps its source reference_id in metadata. Pull those IDs off a query result with extract_entry_ids() and feed them into record_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.

support_assistant.py
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.

multi_agent.py
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

ParameterDefaultPurpose
endpointhttp://127.0.0.1:3000Mubit 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
limit10Max memories recalled per turn
entry_typesNoneRestrict recall to specific entry types

Gotchas

  • memory=[...] takes a list. AutoGen accepts multiple memory providers; pass MubitMemory as one element.
  • The Memory methods are async; the reinforcement methods are not. query/add/clear/close must be awaited, while record_outcome, record_step_outcome, emit_handoff, and emit_feedback are 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-sdk needs >=6.33. Run pip install -U "protobuf>=6.33.4" after installing both.

Version compatibility

mubit-autogenmubit-sdkautogen-core / autogen-agentchat
0.6.x>= 0.9.0, < 1.0>= 0.7.5, < 0.8