Documentation menu
Most memory APIs flatten to current state. Anansi keeps the timeline — every fact and relationship carries validity bounds, so you can ask: what was true about this user in June 2024?
Two kinds of temporal data
When Anansi synthesizes a user's memory, it extracts two time-aware structures:
- Temporal facts — time-bounded statements with
validFrom/validUntil("Works at Stripe", "Lived in NYC"). - Entity relationships — bi-temporal edges in the entity graph (Alex —works_at→ Stripe, valid 2024-01 onward).
Both are returned by GET /v1/context and GET /v1/entities, and both can be queried at a point in time with asOf.
The asOf parameter
Add asOf to GET /v1/context or GET /v1/entities to get the world as it was valid at that instant. Accepted formats: YYYY-MM, YYYY-MM-DD, or full ISO 8601.
What asOf changes
| Field | Without asOf | With asOf |
|---|---|---|
| temporal[] | every fact, each tagged current (valid now) | only facts valid at asOf, each current: true |
| entities[].relationships[] | full history (active + closed edges) | only relationships active at asOf |
| static[], dynamic[], relevant[] | unchanged | unchanged (not time-versioned) |
asOf is valid-time — when the fact was true in the real world — not when Anansi learned it.
Worked example
Suppose the user's history looks like this:
GET /v1/entities?userId=alex (no asOf) — full history:
GET /v1/entities?userId=alex&asOf=2023-06 — snapshot:
At asOf=2023-06, Alex worked at Google, and that relationship is current relative to the query instant. Stripe doesn't appear — it wasn't true yet.
[validFrom, validUntil), inclusive start, exclusive end. At the exact switch instant (asOf=2024-01-01) only the Stripe edge is returned. No double-counting at transitions.The knowledge-time axis
asOf answers what was true. There's a second, independent question: what did we know? These differ whenever we learn about something after it happened — which is almost always.
The entity graph is bi-temporal: every relationship carries two time axes.
| Axis | Question | Stored as |
|---|---|---|
| Valid time | When was the relationship true in the real world? | validFrom / validUntil |
| Knowledge time | When did Anansi learn it? | recorded_at (learned of the edge) / when its end was recorded |
Query the knowledge axis with asOfKnowledge. It reconstructs the graph as we believed it at that instant:
- relationships first recorded after
asOfKnowledgeare excluded — we didn't know them yet; - a relationship's end is applied only if we'd learned of it by
asOfKnowledge; otherwise it reads as still open.
Belief vs. reality
Suppose Alex moved Google → Stripe in January 2024 (valid time), but Anansi only recorded it in March 2024 (knowledge time). Then in February 2024:
| Query | Result | Why |
|---|---|---|
| asOf=2024-02 | Stripe | At that valid instant Alex was already at Stripe… |
| asOfKnowledge=2024-02 | Google (still open) | …but we hadn't learned it yet, so our belief was still Google |
| asOf=2024-02 & asOfKnowledge=2024-02 | What we believed, at the time we believed it |
This is the auditability guarantee: you can reconstruct exactly what an agent knew at the moment it acted — not what turned out to be true later. Combine both axes for a full bi-temporal point query.
entities[]). Temporal facts (temporal[]) are re-derived each synthesis pass and support valid-time asOf only.Why this matters
- Auditability — "What did the agent know about the customer when it made this recommendation?" Reconstruct the exact context behind a past decision.
- Correctness over time — a support bot answering "where do you work?" gets the answer that was true when the conversation happened, not a stale or future one.
- History without bloat — superseded facts aren't deleted; they're closed. You keep the trajectory (promotions, relocations, tech migrations) without it polluting current state.
How the timeline is built
The synthesis worker maintains validity automatically:
- When a new fact supersedes an old one (Alex changes jobs), the old relationship's
validUntilis set to the moment the change was observed, and a new active relationship is opened. - Facts explicitly marked as ended close cleanly.
- The entity graph enforces at most one active relationship of a given type between two entities, so snapshots are never ambiguous.
See the entity graph for the underlying data model, and metadata filters for filtering search results by stored fields.
YYYY-MM) as emitted by synthesis; entity edges record full timestamps. asOf accepts any of YYYY-MM, YYYY-MM-DD, or ISO 8601 and is compared in UTC.