Search and queries
/context is the right call for “what should my agent know.”
These two are for when you want the raw material instead.
Search — passages
Section titled “Search — passages”curl "$API/v1/brains/tenant:acme/search?q=sso+redirect+loop&limit=5" \ -H "authorization: Bearer $NICIA_KEY"{ "data": { "results": [ { "source": "zendesk:ticket:8821", "slug": "brain-evidence-3bb86259c42d0261e0f1cc2d0f7f5f6bb2ee2a9a1cfa8a5b1c5e8a5f0f2a7d31", "title": "SSO login loop after IdP change", "excerpt": "Customer reports a redirect loop after switching to Okta…", "rank": 1, "version": 3 } ], "mode": "fulltext", "staged": 0, "warnings": [], "receipt": "rcp_019fff21" }}Search ranks the passages of everything the Brain holds, best match first. Use
it to build your own retrieval flow, to show a “sources” panel, or to debug why
/context answered the way it did.
rank is a position, not a score: 1 is the best match. Ranking fuses a
keyword leg and a semantic leg into an ORDER, and there is no comparable
relevance number underneath to hand you. version is the exact document
version the passage was cut from, and it is what the receipt records.
source is the id you wrote the document under — the address to act on, and the
one that round-trips into GET /documents/{id}. slug is the Brain’s internal
address for the page (an opaque hash, derived from the Brain and your document
id, for anything written through this API), and it is what lets you line a hit
up against a /context citation.
mode is the whole narrowing vocabulary:
mode |
Ranks by |
|---|---|
fulltext (default) |
Keywords. No embedding round trip, so it is the fast path |
hybrid |
Keywords and meaning, fused — matches phrasings you did not use |
The response echoes the mode it actually ranked by. hybrid needs an
embedding provider, and a deployment without one answers your hybrid request
with keyword ranking rather than failing a read it can still serve — so
data.mode comes back fulltext and you can tell a fused answer from a
keyword one. Check it before you conclude that semantic matching did not help.
Search takes no filter, exactly like /context.
Ranking reads a passage index, and that index knows nothing about your document
metadata. When you want exact resolution rather than a ranking — this kind, this
slug — that is /query below. One optional indexed linked predicate can
narrow to neighbors of a known record first; non-slug field predicates still
return 400 index_not_ready. Ranked retrieval and exact address resolution are
different tools, and Nicia will not pretend one is the other by accepting a
filter it cannot apply.
Query — rows
Section titled “Query — rows”When you want exact resolution by record address (slug) rather than ranked passages:
curl -X POST "$API/v1/brains/tenant:acme/query" \ -H "authorization: Bearer $NICIA_KEY" \ -H "content-type: application/json" \ -d '{ "kind": "person", "where": { "slug": "bob-smith" }, "limit": 20 }'{ "data": { "records": [ { "id": "bob-smith", "kind": "person", "fields": { "name": "Bob Smith", "role": "VP Platform" }, "sources": ["zendesk:ticket:8821"], "version": 3, "updatedAt": "2026-08-02T14:20:00Z" } ], "staged": 0, "warnings": [], "receipt": "rcp_019fff44" }}Today, /query index-resolves exact equality on slug, plus one optional
exact linked predicate (one declared link → one kind:identity target).
The following is a valid request:
{ "kind": "person", "where": { "slug": "bob-smith" }, "limit": 50}slug equality is literal: no case folding or trimming. Every non-slug-field
where predicate — declared or undeclared — returns 400 index_not_ready
until a property index ships. A has on slug, or a non-string slug equality,
is a type/operator validation error, not that limit. Declaring a field makes it governed vocabulary and
preserves and returns its values; it does not make that field filterable.
linked is one-hop only: the Brain resolves that indexed edge, then AND-applies
where inside the candidate set. There is no range, or, ordering, multi-hop
walk, or arbitrary graph traversal. See Schemas.
Paging
Section titled “Paging”/query is keyset-paged with an opaque cursor. Its limit may ask for at most
100 records — that is the reader’s page, and a larger one is a 400 rather
than a page quietly cut down to size:
curl -X POST "$API/v1/brains/tenant:acme/query" \ -H "authorization: Bearer $NICIA_KEY" \ -H "content-type: application/json" \ -d '{ "kind": "person", "cursor": "eyJrIjoi…" }'{ "data": { "records": [], "staged": 0, "warnings": [], "receipt": "rcp_019fff44", "nextCursor": "eyJrIjoi…" }}Cursors are stable under concurrent writes: a record added mid-walk will not shift the page boundary and cause you to skip one.
/search is not paged. It is a ranked top-N read with no stable cursor to
hand out, so it takes a limit of at most 20 and returns the best matches for
your query. Ask a narrower question rather than walking a ranking — a cursor
here would have served you the same first page over and over.
Receipts
Section titled “Receipts”Search and query both issue receipts, exactly like /context. Anything that
shows a customer information can be reconstructed later, whichever endpoint
produced it. See Receipts.
Which one do I want?
Section titled “Which one do I want?”- Putting knowledge in a prompt →
/context. It selects, budgets, and renders for you. - Showing sources, or building your own selection →
/search. - Resolving a known record by
slugfor a table, dashboard, or rule →/query(non-slug field filters return400 index_not_readyuntil a property index ships).
If you are reaching for /search to then paste the results into a prompt, use
/context with format: "items" instead — you get the same pieces plus the
budgeting.