RememberStackremember.dev/docs

Entities and facts

These five routes are the direct, single-purpose reads behind the assured operations. Use them when you already know what you want: the entity ids for a name, the relations that match a pattern, or the evidence behind one fact. Each returns an Envelope.

All five need the read scope. Base URL, authentication and error shapes are described in HTTP API conventions.

GET /resolve

Resolve a name to the current entities it can mean, ranked. It never guesses: if several entities match, you get all of them.

Parameters

NameInTypeRequiredDefaultConstraints
namequerystringyes
context_entity_idsqueryarray of UUIDnononeRepeat the parameter for each id. At most 8. Duplicates are collapsed.

Matching runs in tiers and stops at the first that finds anything:

Tiertier valueHow it matches
ExactT0The normalized name equals a current alias. Every entity with that alias is returned, uncapped.
TrigramT1Fuzzy match against current aliases.
PhoneticT2Sound-alike match against current aliases.
EmbeddingT3The name is embedded and compared with entity profiles.

T1, T2 and T3 stop at the same candidate width the ingest pipeline uses and say so in truncation (reason: "resolve_candidate_limit", total_is_exact: false). context_entity_ids does not add or remove candidates; it reorders them by how many current relations connect each candidate to those entities (context_hits).

Response

200 with an Envelope of grain fact. entities holds the candidates, best first. When nothing matches, entities is empty and negative.kind is unknown_entity. If the embedding tier was needed but the entity search index is not published, negative.kind is boundary.

{
  "grain": "fact",
  "temporal_scope": {"mode": "current", "evaluated_at": "2026-09-23T10:00:00Z", "believed_at": "2026-09-23T10:00:00Z", "identity_regime": "current"},
  "entities": [
    {"entity_id": "7c1e…", "canonical_name": "Dana Whitfield", "tier": "T0", "context_hits": 0},
    {"entity_id": "91ab…", "canonical_name": "Dana", "tier": "T0", "context_hits": 0}
  ],
  "freshness": {"pg_live_ts": "2026-09-23T10:00:00Z", "p1_written_inline": true, "p1_believed_at_horizon": null, "k": null},
  "truncation": null,
  "negative": null
}

Array fields that are empty (facts, evidence and so on) are present in the real response and omitted here.

Errors

StatusdetailCause
422validation listname missing, a malformed UUID, or more than 8 context_entity_ids.
503model provider unavailableThe embedding tier was needed and the embedding call failed. Retry with back-off.

Example

curl -s -G "$REMEMBER_API_URL/resolve" \
  -H "Authorization: Bearer $REMEMBER_API_KEY" \
  --data-urlencode "name=Dana"
from remember import Client
 
memory = Client()
envelope = memory.resolve(name="Dana")
for candidate in envelope.entities:
    print(candidate.entity_id, candidate.canonical_name, candidate.tier)

The assured operation resolve_entity runs the same resolution without context_entity_ids.

GET /lookup/relations

Return the relations that match a subject–predicate–object pattern, as held now or at a past instant.

Parameters

NameInTypeRequiredDefaultConstraints
subject_entity_idqueryUUIDnoany
predicatequerystringnoanyExact predicate name.
object_entity_idqueryUUIDnoany
valid_atquerydate-timenonowMust be UTC (Z or +00:00).
kqueryintegerno501–400. The most relations to return.

Every filter is optional; the ones you send are combined with AND. A relation matches when it has not been invalidated and its validity window covers valid_at (or now). A relation with no known start or end is treated as open on that side.

At most k relations come back. When more match, truncation says so (truncated: true, reason: "lookup_k_limit", total_is_exact: false): narrow the pattern or raise k.

Response

200 with an Envelope of grain fact. facts holds one FactResult per relation (kind: "relation"), ordered by evidence count, highest first, then by when the memory learned it; truncation is set when the k cap left matches out. Each result carries its validity, its temporal_match, its support and, when the relation is part of a contradiction, the other sides in contradiction. With valid_at, temporal_scope.mode is at; without it, current. No match gives negative.kind known_empty.

