Overview
The Memory Query Language (MQL) lets you express exactly which memories you want in one line: structured filters, boolean logic, graph and geo predicates, full-text and semantic search, aggregation, ordering, and a limit. Run it interactively on the Query page, where you get syntax highlighting, autocomplete of your real spaces and tags, inline error underlines, a plain-English read-out, and one-click refine.
space:work quality>=0.7 created>now-30d ~"postgres decision" order by recency limit 20A query is an optional filter expression, an optional ~"…" semantic clause, an
optional order by, and an optional limit/offset — in
that order. Any part can be omitted.
Fields
Predicates take the form field<op>value. The common fields:
space,cluster,session— where a memory livescontent_type— text, image, audio, … ·type(memory_type) — fact, preference, episode, …tags— your labels ·origin,source_type— how it arrivedpinned,protected— boolean flagscreated,updated,event_date— timestampssalience,quality,confidence,feedback_score— scoresentity,topic,related— graph fields ·metadata.*— your custom keyscountry,region,near,bbox— geo fields
The Query page's cheatsheet lists every field available for your account.
Operators
:— equals, or full-text match oncontent=!=— equals / not equals>>=<<=— compare numbers and datesin [a, b]/not in [a, b]— any / none of a listbetween x and y— inclusive rangefield:*— field has any value ·field:null— field is empty
Combining predicates
A space means and. Use or, not, and parentheses
to compose:
space:work tags:urgent # both (AND)
space:personal or space:work # either (OR)
not pinned:true # negate
(origin:work or origin:private) created>now-7dValues & time
"quoted text"— strings (quote anything with spaces)0.742— numbers ·truefalse— booleans2026-01-01— absolute datesnow-7d,today,now+2h— relative time, past or future (unitss m h d w)within 30d— sugar for a recent window
Full-text & semantic search
content: runs a full-text search that understands operators — multiple words are
OR'd, -word excludes, and "a phrase" matches in order. A trailing * inside quotes is a prefix match. ~"…" is a separate
meaning-based (vector) search that ranks by similarity.
content:"postgres migration" # full-text (OR of the words)
content:"deploy -rollback" # exclude a term
content:"post*" # prefix match
~"how did we decide on the schema" # semantic (meaning) searchGraph filters
Filter through the knowledge graph — extracted entities and topics, clusters, and direct relationships to another memory.
entity:"Postgres" # memories mentioning an entity
topic:database # by extracted topic
cluster:"Onboarding" # within a named cluster
related:<memory-id> # linked to a specific memory
entity:* # has any entity at allGeo filters
Filter memories by place, radius, or bounding box (for memories with a location).
country:SE # ISO country code
region:"California" # named region
near:"59.33,18.06,10" # within 10 km of lat,lng
bbox:"59.2,17.9,59.4,18.2" # inside minLat,minLng,maxLat,maxLngCustom metadata
Any key you store under metadata is queryable with typed comparisons and
existence checks:
metadata.priority>=3
metadata.due<now+7d
metadata.owner:"alice"
metadata.reviewed:nullOrdering, limit & offset
order by—relevance|recency|quality|confidence|feedback_score|<field>[asc|desc]- Sort on multiple keys:
order by quality desc, created asc limit 20— cap the result count ·offset 20— page through results
Aggregation
Instead of a list, ask for a count or a grouped rollup. group by a field and
apply count or avg/sum/min/max over a numeric field:
count # total matching memories
space:work group by type count # how many of each memory_type
group by space avg quality # average quality per spaceHow it runs
Every valid query runs. Simple filters map directly onto the memory endpoint's parameters;
everything richer — score thresholds, type, graph, geo, metadata.*,
ranges, aggregation, and any and/or/not combination —
is compiled to a parameterised SQL filter on the server and executed after your access
checks.
Only the query string travels over the wire — never SQL. Column names come from a fixed field catalogue and every value is a bound parameter, so a query can filter your memories but can never reach beyond them or inject SQL. Invalid queries are rejected with a precise, caret-pointing message before anything runs, and every query runs under a statement timeout.
On the Query page
The interactive Query page turns MQL into a workbench:
- Result facets — click a type, tag, or space from your results to refine and re-run
- Cards or table — toggle a dense, sortable grid for scanning many results
- Export — copy results as Markdown, CSV, or JSON, or download to a file
- Ask AI — describe what you want in plain English and get an editable MQL query, or "Improve" your current one
- Advisor — instant, rule-based tips (add a limit, scope a space, prefer structured filters)
- Saved searches — save a query and run it on a schedule
Examples
space:work tags:urgent
created>now-7d pinned:true
space:personal or space:work
type:fact quality>=0.7 order by confidence desc
entity:"Postgres" ~"migration plan"
near:"59.33,18.06,25" created>now-90d
group by type count
salience>=0.5 order by recency limit 20 offset 20Try any of these on the Query page — click an example to load it, then press ⌘/Ctrl+Enter to run.