Skip to content

Creating runs

A run is created once, by name, and then written to by as many processes as you like. There are two ways to create one:

  • CreateRun (gRPC or POST /api/ingest/v1/runs) creates the run and fails if it already exists. Pair it with UpdateRuns.
  • InitializeRunLogging (gRPC only) creates the run or attaches to an existing one, and registers the caller as a streaming logger. See Streaming ingestion.

Both take the same Run definition, create_project_if_missing flag and aggregation_rules.

{
"run": {
"workspace": "my-workspace",
"organization": "my-org",
"project": "vision",
"runName": "resnet50-lr3e-4",
"experiment": "lr-sweep",
"directory": "sweeps/2026-09",
"creationTime": "2026-09-30T09:00:00Z",
"orchestrationIdentifier": "slurm-8812345"
},
"createProjectIfMissing": true
}
Field Notes
workspace Must exist. Your token needs member access to it.
organization Optional organization slug; needed only when another organization has a workspace of the same name.
project Created if missing when createProjectIfMissing is true; otherwise a missing project is NOT_FOUND (404).
runName Unique within the project.
experiment Optional. Created on first use. A run’s experiment cannot be changed later.
directory Optional /-separated folder path the run is placed in; missing folders are created. The run can be moved later.
expDirectory Optional folder for the experiment, used only when this call creates the experiment. Defaults to directory.
creationTime Optional; defaults to the time of the call.
forkPoint Optional; see Forking.
orchestrationIdentifier Optional opaque token for the job launch that created the run; see below.

Project names, run names and environment ids appear in portal URLs, so they follow the strictest rules:

  • Not empty, at most 512 bytes, and not starting with :.
  • No whitespace or control characters.
  • None of ( ) [ ] , = < > ! ~ " | — reserved by the query language.
  • None of / \ ? # % — they have meaning in a URL.
  • Not a name reserved for a portal route.

Anything else is allowed, including Unicode. Metric names, scales and attribute paths follow the same rules except that / is allowed (it builds hierarchies such as train/loss); see Limits.

CreateRun is strict: if a run with the same name already exists in the project, it fails with ALREADY_EXISTS. Over REST that is a 409 with a JSON body describing the existing run:

{
"message": "Run already exists: my-workspace/vision/resnet50-lr3e-4",
"creation_time": "2026-09-30T09:00:00+00:00",
"orchestration_identifier": "slurm-8812345"
}

(These keys are snake_case, unlike the camelCase message JSON.) creation_time may be null, and orchestration_identifier is null when the existing run was created without one.

A 409 after a retry is usually good news: the first attempt created the run and only its response was lost. Compare orchestration_identifier with your own to tell that case — or a sibling process of the same job winning the race — from a stale run left by an earlier job that reused the name.

When several processes of one job write to the same run (for example, ranks of a distributed training job), give them all the same orchestrationIdentifier — typically the scheduler’s job id — and give each new job launch a different one. Metrana stores the identifier of the creating request and never interprets it; it is up to 256 bytes of any printable text.

InitializeRunLogging uses it to decide whether an existing run may be attached to; see Resuming an existing run.

A fork starts a new run from a point in an existing one: everything the parent logged up to and including forkStep is carried into the child, which then continues on its own.

{
"run": {
"workspace": "my-workspace",
"project": "vision",
"runName": "resnet50-lr1e-4-from-20k",
"forkPoint": {"parentRunName": "resnet50-lr3e-4", "forkStep": "20000"}
}
}

The parent must be in the same project; a missing parent is NOT_FOUND. For reinforcement-learning series, forkStep is matched against the RL step. The carried-over history is copied asynchronously: you can write to the child immediately, and the inherited points appear shortly after.

aggregationRules declare derived series that Metrana computes while ingesting, for example the mean of a metric across every GPU. They are registered when the run is created. See Aggregation rules.

Write to the run with UpdateRuns or a stream. A run is running while writers are active, closed once every writer has sent closeRun, and marked crashed if its writers go quiet for a long time without closing (15 minutes by default).