Skip to main content

Temporal Memory Patterns

MuBit tracks two time dimensions for every memory entry: ingestion time (when the system learned it) and occurrence time (when the event actually happened). This distinction is critical for agents that reason about historical events.

Storing events with occurrence time

When ingesting facts about past events, set occurrence_time to record when the event happened. Without it, the system only knows when the fact was ingested.
import time

# Event happened 3 days ago, ingested now
client.remember(
    content="New CI/CD pipeline reduced deployment time by 60%.",
    intent="fact",
    occurrence_time=int(time.time()) - 86400 * 3,
)

# Historical event from January 2025
client.remember(
    content="Server migration to AWS completed with zero downtime.",
    intent="fact",
    occurrence_time=1736899200,  # Jan 15 2025 UTC
)

Querying by time range

Use min_timestamp and max_timestamp to filter evidence to a specific time window. The filter checks occurrence_time first, falling back to ingestion time.
# "What happened in January 2025?"
results = client.recall(
    query="What technical changes were made?",
    min_timestamp=1735689600,   # Jan 1 2025
    max_timestamp=1738367999,   # Jan 31 2025
)

for evidence in results["evidence"]:
    print(f"  {evidence['content'][:80]}")
Without temporal bounds, “What happened last week?” uses natural language temporal intent detection and prioritizes entries by occurrence time in the recency ranking.

Handling stale facts

When a newer fact contradicts an older one, MuBit marks the older entry as stale and deprioritizes it in ranking. The staleness metadata is available in evidence responses.
# Store contradicting facts
client.remember(
    content="The office is in Building A, Floor 3.",
    intent="fact",
    metadata={"speaker": "facilities"},
)
# Later...
client.remember(
    content="The office moved to Building B, Floor 7.",
    intent="fact",
    metadata={"speaker": "facilities"},
)

# Query — newer fact ranks higher, older is marked stale
results = client.recall(query="Where is the office?")
for evidence in results["evidence"]:
    stale = evidence.get("is_stale", False)
    status = " [STALE]" if stale else ""
    print(f"  {evidence['content'][:60]}{status}")
Stale entries are still returned for transparency. The ranking penalty ensures they appear below the current fact. Filter them out in your application if you only want current information.

Budget control for latency-sensitive agents

The budget parameter controls the depth of retrieval. Use "low" for real-time agents and "high" for accuracy-critical offline analysis.
BudgetBehaviorTypical latency
"low"Fewer candidates, skip deep traversal< 500ms
"mid"Standard retrieval (default)500ms–2s
"high"More candidates, deeper graph traversal1–5s
# Fast retrieval for a real-time chatbot
fast = client.recall(query="user question", budget="low")

# Deep retrieval for a research report
deep = client.recall(query="comprehensive analysis topic", budget="high")

Next steps