EmbodiFlowDocs
Get startedDataWorkflows and algorithmsTraining and deploymentDeveloper reference
  • Workflows and algorithms

Workflows

  • How workflows work
  • Build your own workflow
  • Runs and logs

Algorithms

  • Algorithm catalog
  • Write a custom algorithm

Algorithm developer guide

  • Your first algorithm
    • Standardize
    • Check
    • Transform
    • Enrich
    • Segment
    • Curate
    • Export
  • Image algorithms
  • Use your algorithm in a workflow
  • Interface reference
  • SDK reference
  • Command line
  • MCP tools
  • Troubleshooting

© 2026 EmbodiFlow

llms.txtOpenAPI JSON
  1. Workflows and algorithms
  2. Algorithm developer guide
  3. Image algorithms

Image algorithms

Package an algorithm in any language as a container image that follows the same rules as a Python one.

Python in the browser covers most needs, but sometimes your best code is C++, Rust or a model with its own stack. An image algorithm lets you bring it as a container. The platform treats it like any other step: same categories, same ports, same checks on what it writes. Only the packaging differs.

The arrangement is simple. The container reads a job file and its inputs from fixed folders, writes its outputs to fixed folders and exits with a code. Since there is no decorator to read, you write the interface by hand as algorithm.yaml, and embodiflow algorithm push bakes it into the image label io.embodiflow.algorithm.

Beta. Custom algorithms and workflows are in the product and ready to try, but they haven't been through a full acceptance on real data yet. Expect some rough edges, and check results before you rely on them.

What the container does

  • Read /embodiflow/config/job.json.
  • Read inputs under /embodiflow/input/<port>/ and write outputs under /embodiflow/output/<port>/, in the layouts below.
  • Optionally report progress in /embodiflow/output/progress.json: { "done", "total", "message" }.
  • On a refusal, write /embodiflow/output/error.json: { "code", "message" }, with a code in capital letters.
  • Use /embodiflow/tmp/ for scratch space.
  • Exit with one of the codes below.

job.json

The job file tells your container what it's working on: the run, the item, the parameters, the facts and where each port lives. This one is for an episode-level enrich step.

{
  "contract": "embodiflow-runtime/v1",
  "category": "enrich", "level": "episode",
  "runId": "<uuid>", "stepId": "success", "recordingId": "<uuid>",
  "item": { "episodeIndex": 3, "startS": 120.4, "endS": 161.0, "task": "pick up the cup" },
  "params": { "threshold": 0.5 },
  "facts": { "kind": "human", "stereo": true, "imu": true, "privacy_required": true, "duration_s": 40.6 },
  "inputs":  { "recording": { "type": "recording", "root": "/embodiflow/input/recording" },
               "episodes":  { "type": "episodes",  "root": "/embodiflow/input/episodes" } },
  "outputs": { "features": { "type": "features", "root": "/embodiflow/output/features" } }
}

An optional input that is absent is simply missing from inputs.

Layouts at a port root

TypeLayoutValidated when the step finishes
rawFiles at their upload-relative paths.No check.
recordingThe LeRobot v3 tree plus meta/embodiflow/recording.json.The canonical rules R1 to R7 and embodiflow-recording/v1.
featuresfeatures.json, frames.parquet, episodes.parquet and files/**.embodiflow-features/v1
checkschecks.json and evidence/**.embodiflow-checks/v1
episodesepisodes.json.embodiflow-episodes/v1
versionversion.json and urls.json, with presigned links.Input only.
selectionselection.json.embodiflow-selection/v1
artifactartifact.json and the files.embodiflow-artifact/v1

A per-frame feature needs exactly one row per frame in frames.parquet. A per-episode value is keyed by episodeIndex, its position in the connected episodes document. Times in checks.json and episodes.json are seconds on the recording timeline.

Exit codes

Exit codeMeaningThe step ends
0Done.succeeded
85This data is not for me.not applicable
87The data is broken.failed; the recording is quarantined
88Try again: network, GPU busy.retried, then failed
1A bug.failed; the log is kept

Before exiting with 85 or 87, write the code and message to error.json. The step message then reads <code>: <message>.

algorithm.yaml

This file is the same document a Python decorator produces, with the schema embodiflow-algorithm/v1. Here is the motion energy algorithm from Your first algorithm, declared for an image:

apiVersion: embodiflow-algorithm/v1
name: motion-energy
title: Motion energy
category: enrich
features:
  - name: motion_energy
    type: scalar
    per: frame
    dtype: float32
    unit: none
params:
  step: { type: integer, default: 1, minimum: 1, title: Frame step }
resources: { cpu: 4, memory: 8Gi, timeout: 30m }

Test locally, then register

You don't have to start from an empty folder. embodiflow algorithm init <dir> --category <category> --lang image writes an algorithm.yaml, a Dockerfile with an exec-form ENTRYPOINT and an entry script that already writes the outputs of the category. From there the loop looks like this:

# write my-algo/algorithm.yaml (above) and a Dockerfile by hand
embodiflow algorithm validate my-algo
embodiflow algorithm test my-algo --build --input recording=./rec
docker build -t my-algo my-algo && docker save my-algo -o my-algo.tar
embodiflow algorithm push my-algo --archive my-algo.tar --registry <registry-host>

validate checks algorithm.yaml with the same parser the platform uses. test runs the container on your machine and checks its outputs with the platform's rules. push imports the image archive into your team's registry and registers the algorithm with an image reference pinned to its digest.

An algorithm image is reviewed before it runs in a workflow. Cloud test runs of a saved image algorithm haven't yet been proven on a freshly installed deployment, so rely on algorithm test on your machine for now.

Next

  • Command line
  • Troubleshooting
Previous

Export

Next

Use your algorithm in a workflow