Skip to main content
A filter is a saved narrowing expression over one Brain. It owns no documents, no index, and no configuration of its own — it is a named view that restricts what searches and reads can see. Filters are addressed by a qualified reference: {brain-slug}:{filter-slug}, for example company-knowledge:support-docs.

Brain vs. filter

Reach for a separate Brain when the content is a genuinely different corpus — different documents, a different embedding model or language, or a different set of sync workflows feeding it. Reach for a filter when it’s the same corpus and you want different audiences or agents to see different slices of it. A practical rule: if you’re about to create a second Brain and a sync workflow would upload the same documents to both, you want one Brain and a filter.

The filter expression

A filter combines an optional source condition with optional metadata conditions:
Semantics are simple and uniform:
  • Entries AND together — a document must match source and every metadata key.
  • Arrays mean any-of"source": ["linear", "notion"] matches documents from either source; "labels": ["faq", "how-to"] matches if the document’s labels contains either value.
  • Scalars mean equals"team": "support" matches documents whose team metadata equals "support" (or contains it, when the stored attribute is an array).
This is why disciplined source values and metadata on upload matter: filters can only slice on what your sync workflows stored. If you anticipate a “just the support docs” view, make sure the sync writes a team or docType attribute worth filtering on.

Creating filters

In the dashboard: Brains → your Brain → Filters → Create filter. Or with the CLI:
The description is load-bearing for agents: like a Brain’s description, it’s how a model decides which attached knowledge source to search, so describe what the slice contains and when to use it.

Using filters

Attach to an agent — the agent’s brain_search / brain_read tools only ever see matching documents:
src/agents/support-bot.ts
Open from a workflow — a qualified reference returns a read-only handle. search, read, and list are narrowed by the filter; uploadDocument, updateMetadata, and deletes are rejected:
src/workflows/support-digest.ts
Narrow further at query time — search requests accept their own filters expression, which ANDs with the persisted filter:
Filter the document table — the dashboard’s document list and keystroke brains documents list <brain> --filter <filter-slug> apply a saved filter server-side, which is also a quick way to sanity-check what a filter matches before pointing an agent at it.

Behavior to know

  • Live, not snapshotted — a filter evaluates against current documents on every query. New documents that match appear immediately; editing the expression changes what every consumer sees on their next search.
  • Deleting a filter doesn’t touch documents, but agents and workflows addressing the qualified reference stop resolving — treat filter slugs referenced in deployed code as API contracts.
  • No document can hide from its Brain — filters narrow reads through the qualified reference only. Anything with read access to the base Brain still sees everything, so a filter is a scoping tool for agents and views, not a security boundary between projects.