Errors

StatusdetailCause
422validation listA malformed UUID or timestamp, a valid_at without a zero UTC offset, or k outside 1–400.

Example

curl -s -G "$REMEMBER_API_URL/lookup/relations" \
  -H "Authorization: Bearer $REMEMBER_API_KEY" \
  --data-urlencode "subject_entity_id=$RAVI_ID" \
  --data-urlencode "valid_at=2026-06-01T00:00:00Z"
from datetime import datetime, UTC
from remember import Client
 
memory = Client()
envelope = memory.lookup_relations(
    subject_entity_id=ravi_id,
    valid_at=datetime(2026, 6, 1, tzinfo=UTC),
)

GET /lookup/observations

Return the live observations (single-entity facts, such as "the billing migration is behind schedule") about one entity, optionally ranked by how well they match a phrase.

Parameters

NameInTypeRequiredDefaultConstraints
entity_idqueryUUIDyes
property_queryquerystringnoWhen present, observations are found by semantic similarity to this text.
kqueryintegerno101–400. The most observations to return.

Without property_query, the live observations on the entity whose validity covers now are returned, strongest evidence first, at most k; when more exist, truncation says so (reason: "lookup_k_limit"). With property_query, up to k candidates are nominated by similarity and each is re-checked against the database before it is returned; candidates that no longer hold are dropped and counted in dropped_by_hydration.

Response

200 with an Envelope of grain fact. facts holds one FactResult per observation (kind: "observation"). No match gives negative.kind known_empty.

Errors

StatusdetailCause
422validation listentity_id missing or malformed, or k not an integer in 1–400.
503model provider unavailableThe embedding call for property_query failed. Retry with back-off.

Example

curl -s -G "$REMEMBER_API_URL/lookup/observations" \
  -H "Authorization: Bearer $REMEMBER_API_KEY" \
  --data-urlencode "entity_id=$BILLING_MIGRATION_ID" \
  --data-urlencode "property_query=schedule" \
  --data-urlencode "k=10"
envelope = memory.lookup_observations(
    entity_id=billing_migration_id, property_query="schedule", k=10
)

GET /hydrate/relation/{relation_id}

Follow one relation down to the claims that support it and the documents those claims came from. This is the audit hop: it answers "why does the memory hold this?".

Parameters

NameInTypeRequiredConstraints
relation_idpathUUIDyes

Response

200 with an Envelope of grain composite:

  • facts: the relation itself, with its contradiction block and support state. An invalidated relation is still returned, with invalidated_at set in its validity: this route does not hide history.
  • evidence: the supporting claims (EvidenceResult), each with its source span and character offsets.
  • sources: the documents (SourceRecord).

An unknown relation id gives negative.kind unknown_entity.

Errors

StatusdetailCause
422validation listrelation_id is not a UUID.

Example

curl -s "$REMEMBER_API_URL/hydrate/relation/$RELATION_ID" \
  -H "Authorization: Bearer $REMEMBER_API_KEY"
envelope = memory.hydrate_relation(relation_id=relation_id)

GET /transcript/relation/{relation_id}

Return the decisions the memory made about one relation: when it was superseded, by what, how, and on what grounds.

Parameters

NameInTypeRequiredConstraints
relation_idpathUUIDyes

Response

200 with an Envelope of grain composite. transcript holds up to the 40 most recent decisions (TranscriptEntry), oldest first. truncation is always present and says whether older decisions were left out (truncated, returned, estimated_total). A relation with no recorded decisions, or an unknown id, gives negative.kind known_empty.

Errors

StatusdetailCause
422validation listrelation_id is not a UUID.

Example

curl -s "$REMEMBER_API_URL/transcript/relation/$RELATION_ID" \
  -H "Authorization: Bearer $REMEMBER_API_KEY"
envelope = memory.transcript_relation(relation_id=relation_id)
for decision in envelope.transcript:
    print(decision.decided_at, decision.outcome, decision.method)