Weights & Biases
pip install 'metrana[wandb]'metrana migrate wandb --entity my-team --project sweeps --workspace my-workspaceHow the hierarchies line up
Section titled “How the hierarchies line up”W&B nests an organization above entities (a team or a personal user account), which own projects:
| Weights & Biases | Metrana |
|---|---|
| organization | — not involved in a migration |
| entity (team or user) | workspace |
| project | project |
| run | run |
An entity is not an organization — it is the namespace that owns projects, which is what a Metrana
workspace is. The command keeps each side’s own vocabulary (--entity for the source, --workspace for the
target) and never derives one from the other, so migrating three teams into three workspaces is three
invocations with an explicit pairing rather than a guessed name transform.
One invocation covers as many of an entity’s projects as you like — --project repeats, and
--all-projects takes every project the entity owns, each into a Metrana project of the same name:
metrana migrate wandb --entity my-team --workspace my-workspace --all-projects --workers 12Runs then migrate concurrently, a worker process per run; see Migrating many runs at once.
Run names
Section titled “Run names”Every migrated run is prefixed with the source: a W&B run named sunny-sweep becomes wandb-sunny-sweep.
The prefix guarantees a migration can never resume into an unrelated Metrana run that happens to share a name.
W&B run names are not unique, so when several runs claim the same target name in one target project, all of
them take their W&B run id as a suffix — wandb-sweep-a1b2c3, wandb-sweep-d4e5f6. Never just the later
ones, which would depend on the order runs were listed. --always-append-id applies the suffix everywhere.
History
Section titled “History”History is read with W&B’s full-fidelity history scan rather than its sampled read, so migrated curves carry
every logged point. Each row’s _step becomes the Metrana step, on the ML_STEP scale, and _timestamp
becomes the point’s timestamp — migrated curves keep their original wall clock.
Two value kinds migrate:
| W&B value | Result |
|---|---|
| A number (int, float, bool) | A float point. NaN and infinity pass through — they are real logged values |
A histogram (wandb.Histogram, i.e. bins + values) |
A histogram point in counts form |
| Anything else — images, video, tables, plots, strings | Skipped and reported |
W&B’s own _-prefixed bookkeeping keys (_step, _runtime, _timestamp, _wandb) are never migrated.
Histograms
Section titled “Histograms”W&B’s bins are edges and values are per-bin counts, which map directly onto Metrana’s counts form.
The two bin limits are the same: wandb.Histogram
rejects more than 512 bins at construction, and so does Metrana — so no histogram logged through W&B is too
large to migrate, and none is ever rebinned to fit.
A histogram is still validated on the way in, and is rejected — and named in the report — when its edges are not
strictly increasing, when there is not exactly one more edge than count, or when its counts are not whole
numbers. wandb.Histogram enforces the edge count too, so these rejections indicate history that was written
by something other than that class.
A key that logged two kinds
Section titled “A key that logged two kinds”A Metrana metric holds one value kind for its lifetime, so a W&B key that logged numbers at some steps and histograms at others cannot migrate as one series. The first kind seen wins; the other kind’s points are dropped, counted, and reported:
skipped 'thing': logged both float and histogram values; kept float dropped 4 point(s) from 'thing'Config, summary, and provenance
Section titled “Config, summary, and provenance”run.config becomes run attributes under config/, matching
metrana.log_config(). W&B’s
{"desc": ..., "value": ...} envelope is unwrapped, and nested dicts keep their structure.
run.summary is filtered before it transfers. W&B auto-populates it with the last value of every history
key, and copying those back would only duplicate what Metrana already derives. Only entries that are scalar
and do not correspond to a migrated series survive — the genuinely user-set ones, like a
best_val_acc written directly or shaped by define_metric(summary="max"). They land under summary/.
Provenance goes under wandb/, so a migrated run always records where it came from:
| Attribute | Value |
|---|---|
wandb/entity, wandb/project |
Source coordinates |
wandb/run_id, wandb/run_name |
The W&B run’s id and its original name |
wandb/url |
Link back to the run in W&B |
wandb/state, wandb/created_at |
Its state and creation time |
wandb/migrated_to |
The Metrana run name it became |
run.tags become run tags and run.notes becomes the run description. All of this is written on every
pass, including a resumed one, so an interrupted migration still ends with complete metadata.
Selecting runs
Section titled “Selecting runs”Without --run, every run in the project migrates. --filter takes W&B’s own MongoDB-style query as JSON and
is passed straight through:
--filter '{"state": "finished"}'--filter '{"config.optimizer": "adam"}'--filter '{"created_at": {"$gt": "2026-01-01"}}'Not migrated
Section titled “Not migrated”System metrics (system.*), artifacts, and W&B’s media types are out of scope today.