Skip to main content
That is the whole thing for most people — the Python SDK speaks this contract for you. Read on only if you are writing an adapter for a framework the catalog does not cover, or a client in another language.

What the platform injects

Four environment variables arrive in every training container. Your code reads them; it never receives account credentials, cluster addresses, or object-store keys. Authenticate with X-StarForge-Token: <token>. The routes also accept Authorization: Bearer <token>, which is what a client that already has a bearer helper will do naturally.

The endpoints

All are POST, all take JSON, all include run_id.
Events are starting, running, succeeded, failed.Report running immediately before you hand control to the training entrypoint. The executor’s own RUNNING is much earlier — it fires before the virtualenv is built and the weights are pulled, which can be several minutes — so using it as the billing start systematically overcharges.
Returns {"ok": true, "inserted": 2}. Points are already flattened: one scalar per key, per step. Nested dictionaries and non-scalar values are the caller’s problem to reduce first.
Upserts, so calling it again with more keys adds them. Flatten nested config with dots.
user, assistant, env, and reward are the skeleton the console renders. Anything algorithm-specific — DPO’s rejected completion, SFT’s reference answer — goes in each sample’s extra and is displayed without the platform needing to know what it is.Large validation rounds split across chunks: set total_chunks and send each with its own chunk_index.
The one channel where a caller must swallow its own errors. Every other ingest route fails loudly because losing a metric or an artifact is a data incident; losing a few log lines is not, and a momentary console hiccup must never turn a successful training run into a failed one.Do not send eof yourself. The platform sets it when the job reaches a terminal state, because a container killed with SIGKILL never gets the chance.
Kinds are checkpoint, hf_export, eval_report, merged_model. format is required and must not be empty.On a container executor, path must be an object-store URI. A local path stops existing the moment the container does, and the platform will not guess where it went. GET /api/ingest/artifact/upload-url hands you a signed URL to PUT to first.
hardware takes sampled points (GPU utilisation, memory, network). environment takes the static picture once: package versions, CUDA version, GPU models. environment/nodes reports per-node hardware for a multi-node run.The SDK collects and sends all three for you unless you pass monitor_hardware=False.
For a harness that scores outside the platform and reports back. See benchmarks for the workflow that surrounds it.

Confirm it worked

Open the job in the console. The Charts tab shows a point within a few seconds of your first metrics call. If logs are streaming and charts stay empty, the reporting call is not happening — check that STARFORGE_ENABLED is 1 inside the container, and that your code reached init().
Lifecycle marks and artifact registration are how the platform knows a job really started and what it produced. If that code shipped inside the user’s own common/ directory, deleting or breaking that directory would blind the platform — and the person doing it would have no way to know. It is also why the module depends on nothing but the standard library: it has to import cleanly inside any training image, and every dependency is one more way for that to fail.