Concepts
Anatomy of a pipeline — segment, models, schedule, and the automation around them.
Anatomy
Every pipeline has four parts:
| Part | What it is | Field(s) |
|---|---|---|
| Segment | The data view trainings run on | segment |
| Models | What gets trained — a pool of models, any mix of kinds; the best score wins | models |
| Schedule | When trainings fire | training_schedule |
| Automation | What happens around each run | promotion_policy, retrain_triggers, budget |
One way to reference a model
Every entry in models is the same shape, whatever the model is — a
custom model from your catalog, or a foundation model. Reference it by
catalog ID, or use family + slug shorthand for foundation models:
{
"models": [
{ "model": "MODEL_ID" },
{ "family": "predictfm", "slug": "predictfm-f-v0.1" },
{ "family": "chronos_bolt", "slug": "chronos-bolt-base", "lookback": 1024 }
]
}You never declare what kind a model is; the platform resolves that from
the reference. Foundation entries accept two per-entry tuning knobs:
intensity (adapt by default — how much fine-tuning to do) and
lookback (how much history the model sees per window).
forecast_horizon is not per-entry — it's pipeline-level, so every
entry predicts the same target and scores stay comparable.
Schedules
training_schedule defines when runs fire:
{
"training_schedule": {
"start_time": "02:00:00",
"end_time": "05:00:00",
"days": ["monday", "wednesday", "friday"],
"frequency": "86400",
"timezone": "UTC"
}
}days+start_time/end_timedefine the windows in which the scheduler may fire;frequencyis the minimum seconds between runs.- Run once: omit the schedule (or send an empty
daysarray) and the pipeline trains exactly once at creation, then only when you trigger a run or a retrain trigger fires.
The model pool
A pipeline isn't limited to one model. The entries in models are a
pool of equals: every run trains all of them, on the same
segment — the segment fixes the features and labels and the shared
forecast_horizon fixes the target, so the scores are directly
comparable. Order carries no meaning beyond display:
{
"models": [
{ "model": "MODEL_ID" },
{ "model": "ANOTHER_MODEL_ID" },
{ "family": "chronos_bolt", "slug": "chronos-bolt-base" }
]
}Each dispatch is a cycle: all entries train, all get scored, and the
best-scoring result — whichever model produced it — becomes the promotion
candidate. The candidate is always measured against the version that's
currently serving, never against another entry in the pool. When a
cycle produces a better result than what's serving you also get a
pipeline.new_best notification with both
scores. This is how you A/B model architectures — or race a foundation
model against your own — without duplicate pipelines.
A few rules: entries are deduplicated, each must be a model you own (or a
public one), and BYOM models can't enter a training cycle (they arrive
pre-trained, so a BYOM pipeline references exactly one model). There's
deliberately no cap on the list — every entry is a full paid training per
cycle, so the real brakes are your credit balance, the pipeline's
budget, and your plan's training quotas.
Promotion policy
promotion_policy decides what happens when a cycle's winner beats what's
currently serving:
{ "promotion_policy": { "mode": "auto", "demote_previous": true } }auto— the winner deploys itself; withdemote_previous: true(the default) the previously serving version is retired.manual(default) — the pipeline records a pending decision and waits. You resolve it withPOST /v1/pipelines/{id}/promotion-decision.off— trainings accumulate but nothing is ever proposed or deployed automatically.
The mechanics of serving live in Deployments.
Guardrails
- Budget —
budget.monthly_credit_capcaps a pipeline's monthly training spend; runs that would exceed it don't dispatch (nullor0means no cap). - Retrain triggers —
retrain_triggers.on_new_datafires a run when enough new rows land on the segment, independent of the schedule (tunablemin_rows,quiet_seconds,max_wait_seconds,cooldown_seconds). - Plan quota — each plan caps pipelines per workspace; creation past
the cap returns
403.

