Skip to content

Query SDK overview

The Metrana query SDK (metrana.query) is the read side of the Python client. Where the ingestion SDK sends data in from your training loop, this one pulls it back out — projects, runs, RL environments and series — as pandas DataFrames, ready for analysis in a notebook or a script.

from metrana.query import QueryClient
client = QueryClient(workspace_name="my-team", project_name="my-project")
runs = client.fetch_runs(max_runs=20) # a table of runs
loss = client.fetch_float_series(runs["name"].tolist(), "loss") # their loss curves

It ships in the same metrana package, behind an optional extra, so training images that only log never carry pandas or gRPC.

The method name tells you the shape of the answer:

Prefix Returns Examples
fetch_ a 2-D DataFrame fetch_runs, fetch_float_series
list_ a 1-D list or dict list_experiments, list_run_attributes
get_ a single record get_rl_info

Every fetch_ method depaginates for you: you ask for a table, you get the whole table, not a page and a cursor. Where a result could be unbounded there is a cap argument (max_runs, max_projects, …) rather than a hidden default. The SDK takes your request at face value — an uncapped fetch over a large project materializes everything that matches, in memory. Passing the max_* caps (or a narrowing filter) is recommended whenever the result size is not known to be small; if you want pagination, build it from caps and filters on your side.

A client is bound to one workspace for its lifetime. Reading another workspace means another client.

The project is different: it is only a default. Every method takes a project_name= override, and a client used solely for workspace-wide listings never needs one at all.

filter= and order_by= take builder objects — AttrFilter, SeriesFilter, AttrOrderBy, SeriesOrderBy. They cover the full query grammar, validate client-side, and escape values correctly. There is deliberately no raw-string form to get wrong:

from metrana.query import AttrFilter, SeriesFilter
client.fetch_runs(filter=(AttrFilter("config/lr") < 0.01) & (SeriesFilter("loss").last() < 0.5))

See Filters & ordering.