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
)
// Event happened 3 days ago, ingested now
await client.remember({
content: "New CI/CD pipeline reduced deployment time by 60%.",
intent: "fact",
occurrence_time: Math.floor(Date.now() / 1000) - 86400 * 3,
});
// Historical event from January 2025
await 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]}")
const results = await client.recall({
query: "What technical changes were made?",
min_timestamp: 1735689600,
max_timestamp: 1738367999,
});
results.evidence.forEach(e => console.log(e.content.slice(0, 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}")
const results = await client.recall({ query: "Where is the office?" });
results.evidence.forEach(e => {
const status = e.is_stale ? " [STALE]" : "";
console.log(` ${e.content.slice(0, 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.
| Budget | Behavior | Typical latency |
|---|
"low" | Fewer candidates, skip deep traversal | < 500ms |
"mid" | Standard retrieval (default) | 500ms–2s |
"high" | More candidates, deeper graph traversal | 1–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")
// Fast
const fast = await client.recall({ query: "user question", budget: "low" });
// Deep
const deep = await client.recall({ query: "analysis topic", budget: "high" });
Next steps