Building block · Search

Hybrid search, no separate vector database.

One call spans full-text and semantic search, fused or on their own, chosen per schema, for records and ingested documents alike.

The alternative

What you'd otherwise build.

  • Separate tools for separate needs. A keyword engine here, a vector index there, and your own routing logic deciding which one a given query should hit.
  • A pipeline to keep alive. Embeddings generated, re-generated on model changes, and a sync job making sure the index never drifts from the source of truth.
  • Metadata as an afterthought. Your own document processor to attach structured fields to what you ingest, instead of storing a blob of extracted text.
  • No record of who searched what. If you ever need to show which caller saw a sensitive result, that’s a logging system you build and maintain yourself.
  • Data-level access control. Filter results after retrieval based on permissions, and hope nothing leaks through pagination, faceting, or a cache. Get it wrong once and it’s a real leak, not a bug report.

What's actually different

Mode is a property of the schema, not a platform-wide setting.

Full-text

Keyword relevance, no embedding cost: for data where meaning-based recall doesn't pay for itself.

Semantic

Meaning-based similarity, for natural-language recall where exact keywords miss the point.

Hybrid

Both, fused into one ranking: the recommended default when you're not sure which one wins.

TypeScript SDK: client.search.content
// Hybrid, scoped to one record type
const results = await client.search.content({
  query: 'lifestyle changes for stage 1 hypertension',
  mode: 'HYBRID',        // 'TEXT' | 'SEMANTIC' | 'HYBRID'
  typeName: 'patient_visit',
  limit: 10,
});

// Same call, filtered on structured metadata
const filtered = await client.search.content({
  query: 'medication review',
  mode: 'HYBRID',
  filters: { status: 'open', tag: ['anxiety', 'depression'] },
});

Each mode takes real tuning, not just on or off. Keyword search ranges from broad OR-matching to full boolean syntax. Filters support range operators, not just exact match. And you can set a relevance floor on either half of a hybrid query, the keyword side or the semantic side, to cut out noise.

Isolate your own clients, orgs, or anything else

Give a caller access to exactly one client, one org, or any other axis your product needs. It can never read, write, or search outside that boundary, no matter what the call itself says: leave the scope off and the request is rejected outright, not silently widened. Org and client are two reserved names, registered the same way as anything else you define.

TypeScript SDK: a client-scoped credential
// clientId is the id of a client entity you already created.
const { token } = await client.auth.mintToken({
  scope: {
    allowedActions: ['search:r'],
    dataScope: { 'scope:client': [clientId] },
  },
});
const scoped = new VectrosClient({ token, environment: 'production' });

// The call must name that same boundary, or it's rejected outright:
const hits = await scoped.search.content({
  query: 'medication review',
  mode: 'HYBRID',
  scope: 'client:' + clientId,
});

See the full access-control mechanics: roles, credentials, audit →

Metadata, not just text

Ingested documents carry the same treatment, plus real structured metadata (client name, case type, whatever fields you declare) searchable and filterable alongside the extracted text, not just a blob. See document ingestion.

Scales independently

Full-text search scales independently of your data's size, so a growing corpus doesn't mean degrading query speed.

Sensitive fields never enter the index at all, so no query can surface them, under any credential. Metered by what's actually indexed and queried, on the same underlying database.

What this isn't. Not a place to plug in your own analyzers, tokenizers, or scoring and ranking algorithms. If you need that level of low-level control, this isn't it. Modes and relevance are tuned through the schema and the query instead.
A note on semantic search. Semantic indexing has a per-tenant capacity limit, well above what the overwhelming majority of use cases need, with room to raise it for larger ones. Past it, hybrid or full-text content keeps serving from its keyword leg; a schema indexed as semantic-only has no keyword leg to fall back on, so that's the case actually worth watching if you're near the limit. See the published limit.

This page covers search: a ranked list of results. Want a synthesized, cited answer instead? See RAG, built directly on this same index.

See it in a real app

Search over real case notes.

The RAVV reference app searches case notes in hybrid mode today, for its admin role (a narrower role there is still waiting on a platform-side scope fix). The Second Brain blueprint is the lower-stakes version: dump every note, then just ask it.

Read: the RAVV stack →

This is one of five building blocks Vectros is built from, reachable over the same API and the same access policy as everything else.