Models and machine learning
A model in cortex is a trained, versioned artifact: deterministic, evaluated by a metric, traceable to the data commit it was trained on. A model never chooses its own inputs or tools, so models have their own surface (Build, Models), registry and engine, with a version history, an evaluation metric, lineage and a promotion pointer. The engine is shared by every project and extended per project in its fork.
The engine
The engine is data in the shared platform engine, inherited by every fork: one model service and these operations.
| Operation | Input | Output |
|---|---|---|
| Train | A SQL query over the governed tables (row id first, then target and feature columns), the target column, the task, the algorithm, a feature specification or a series contract, the model name and version | Metrics with a primary one, global feature importances, the artifact reference and checksum, the framework, the parameters, the row count |
| Predict | The artifact reference, the records, an optional threshold | One prediction per record (score and label; a value for regression; a forecast path for series) and the count |
| Batch score | The artifact reference, a query, the id column, an optional output table, the model name and version | An upsert into the prediction table (entity id, model name and version, score, label, detail); how many were scored and flagged |
| Catalogue | None | The engine's tasks and algorithms with their contracts, merged with the fork's own declarations |
Batch scoring is also a registered pipeline transformation kind. Training and scoring requests pass through an action-allowlisted proxy; no fitting or scoring happens in the platform backend. The registry is ordinary records under the same access rule as agents. Artifacts live in object storage under the project's prefix, one folder per model and version. The model version stored beside every prediction lets an application or a workflow answer "why was this row flagged" months later.
Tasks and algorithms
| Task | Algorithms | Family | Fits | Primary metric |
|---|---|---|---|---|
| Classification | Gradient-boosted trees (default), random forest, extra trees, logistic regression | Tabular | Rows to a yes/no label | ROC-AUC, cross-validated |
| Regression | Gradient-boosted trees, random forest, extra trees, ridge regression | Tabular | Rows to a number | MAE, with MAPE, RMSE, R² and cross-validated MAE |
| Regression on time series | Exponential smoothing with trend and season, seasonal ARIMA, piecewise trend with seasonal harmonics | Series | One series per group, forward to a horizon | MAE and MAPE on the same held-out last horizon of every series |
A tabular algorithm takes a feature specification (columns and their types). A series algorithm takes a series contract: the time column, the grouping column, the horizon and the seasonal period. Every series candidate is evaluated on the same holdout, so their errors compare. Scoring a series model refits on the latest series per group and lands the forecast at the horizon as the score, with the whole path in the prediction's detail. A proportion is a regression target, never a classifier over synthetic slots.
The catalogue lists keys, labels, families, tasks, parameters, steps, the series contract and the fork contract. The Models page and the assistants render from it, so a new shared algorithm is an edit to the model service with no cortex release.
Versions and lineage
Training starts from the Models page ("Train a version"), from the training tool of the project's MCP endpoint, or from the proxy an application uses. The operation that starts training writes the registry row, because the lineage exists only at that moment. A version records its number and status, the configuration commit the training data came from, the training query, the feature specification, the algorithm, task and parameters the engine actually used, and the result: metrics with a primary one, global feature importances, the framework, the artifact reference and its checksum. One version is active. "Promote" moves the pointer, and consumers reading the active version follow it.
Every model is also a manifest endpoint on the fork, discovered like agents. The manifest carries the versions and a precomputed active metric, the cross-validated figure, so a consumer cannot quote the single-split number by accident. Model manifests are never cached because they change on every training run.
Extending the engine in a fork
Only the prebuilt algorithms are shared. A project that needs another estimator, a domain-specific forecaster or a library the shared service does not ship extends the engine in its own fork. The shared service is never edited and never executes project code.
- Author a model service on the fork with train, predict and batch score under the contracts above.
- Declare it as one algorithm-declaration endpoint, which returns the algorithm's manifest (name, label, family, tasks, service, description, steps) when called without an operation and forwards to the service otherwise. Removing the declaration leaves the service in place.
- Train with the algorithm chosen as "this project's own". The shared operations route to the fork by project identity, because an inherited endpoint runs in the shared engine's own project and cannot see fork endpoints by name.
The catalogue then lists the algorithm as the project's own, and the version row records the fork algorithm and its service as the framework. A naive-drift series forecaster ships with the fleet's engine recipe as a working template.
The Models page
Build, Models lists the project's models with their active version and metric. A model's page has Versions & training (train, promote, metrics, lineage with the configuration commit, importances), an Algorithm tab describing the version's algorithm from the catalogue, and sharing. The model runner tries one record against the active version and shows the input contract with real examples, the score, timing and every place the model is used. A Model Lab compares candidate forecasts side by side under one rule: each candidate is a distinct algorithm, never the same estimator over another feature list.
The stamped Models Assistant agent trains, scores and explains models in chat through fork-local tool wrappers. The project's MCP endpoint offers tools to list models, read one, train a version and score records.
Access and sharing
Model registry rows carry the access model of agents and applications: an owner, explicit shares, organisation visibility, administrator override. Promotion and deletion require management rights; training and scoring require project access; declaring a fork algorithm requires project write access (Security and operations).
Asking for a model
A "new model" or "change model" Board card is filed from "New task" or from a Docs requirement whose text names a learned prediction. The requirement chain files a model card for such requirements rather than an application change (Requirements and knowledge). The fleet trains through the same engine and hands back the manifest.
Where a model is used
| Surface | Mechanism |
|---|---|
| Pipeline | Batch scoring dropped as a node scores a whole table on each run and upserts the prediction table; regression predictions carry a value and no label. Scoring a table is a pipeline node, never a workflow step (Data governance and pipelines) |
| Workflow | A code step calls predict, putting score and label into the run context; a decision node branches on them, risky records to a human gate. The artifact reference should come from the active version so the process follows promotions (Business workflows) |
| Application | The Models companion, on by default in Viewer options, embeds the Models page so viewers see what each model predicts, how it scores and which commit trained it (Applications) |
| Chat and MCP | The Models Assistant in the project chat; the training and scoring tools for an external MCP client |
Tests over a model's behaviour are declared like any other requirement test (Tests and health).