Skip to content

Search

chronicle.search runs Vertex-backed semantic search across your research docs, experiment metadata, and arxiv assets, filtered to what you're allowed to read.

query is the primitive: it hits POST /search, returns one page of SearchResult hits ranked by relevance, and takes filters, an experiment-context boost, and a hard scope. history is a thin alias for searching your internal corpus; iter walks every page for you.

ACL- and namespace-filtered server-side

The server applies RBAC and storage-prefix isolation before ranking — you only ever see hits you can read, so you never filter for them yourself. SearchFilters layers on top of those server filters. POST /search is Vertex-backed and returns 503 where Vertex isn't configured (local dev, CI without credentials) — catch methodic.errors.ServerError and check status_code == 503 to gate against that.

query

resp = chronicle.search.query(
    "shock formation in 2D compressible Euler",
    filters={"asset_types": ["research_report"], "created_after": "2026-01-01"},
)
for hit in resp.results:
    print(hit.relevance_score, hit.title, hit.document_id)
print(resp.total_size, resp.next_page_token)

Parameters:

Param Type Effect
query str The semantic query string.
filters SearchFilters \| dict \| None Narrowing filters (table below).
experiment_context list[str] \| None Experiment ids that boost lineage-related hits — does not exclude others.
scope SearchScope \| dict \| None Hard filter to a union of collections + experiments (see below).
page_size int \| None Hits per page.
page_token str \| None Cursor from a prior next_page_token.

SearchFilters fields:

Field Matches on
asset_types restrict to listed asset types (e.g. ["research_report"])
created_by author principal
created_after / created_before creation-time window
source_type source of the indexed doc
tags hits carrying any listed tag (human-facing label names)
organization_id / team_id owning scope

Boost vs. scope

experiment_context and scope both name experiments but do opposite things. experiment_context boosts lineage-related hits while leaving the rest of the corpus in play. scope is a hard filter — results are restricted to the resolved union of the named collections and experiments, ANDed with the server's ACL filter:

from methodic import SearchScope

resp = chronicle.search.query(
    "spectral loss instabilities",
    scope=SearchScope(collections=["col_pde"], experiments=["exp_7Qk"]),
)

To scope to your current experiment, pass an empty SearchScope() together with experiment_context — the empty scope flips those anchors from boost to hard-scope.

history — your internal corpus

history searches Chronicle's internal corpus: your experiment history and internal research documents (hypotheses, takeaways, research reports, experiment metadata). It's a semantic alias for query with the common narrowing knobs lifted into keyword args (created_by, created_after, created_before, asset_types) and assembled into a SearchFilters — same POST /search endpoint, same ACL scoping.

resp = chronicle.search.history(
    "did increasing viscosity stabilize the rollout?",
    asset_types=["research_report"],
    created_after="2026-03-01",
)

asset_types defaults to None; Chronicle already excludes session assets server-side, so the unfiltered corpus is the right default. history takes no scope or source_type — reach for query when you need those.

No external literature

history does not search arxiv or external papers — that's served by a separate external MCP, not by this API.

iter — paginate

iter yields every hit across all pages, fetching the next page server-side as it goes. Same query/filters/experiment_context/scope/page_size parameters as query; no page_token (it manages the cursor):

for hit in chronicle.search.iter(
    "neural operator generalization across Reynolds numbers",
    filters=SearchFilters(asset_types=["research_report"]),
    page_size=50,
):
    print(hit.title, hit.relevance_score)

Result fields

Each SearchResult carries document_id, source_type, relevance_score, and lineage_boost always, plus optional asset_type, title, snippet, experiment_ids, and created_at. A SearchResponse wraps results, total_size, and next_page_token (None on the last page). Full field list: reference/client.md.