Sable Autopilot
Autopilot watches an account's real metered usage, proposes a cheaper or faster Model Foundry configuration, and proves the swap is safe by running your eval suite against both the current and the proposed spec and showing the receipted comparison. One action adopts it. One action rolls it back.
Autopilot is built and tested. It is not on the production deployment yet,
so the calls below describe a surface you cannot reach at api.buildsable.com
today.
It never changes anything on its own
That is the design constraint, not a caveat. An optimizer that silently rerouted traffic would destroy the proposition the whole gateway rests on: a signed receipt is worth something only because nobody moved the thing it describes.
So Autopilot produces a proposal with evidence attached and stops. Adoption
is an explicit owner action at Admin — the same bar publishing a foundry
version sets, because it changes what foundry/<slug> does for every caller in
the account, live. And a proposal whose evidence says regression cannot be
adopted by anyone, with no override, ever.
Adoption goes through the Foundry's own handlers in process. Autopilot
does not write a single row of foundry_builds itself, so version numbering
under the family lock, the never-reused version rule, the at-most-one-published
constraint, ownership checks on the referenced policy and rule sets, the sealed
prompt and the spec digest are all still enforced by the code that owns them.
Autopilot is a caller of the Foundry, exactly as a human with a browser is.
Rollback needs no machinery
The version that was published before adoption was never mutated, so publishing it again restores the previous configuration exactly. The adopt response names that call for you:
"rollback": {
"method": "POST",
"path": "/v1/foundry/builds/<previous build id>/publish",
"restores_spec_sha256": "9f3a…",
"note": "Publishing the previous version again restores the exact configuration this replaced — the row was never mutated, so nothing about it was lost."
}
The repricing guard
An optimizer that always finds a saving is a tell that it is guessing.
Before projecting any saving, Autopilot reprices the baseline's own
observed token mix at catalogue prices and compares the result to what the
account was actually billed. If the two disagree by more than the allowed
divergence, no proposal is produced at all and the divergence is reported
as repricing_disagrees with all four numbers.
This is the load-bearing honesty mechanism. Several real things make the two figures diverge — a flagship id whose engine chain served a different upstream than the id's own list price, prompt-cache passthrough discounts, a fleet node's self-report being clamped, a margin change mid-window — and in every one of those cases the arithmetic Autopilot is about to project with is not the arithmetic that billed.
If it cannot reproduce the bill you already have, it has no business predicting the bill you would have had.
The same conservatism runs through every other threshold. Each refusal is a fixed class carrying the figures that decided it:
| Class | Meaning |
|---|---|
no_traffic | Nothing ran against this build's base model in the window. |
too_few_requests | The token mix is still noise. |
too_little_spend | Any saving would be smaller than the cost of the evidence runs that would justify it. |
repricing_disagrees | The guard above. |
no_eligible_candidate | Candidates were considered; none can carry this traffic — its largest prompt, its modality, or its confidentiality tier rules them out. |
saving_below_threshold | A cheaper candidate exists, but the saving is inside the noise of a shifting token mix. |
What the analysis is allowed to know
Only figures Sable actually has: real usage_events for the account in the
window (request counts, prompt and completion tokens, billed cost, observed
latency); real catalogue prices with the deployment's own margin
applied, so a projection is in the units you are actually charged; and real
observed latency, only for models this account has itself run in the same
window. Autopilot never quotes a latency for a model it has not served — that
would be an invention, and an invention is the one thing this feature cannot
afford.
There is no quality model. Autopilot does not know, guess, or imply that one model is as good as another. That question is answered by your eval suite, on your own cases, and by nothing else. A proposal without evidence is a priced hypothesis, and the API says exactly that.
Attribution, honestly
usage_events.model records the base model, because a foundry build
rewrites the request's model id to the base model before anything is
metered. A build's traffic is therefore not separately attributable, and a
window's figures describe every call to that base model on the account —
foundry-routed or not.
Every proposal carries "attribution": "base_model" and says this in plain
words. It is not a defect to be hidden; it is a bound on what the figures mean.
Evidence
Both arms execute your eval suite through the ordinary in-process chat path,
under one of your own API keys. Holds, spend caps, key policy, guardrails,
metering and signed receipts all apply with no new enforcement code — which is
what makes the pass rates mean anything at all: they were produced by the same
path a paying request takes. Each arm's receipts are chained into one run
id, so GET /v1/runs/{id} folds a whole arm into a head hash a third party can
verify.
| Verdict | Meaning | Adoptable |
|---|---|---|
equivalent | The candidate scored at least as well as the baseline, within tolerance. | yes |
improvement | The candidate scored better. | yes |
inconclusive | The comparison could not be made: too few cases, or an arm where some case never produced a completion. A model we could not reach did not score zero. | only with acknowledge_no_evidence |
regression | The candidate scored worse. | never, by anybody |
inconclusive is a real, expected outcome. It is never presented as
equivalent, and it does not by itself authorise adoption — the honest
statement there is nobody has checked, not it is worse, which is why an
owner may override it and may never override a regression.
The default equivalence tolerance is zero basis points: any drop in pass rate is a regression. A suite too small to tell noise from signal should say so through the minimum-cases threshold, not be papered over with a tolerance.
Proven: that on these declared cases, at this time, the candidate scored this much against the baseline, with both arms run through the ordinary metered, receipted path and every receipt chained into a verifiable run.
Not proven: that the candidate is better in general, that it will hold on traffic the suite does not cover, or that the projected saving will be realised on a token mix that changes — a cheaper model that needs more output tokens to say the same thing will not save what is projected. A proposal is a priced hypothesis, never an instruction.
Evidence is opt-in and costs money
Passing an eval_suite_id runs your suite twice — once per arm, per case —
through the real billed path. That is the point, and it is also a bill, so it
never happens implicitly and never happens on the background pass. One
analyze call gathers evidence for at most four proposals; the rest are
reported in evidence_skipped with the call that would cover them.
Evidence runs are capped at 50 cases and 512 completion tokens per case.
Quickstart
# Priced hypotheses only: no eval_suite_id, so nothing extra is billed.
curl -s https://api.buildsable.com/v1/autopilot/analyze \
-H "Authorization: Bearer $SESSION" \
-H "Content-Type: application/json" \
-d '{"window_days": 7}'
# {
# "window_days": 7,
# "targets": [{"target":"triage","observed":{…},"analysis":{…},"minted":["…"]}],
# "proposals": [ … ],
# "evidence_gathered": false,
# "note": "No evidence was gathered. Each proposal is a priced hypothesis; pass an
# `eval_suite_id` to run your own suite against both configurations before adopting.",
# "trust_model": "An Autopilot proposal is a PRICED HYPOTHESIS, never an instruction…"
# }What adoption refuses
| Class | Meaning | Overridable |
|---|---|---|
not_open | Already decided. Decisions are not re-run. | no |
spec_moved | The published spec is no longer the one this proposal reasoned about, so its figures describe a configuration that is not there any more. | no |
spec_corrupt | The stored candidate spec does not hash to its recorded digest. | no |
spec_drift | The version drafted from the proposal hashes to something other than what was promised. The draft is left unpublished and named, and the model id still serves what it served before. | no |
evidence_regression | The candidate passed fewer basis points of your own suite than the baseline. | never |
no_evidence | Nobody has checked. | acknowledge_no_evidence |
evidence_inconclusive | Evidence exists but could not establish equivalence. | acknowledge_no_evidence |
The spec_drift check runs between drafting and publishing: if a catalogue
move or a revoked policy changed the digest, publishing anyway would make the
whole audit trail decorative. Adoption also refuses if the published
build's system prompt is not the one the proposal was built from —
Autopilot swaps the base model and carries the prompt across verbatim, so a
fingerprint that does not match means the two have drifted.
Adopting supersedes every other open proposal for the same target, because they all reasoned about the spec that was just replaced.
reject is refused on a proposal that was adopted: an adoption is a published
foundry version, and pretending it had been rejected would make the record
disagree with what the model id actually serves.
Verify a proposal without trusting the API
- Recompute the projected saving from
figuresand the public price sheet atGET /v1/models. - Verify each arm's receipts by folding its run chain at
GET /v1/runs/{id}and checking any receipt atPOST /v1/receipts/verify. - Confirm the adopted configuration by comparing
to_spec_sha256against the published build'sspec_sha256atGET /v1/foundry/resolve/{slug}.
Configuration
| Variable | Default | Meaning |
|---|---|---|
SABLE_AUTOPILOT_WINDOW_DAYS | 7 | Observation window. |
SABLE_AUTOPILOT_MIN_REQUESTS | 50 | Below this the token mix is noise. |
SABLE_AUTOPILOT_MIN_SPEND_MICRO_USD | 100000 | Below this a saving cannot pay for the evidence. |
SABLE_AUTOPILOT_MIN_SAVING_BPS | 1000 | Smallest saving worth proposing (10%). |
SABLE_AUTOPILOT_MAX_REPRICE_DIVERGENCE_BPS | 1000 | How far the repricing may miss the real bill before Autopilot refuses to project. |
SABLE_AUTOPILOT_MIN_LATENCY_SAMPLES | 20 | Observed requests needed before a latency claim. |
SABLE_AUTOPILOT_MIN_LATENCY_GAIN_BPS | 2000 | Smallest latency gain worth proposing (20%). |
SABLE_AUTOPILOT_MIN_EVIDENCE_CASES | 5 | Below this a suite cannot establish equivalence. |
SABLE_AUTOPILOT_EQUIVALENCE_TOLERANCE_BPS | 0 | Pass-rate drop tolerated before it is a regression. |
SABLE_AUTOPILOT_PROPOSAL_TTL_DAYS | 14 | An open proposal older than this goes stale. |
SABLE_AUTOPILOT_TICK_MAX_ACCOUNTS | 50 | Accounts refreshed per background pass. |
Endpoints
| Method | Path | Role | Notes |
|---|---|---|---|
POST | /v1/autopilot/analyze | Member | Look at real usage now and propose. Body: {targets?, window_days?, eval_suite_id?, api_key_id?}. Spends credit when a suite is attached. |
GET | /v1/autopilot/proposals | Viewer | Open and decided proposals. |
GET | /v1/autopilot/proposals/{id} | Viewer | One proposal with all of its evidence, plus applies_to_current_spec. |
POST | /v1/autopilot/proposals/{id}/adopt | Admin | Publish the proposed configuration as a new foundry version. Body {acknowledge_no_evidence?, name?}. |
POST | /v1/autopilot/proposals/{id}/reject | Member | Close without adopting. Idempotent; refused on an adopted proposal. |
Privacy posture
Proposals and evidence are metadata: model ids, catalogue prices, token
counts, pass rates in basis points, receipt request ids, spec hashes, run ids.
No prompt, completion, eval case input or model output ever enters these
tables — and that explicitly includes reason, which is a fixed class, and
figures, which holds numbers.
Eval cases are read in-frame to build a request and are never copied here; each arm's output is scored and dropped, exactly as chat drops it. The candidate spec is a foundry canonical spec, which is content-free by construction: the system prompt appears in it only as its sha256. See the privacy contract.
Related
- Model Foundry — what a proposal targets and what adoption publishes.
- Evals — the suite that supplies the evidence.
- Agent runs — how each arm folds into one verifiable head hash.
- FinOps — budgets and the circuit breaker, which bind whether or not a proposal exists.