Skip to main content

Unified retrieve contract (CLI · MCP · API)

One mental model for reading at scale across all four planes — Topics, Projects, Collections, Broker — so an agent never has to learn per-surface rules. Every retrieval read on every surface converges on the same vocabulary, defaults, and output shape. The navigation.md plan says which plane to move to; this contract says how every read behaves once you’re there. It is deliberately composable surfaces, not one mega-tool: each plane keeps its own bounded read, and they share this contract so results line up. A unified primitive is only earned once every plane passes the retrieval-scale gate.

The shared vocabulary

ConceptParamMeaningDefault
Intentquery / taskfree-text “what I’m looking for / about to do”
Anchorfilesrepo paths the work touches (topics only)
Scopestatus, tags, area, provider, effect, entity, drifted/stale, updated_after, fieldsstructured narrowing (per plane)
Boundlimitmax rows this pagesmall, plane-specific
Pagecursoropaque keyset/offset token for the next pagefirst page
Depthview = summary | brief | fullpayload tier (full is always opt-in)summary/brief
Notesinclude_notesalso surface shared private Notes (your OWN are always visible)false
Explainexplain / why_matchedwhy each hit matchedoff

The shared output shape

Every bounded read returns, in some form:
  • shown + has_more (and a nextCursor when more exist) — bounded, pageable.
  • results/records/operations/cards — the rows, at the requested view.
  • trust where governance applies (knowledge | proposed | note) — an agent must never confuse a hint with team truth.
  • stale / drift flag where drift applies — verify before relying.
  • next_action — the next bounded call (the navigation rail).

The invariants (hold on every surface)

  1. Bounded by default. No read returns an unbounded set; the default page is small and full bodies are always an explicit opt-in.
  2. Filter + privacy BEFORE limit. Visibility (the draft-privacy predicate) and all filters run in SQL before LIMIT — a page never leaks across the visibility boundary, and the caller’s OWN Notes are never false-empty.
  3. next_action is the rail. Every read names the next bounded call; the chain composes the planes (see navigation.md).
  4. No list-all to find one thing. Searching is a server-side filter call (query + keyset), never a client-side scan of a full list.

Where each surface implements it

PlaneCLIMCPAPI
Topics (task)context retrieve "<task>" [--explain]driftless_context_retrievePOST /topics/retrieve
Topics (files)context get --files/--diffdriftless_context_get_for_filesGET /topics/match-files
Topics (browse)context list/search [--limit --cursor]driftless_context_list/_searchGET /topics, /topics/search
Projectsproject cards [--owner --cursor] · project card nextdriftless_project_card list/nextGET /projects/:id/cards, /cards/next
Collectionscollection retrieve/records [--limit --cursor]driftless_collection retrieve · driftless_collection_record listGET /collections/:id/retrieve, /records
Brokerbroker operations --querydriftless_broker operations (query)GET /broker/operations
The matrix of names + default views is surface-matrix.md; the retrieve-first routing for agents is skills/driftless/references/retrieve.md.