Pipeline settings
Pipeline settings is where a team decides what a run produces and what it costs. Every annotation layer has a mode, optional per-layer configuration, and a model where the layer resolves through a selectable registry surface (see Models per project). A preset sets every mode at once, and the panel shows the cost of the current selection before you spend anything.
A project that never opens this screen behaves exactly as it did before the screen existed. Defaults are computed, not blank.
Layer modes
Each layer is in one of three modes.
| Mode | What it means |
|---|---|
in_run | The layer executes inside the pipeline run. Its output is there when the run finishes, and its cost is part of the run’s cost. |
on_demand | The layer does not run automatically. It stays reachable afterwards through its annotation job or its per-episode endpoint. |
off | The layer never spends. Enqueuing it returns 409 with a message naming the setting to change. |
Applicability gates on top of the mode and always wins. A layer whose data kind cannot carry it is reported as inapplicable whatever mode is stored, and it never spends.
Two guards protect stored settings from going stale:
- An unknown layer id or an invalid mode in stored settings is ignored rather than crashing a run.
- A mode outside the layer’s offered set degrades to the nearest offered one. Asking
in_runof an on-demand-only lane becomeson_demand, not a silent no-op and not an over-run.
How a mode is resolved
The effective mode for a layer is resolved on every read, in this order, most specific first:
project settings > workspace settings > computed use-case default
The computed default is not a constant. It is derived from the workspace’s use case and the project’s target profile so that it reproduces the platform’s behaviour before per-layer settings existed:
- A capability-gated lane (hand pose, dense text) runs in-run only when the use case requests that capability. Otherwise it stays reachable on demand.
- Object labels run in-run only for target profiles that need them, and on demand otherwise.
- Every other layer keeps its catalog fallback mode.
A layer that is catalogued but not yet servable is pinned to off whatever is stored, so a stale setting can never queue work the platform cannot do. Every layer in the catalog is servable today.
Read the resolved state, including what is stored at each level:
curl -fsS -H "Authorization: Bearer $EULER_TOKEN" \
"$EULER_BASE_URL/v1/projects/$PROJECT/annotation/settings"
The response carries the full catalog resolved for the project: effective mode per layer, per-kind applicability with the reason when a layer does not apply, the preset list, and the cost preview. workspace_modes and project_modes show what is actually stored at each level; empty means inherit.
Setting modes
Write project-level overrides with PUT. Every part of the body is optional: omitting a field leaves it untouched, and an empty object clears it back to inherit.
curl -fsS -X PUT -H "Authorization: Bearer $EULER_TOKEN" \
-H "Content-Type: application/json" \
"$EULER_BASE_URL/v1/projects/$PROJECT/annotation/settings" \
-d '{
"modes": {
"depth": "on_demand",
"optical_flow": "off",
"hand_pose": "in_run"
}
}'
Workspace defaults, which every project without its own override inherits, are written separately:
curl -fsS -X PUT -H "Authorization: Bearer $EULER_TOKEN" \
-H "Content-Type: application/json" \
"$EULER_BASE_URL/v1/workspaces/$WORKSPACE/annotation/settings" \
-d '{"modes": {"captions": "in_run", "metadata": "in_run"}}'
Both writes need the engineer role and are audited as a policy change.
Presets
A preset is a one-click bundle of per-layer modes for a use-case shape. Apply one by id; layers the preset does not name fall back to their catalog default. Explicit modes in the same request win on top of the preset.
| Preset | What it turns on | Written for |
|---|---|---|
readiness-only | Measure and certify. No annotation spend beyond captions. | Any workspace |
egocentric-full | The full first-person stack: hands, captions, objects, sub-tasks, dense actions and metadata in the run; body pose, tracks, segmentation, depth and flow on demand. | Egocentric annotation on first-person capture |
exocentric-annotation | Sub-tasks, dense actions and event tags in the run; objects and tracks on demand. | Third-person video annotation |
manipulation-qc | Captions, objects, sub-tasks and metadata in the run; the heavy lanes on demand. | Manipulation, humanoid and mobile work on teleoperated data |
drive-log-lite | Detection first: objects, captions and metadata in the run; tracks, segmentation, depth and flow on demand. | Driving perception on drive logs |
world-model | Geometry first: depth, flow and segmentation in the run, with captions and metadata, and the 3D scene on demand. | Spatial, aerial, manipulation and humanoid work |
everything | Every applicable layer in the run. | Any workspace |
Presets are scoped to the work you are doing. The panel only offers the presets written for your workspace’s use case, because a drive-log bundle on a teleoperation project reads as a product that does not know what you ingested. A preset whose in-run layers cannot apply to anything this project ingested is shown disabled, with the reason the layer does not apply.
The scope shapes the picker, not the API: applying any preset by id over HTTP still works, so an integration is never blocked by a scoping decision made for a screen.
curl -fsS -X PUT -H "Authorization: Bearer $EULER_TOKEN" \
-H "Content-Type: application/json" \
"$EULER_BASE_URL/v1/projects/$PROJECT/annotation/settings" \
-d '{"preset": "manipulation-qc"}'
Per-layer configuration
Beyond the mode, each layer exposes typed knobs. Send them under config, keyed by layer id:
curl -fsS -X PUT -H "Authorization: Bearer $EULER_TOKEN" \
-H "Content-Type: application/json" \
"$EULER_BASE_URL/v1/projects/$PROJECT/annotation/settings" \
-d '{
"config": {
"object_labels": {
"ontology_source": "manual",
"classes": ["gripper", "cable", "connector"],
"confidence_floor": 0.45
},
"depth": {"density": "keyframes"}
}
}'
Configuration resolves the same way modes do: catalog defaults, then workspace config, then project config. Submitted values are coerced against the layer’s schema rather than rejected: unknown keys are dropped, numbers are clamped to their range, and integer-stepped fields stay integral. A stale setting from an older catalog version can never break a run or lock a team out of the screen.
The full field list per layer, with types, ranges and plain-language help, is in the settings response and on the annotation layers page. Fields marked as cost-affecting in the response are the ones that move the estimate.
Only settings the platform actually reads are offered. The rendered-overlay-video settings went with the rendered videos, and several depth and 3D options that nothing read were removed; a value saved for one of them earlier is dropped quietly and cannot break a run.
Re-derive from stored data
Below the layers, Re-derive from stored data rebuilds things from what is already stored, with no GPU and no spend:
- Rebuild 3D from stored depth: re-derives the point clouds (in colour from the video), the smoothed camera path and the 3D hands.
- Keep only the wearer’s hands: on first-person data, drops hands that belong to someone else in frame. Preview first; the unfiltered file is kept.
- Clean up object tracks: merges duplicate tracks, chains re-detections and drops flickers.
- Re-route review under the current rules: recomputes every automatic accept or review decision from today’s readiness and certificate rules. Human decisions are never changed.
The Readiness metrics tab has the matching Re-measure from stored data. Each of these works through the project a few episodes at a time and shows progress and an estimate; keep the tab open until it finishes.
Models per project
Some surfaces let a team choose between options we have benchmarked ourselves: hand pose, object detection, object masks, depth, 3D hands and the language passes. Each option has a plain name that says what it adds, such as Multi-scale or Agreement and kinematic checks for hand pose, and experimental options say so. Most surfaces are fixed.
A choice can be made at two levels, and the more specific one wins:
set by operations > project choice > tenant default > workspace default > platform default
- Tenant default. Settings, Tenant, Model defaults sets what every project in the tenant uses unless it chooses otherwise.
- Project choice. Settings, Project, Models for this project (and the same picker on each layer in Pipeline settings) sets a model for one project only. Every picker says where its current choice comes from. Use tenant default hands the surface back to the tenant default.
- Set by operations. When operations pins a model for the whole deployment, the picker says so and that pin wins until it is lifted.
Over the API, write a project choice with models in the same request, using an option id from GET /v1/models; anything else is refused with 422. models replaces the project’s whole map, so send every choice you want to keep, and leave a surface out to go back to the tenant default. The settings response lists each surface under model_choices with its current choice and its source (env, project, tenant, use_case or default).
curl -fsS -X PUT -H "Authorization: Bearer $EULER_TOKEN" \
-H "Content-Type: application/json" \
"$EULER_BASE_URL/v1/projects/$PROJECT/annotation/settings" \
-d '{"models": {"hand_pose": "rtmdet-nano-hand+rtmpose-m-hand5+dwpose+savgol+multiscale"}}'
A choice applies from the next run or job; nothing already produced changes.
Cost preview
The settings screen prices every layer before you spend, on the meter it is billed on:
- Per layer. Each layer set to run shows its own estimate per episode and for the project, so you can see which layer drives the cost.
- Per hardware class. GPU layers are priced on the class of GPU they actually run on; geometry and 3D run on a larger card than the rest, and the estimate says which.
- Measured. A layer whose rate was calibrated against real metered runs carries a measured badge; the others are estimates and say so.
The same figures appear in the run confirmation before a run starts (see Running the pipeline). The estimate is also the pre-flight budget guard: work whose estimate would breach the tenant’s weekly cap returns 402 instead of starting and failing partway. What is metered afterwards is the measured cost. Read the cap and rolling spend with GET /v1/budget and GET /v1/costs.
What actually ran
Settings describe intent. To see what landed, use the status view:
curl -fsS -H "Authorization: Bearer $EULER_TOKEN" \
"$EULER_BASE_URL/v1/projects/$PROJECT/annotation/status"
Every layer reports one honest state: ran, partial, on_demand, off, inapplicable (with the reason) or planned, along with covered and applicable episode counts and whether it ran in the last run. For per-layer quality rather than presence, use GET /v1/projects/{id}/annotation/coverage.
Next
- Run an on-demand layer: Annotation jobs.
- See the same per-layer state one recording at a time: Review workbench.
- Configure what readiness measures: Readiness.