MemorySyncMemorySync
Retrieval

Filters & Scoping

Recall has two layers of scoping: filters that the caller can shape from the request, and scopes that the platform enforces silently from the auth context. This page lists both.

Caller-shaped filters

FieldTypeLogic
filters.sourcesarray of stringsExact match on source. Multiple values OR together.
filters.tagsarray of stringsOR-match: a memory passes if any of its tags is in the list.
filters.since / filters.untilISO 8601 timestampInclusive range on created_at. Both optional.
filters.include_summariesbool, default trueWhen false, drops rows where is_summary=true.
filters.tier"hot" | "warm" | "cold"Restricts to a single tier. Result counts can shrink dramatically.

Platform-enforced scopes (no body override)

  • user_id — resolved from the auth principal. The query is restricted to the user's namespace; cross-user reads are not exposed in the recall API.
  • tenant_id — resolved from the auth principal. Cross-tenant reads are physically impossible.
  • project_id — resolved from X-Project-ID. When set, results are restricted to project_id = header or project_id IS NULL.
  • environment — resolved from the API key's setting. Cross-environment reads require an explicitly multi-environment key, which is rare.

Status filters that always apply

Three retention states are filtered out of recall by default and you cannot opt back into them through the public query API:

  • archived — read-only, accessible only via admin tooling.
  • soft_deleted — within the seven-day grace, restorable by admins.
  • purged / hard_delete_pending — gone, only the audit row remains.

The semantic-intent hard filter

When the platform classifies the query as having a clear intent — e.g. "tell me preferences" — it can apply a hard filter on extracted_type so only matching memories are considered. If the filter would empty the result set, the platform automatically reverts and flags semantic_intent_filter_reverted=true in the response so the caller can tell.

What filtering cannot do

  • Filters cannot relax the user/tenant scope.
  • Filters cannot reach memories in other environments.
  • Filters cannot include archived or soft_deleted memories — that requires an admin-only endpoint.
  • Filters cannot ask for "everything except" — they are inclusion lists only.

How filters affect result count

Filters are applied before ranking, at the index. A query with a tight time range, two tags, and a non-default tier may legitimately return zero results even on a large account. Empty result sets are not errors — render them as the no-match state.

Optional expansion pass when filters are too tight

If a filtered query comes back empty, the engine may try a single relaxed pass — typically by dropping the time range — to surface anything broadly relevant. If that pass returns rows, the response carries applied_filters.expansion_used=true so the caller can either accept or display them as "broader matches".