How the platform works
This page describes how the platform behaves, whether you drive it with the CLI yourself, through the agent skill or over the REST API, since those only differ in how you phrase a request. The commands are in the CLI reference and the requests in Using the REST API.
Entities and jobs
Section titled “Entities and jobs”Each stage of the pipeline produces one entity, and each entity is created either from files you supply or by running a job over the entity before it. That chain is the pipeline:
traces ─► traces ─────────► seed dataset ─┬─► teacher evaluation
(with test set) └─► training dataset ─► SLM ─► deployment
A traces object is uploaded, or created from an inference endpoint’s records. The
test set from traces job builds an updated traces object from it
that carries a test set. A seed dataset comes from trace processing over a traces object, or
directly from a directory of files. Everything downstream is created by naming the ID of its
parent, so keep each ID as you go. If you lose one, distil <group> list shows every entity of a
group with its parent’s ID.
An uploaded traces object and a seed dataset created from files run no job: their status is
JOB_SUCCESS as soon as the create returns, and their logs are empty.
Job status
Section titled “Job status”| Status | Meaning |
|---|---|
JOB_NOT_STARTED |
accepted, not yet scheduled |
JOB_PENDING |
scheduled, waiting for capacity |
JOB_RUNNING |
running |
JOB_SUCCESS |
finished; outputs readable |
JOB_FAILURE |
failed |
JOB_STOPPED |
stopped deliberately |
Deployments report deployment_status and endpoint_status instead of status.
Creating a job returns its ID at once, and only the status says how the job is going. How long a job takes depends on the size of the data and the problem: a small dataset finishes in minutes. Typical durations for a full-size run:
| Stage | Typical duration |
|---|---|
| Test set from traces | scales with num_traces_to_relabel and num_synthetic_examples |
| Trace processing | 45 min |
| Teacher evaluation | 30 min |
| Synthetic data generation | 90 min |
| Model training | 90 min |
| Deployment | 40 min |
Reading a failed job
Section titled “Reading a failed job”When a job fails, its log holds the cause, but not always at the end. A crash often ends with a
second, unrelated error, so an out-of-memory failure can finish with a pickling error thousands
of characters after the OutOfMemoryError that caused it. Search the log for the first error
rather than reading the last one.
A failed job produces no metrics. Fix the cause and submit again: the retry is a new entity from the same parent. Config and job description are readable on some failed entities and not others, so keep a copy of what you submitted.
Smoke runs
Section titled “Smoke runs”Synthetic data generation and training take a --smoke flag that runs the job small, on the same
parent and otherwise with the same config:
- Synthetic data generation smoke:
synthgen.generation_targetis set to 128. - Training smoke: one epoch on the 128 longest train rows and the 32 longest test rows of the training dataset. The rows are chosen by length alone, not per class.
Both accept config and job-description overrides, and both spend their own credit routes, never a full-run credit. Trace processing has no smoke flag: its smoke downloads the traces, trims them to a subsample, and uploads that as its own traces object.
Overrides
Section titled “Overrides”A job’s config.yaml and job_description.json can each be varied at submission. An iteration
is the same parent submitted again rather than a new job input, so several attempts can all point
at one seed dataset.
Two rules govern this. Neither raises an error when you get it wrong.
An override reaches the config and the job description and nothing else. Changing the data means a new entity: a new upload for different traces, a new seed dataset for different rows. See Config file and the CLI reference.
Credits
Section titled “Credits”Credits are metered per route rather than from one pool, so a balance is a count of remaining
calls to that route. Reading the balance (distil credits-balance) is free and answers at zero.
| Stage | Route key | New account starts with |
|---|---|---|
| Trace upload | prepared_traces_post |
100 |
| Test set from traces | prepared_traces_with_expanded_test_set_post |
20 |
| Trace processing | seed_datasets_from_prepared_traces_post |
20 |
| Seed dataset from files, also the validator | seed_datasets_post |
100 |
| Teacher evaluation | teacher_evaluations_post |
20 |
| Synthetic data generation, smoke | training_datasets_from_seed_datasets_smoke_post |
100 |
| Synthetic data generation, full | training_datasets_from_seed_datasets_post |
5 |
| Full training dataset download | training_datasets_download_get |
0 |
| Training dataset from files | training_datasets_post |
100 |
| Model training, smoke | slms_from_training_datasets_smoke_post |
100 |
| Model training, full | slms_from_training_datasets_post |
2 |
Model upload (distil slm create) |
slms_post |
0 |
| Deployment | deployments_from_slms_post |
2 |
| Inference endpoint | inference_endpoints_post |
10 |
Two routes start at zero, so what they gate is unavailable until you ask for a grant at contact@distillabs.ai. Read a balance against your whole plan rather than the next submission: N training runs need N credits, and a synthetic data run is wasted if no training credit is left after it.
A call against an exhausted route is refused. A failed job spends its credit like any other.
Only metered routes appear in a balance. A route the platform never charges for is absent rather than reported as unlimited, so a missing key isn’t a zero.
What each stage produces
Section titled “What each stage produces”| Entity | Metrics | Files | Config + job description |
|---|---|---|---|
| Traces object | original-model score and predictions, built by test set from traces only | traces, test data | free |
| Seed dataset | - | train, test, unstructured | free |
| Teacher evaluation | teacher score, its predictions | - | free |
| Training dataset | train and test size in bytes | credit gated; a free sample instead | free |
| SLM | base and tuned scores, the tuned model’s predictions | model tarball (the LoRA adapter) | free; also the inference client |
| Deployment | - | - | - |
Metrics and files answer once that entity’s own job reaches JOB_SUCCESS. Before that a metrics
field is null and a download names the job’s state and fails. Config and job description are
settled at submission, so a teacher evaluation or SLM answers within seconds of the create; a
training dataset answers only once its job succeeds.
Three conditions apply on top of that table:
- Only a traces object built by the test set from traces job has metrics, and only when that
job ran with
traces_to_test_set.evaluate_original_model: true. They hold the score of the production model on the relabeled test traces (Metrics). - An SLM reports both scores but only the tuned model’s predictions. The base-versus-tuned gap is available as numbers; a base-model failure case isn’t.
- The free training dataset sample is capped at 128 rows drawn from the training data, and never contains test rows; take those from the parent seed dataset, whose download is free. The training data holds the seed rows and the generated rows together, and nothing in a row says which kind it is.
Runs aren’t reproducible
Section titled “Runs aren’t reproducible”The teacher generates and the judge scores at non-zero temperature, so the same config submitted
twice gives different data and different numbers. base.random_seed doesn’t pin this. Treat
every score as a sample (Variation between runs).