Runs & projects
Three methods cover the top of the hierarchy: projects, the experiments inside them, and the runs.
Projects
Section titled “Projects”client.fetch_projects()client.fetch_projects(filter=AttrFilter("sys/name").matches("^rl-"), max_projects=50)One row per project: name, runs_count, experiments_count, then one column per requested attribute path.
Projects are the one resource whose filters and ordering accept attributes only — a project has no series
of its own, so a SeriesFilter is rejected client-side rather than sent and refused.
Experiments
Section titled “Experiments”An experiment is a grouping over runs, so listing them is a list of names:
client.list_experiments()# ['lr-sweep', 'ablations', 'baseline']runs = client.fetch_runs( experiment="lr-sweep", filter=AttrFilter("config/lr") < 0.01, order_by=AttrOrderBy("sys/creation_time").desc(), attributes=["sys/status", "config/lr"], series_summaries=[SeriesSummary("loss", "last")], max_runs=100,)One row per run: name, experiment, then attribute columns (object dtype, None where the run lacks the
attribute), then summary columns (float64, NaN where the run has no such series).
fetch_runs depaginates — max_runs is a cap you choose, not a page size, and the total number of
matching runs is available independently of it:
runs.attrs["total_count"] # matching runs, ignoring max_runs / skipUnlike the series fetches, the runs table has no 1000-run ceiling: its rows are the result, so it pages until you stop it.
Choosing columns without knowing the names
Section titled “Choosing columns without knowing the names”attributes= and series_summaries= also accept a pattern, resolved against the project’s definitions
before the fetch. Useful when you want “everything under config/” without enumerating it:
from metrana.query import AttributeFilter, MetricFilter, SummaryFunction
client.fetch_runs( attributes=AttributeFilter(prefix="config/"), series_summaries=MetricFilter(prefixes=["train/"], functions=[SummaryFunction.LAST]),)AttributeFilter takes prefix (a subtree) or regex (a full-path RE2 match), plus optional kinds.
MetricFilter takes prefixes / regex / scales and the summary functions to apply.
Each pattern costs one extra round trip — the definitions lookup — so an explicit list of columns is the cheaper form when you already know them.
Reading one run’s attributes
Section titled “Reading one run’s attributes”fetch_runs answers “this column across many runs”. For the opposite — every attribute of one run — use the
listing, which returns a plain dict:
client.list_run_attributes("run-001")# {'sys/status': 'CLOSED', 'sys/tags': ['baseline'], 'config/lr': 0.003, ...}
client.list_run_attributes("run-001", filter=AttributeFilter(prefix="config/"))Values come back as Python types: str, int, float, bool, list[str] for string sets, and
datetime for timestamps.