Skip to content

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.

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.

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

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.

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_target is 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.

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 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.

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.

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).