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
| Field | Type | Logic |
|---|---|---|
filters.sources | array of strings | Exact match on source. Multiple values OR together. |
filters.tags | array of strings | OR-match: a memory passes if any of its tags is in the list. |
filters.since / filters.until | ISO 8601 timestamp | Inclusive range on created_at. Both optional. |
filters.include_summaries | bool, default true | When 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 fromX-Project-ID. When set, results are restricted toproject_id = headerorproject_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
archivedorsoft_deletedmemories — 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".