Documentation menu
Temporal memory & point-in-time queries

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.

shell
# What was true about the user as of mid-2023? "kw">curl "https://anansimemory.com/v1/context?userId=user_123&asOf=2023-06" \ -H "Authorization: Bearer ans_..."
typescript
"kw">import AnansiMemory "kw">from "anansi-memory"; "kw">const memory = "kw">new AnansiMemory({ apiKey: process.env.ANANSI_API_KEY }); "kw">const then = "kw">await memory.context({ userId: "user_123", asOf: "2023-06" }); "kw">const now = "kw">await memory.context({ userId: "user_123" });
python
then = memory.context(user_id="user_123", as_of="2023-06") now = memory.context(user_id="user_123")

What asOf changes

FieldWithout asOfWith 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[]unchangedunchanged (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:

text
Alex works_at Google 2022-01 ──────────► 2024-01 Alex works_at Stripe 2024-01 ──────────► (now)

GET /v1/entities?userId=alex (no asOf) — full history:

json
{ "entities": [{ "name": "Alex", "type": "person", "relationships": [ { "relationship": "works_at", "target": { "name": "Google" }, "validFrom": "2022-01-01T...", "validUntil": "2024-01-01T...", "current": false }, { "relationship": "works_at", "target": { "name": "Stripe" }, "validFrom": "2024-01-01T...", "validUntil": null, "current": true } ] }] }

GET /v1/entities?userId=alex&asOf=2023-06snapshot:

json
{ "entities": [{ "name": "Alex", "type": "person", "relationships": [ { "relationship": "works_at", "target": { "name": "Google" }, "validFrom": "2022-01-01T...", "validUntil": "2024-01-01T...", "current": true } ] }] }

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.

Boundaries
Validity intervals are half-open — [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.

AxisQuestionStored as
Valid timeWhen was the relationship true in the real world?validFrom / validUntil
Knowledge timeWhen 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 asOfKnowledge are 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.
shell
# What did we believe about the user back in Feb 2024? "kw">curl "https://anansimemory.com/v1/entities?userId=alex&asOfKnowledge=2024-02" \ -H "Authorization: Bearer ans_..."
typescript
"kw">const believedThen = "kw">await memory.listEntities({ userId: "alex", asOfKnowledge: "2024-02" });

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:

QueryResultWhy
asOf=2024-02StripeAt that valid instant Alex was already at Stripe…
asOfKnowledge=2024-02Google (still open)…but we hadn't learned it yet, so our belief was still Google
asOf=2024-02 & asOfKnowledge=2024-02GoogleWhat 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.

Scope
The knowledge-time axis applies to the entity graph (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 validUntil is 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.

Granularity
Temporal facts use month precision (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.