driftless
When you change the model behind an LLM app, the prompt that used to work often stops working. Driftless runs your eval on the old model and the new one, repairs only the files you allow, and opens a pull request with the evidence — or blocks the change if quality drops.
You need an eval you can run from the command line. The bundled demo needs no API key. Automatic prompt repair on a real workflow does.
If you know Poetry and Dependabot:
driftless.ymlis the manifest (model + eval dataset), the prompt is the lockfile, and delivery is a gated PR. LLM behavior is empirical, so Driftless scores candidates on your eval instead of resolving versions.
Status: public alpha —
0.3.xon PyPI. Upgrading from 0.2.x? Follow the upgrade guide first.
Install
pip install driftless
Python 3.10 or newer. No API key for the steps below.
Quickstart
Copy the bundled support-classifier example and run it. -w is the workflow
name from driftless.yml.
driftless copy-example support-classifier --out-dir driftless-classifier-demo
cd driftless-classifier-demo
driftless validate -w support_classifier
driftless compare -w support_classifier --to gpt-4o-mini
validate checks that the project is wired correctly. compare runs the
current model and the cheaper target on the same tiny eval. You should
see something like:
F1 current 1.000 target 0.000
Total cost current 0.024 target 0.004
FAIL min_f1: 0.000 >= 0.9
Read that last line as: the new model scored 0.000, you required at least 0.9, so the cheaper swap is not safe to ship. That failure is the point of the demo.
Continue without API keys. --generator none makes no prompt edits, so
migration stays blocked. --generator fixture applies the known-good patch
shipped with this example and can pass.
driftless migrate -w support_classifier --to gpt-4o-mini --generator none
# Expected: BLOCKED, non-zero exit. Run the next commands anyway.
driftless migrate -w support_classifier --to gpt-4o-mini --generator fixture
# Expected: PASS — bundled patch, still no API key.
driftless report -w support_classifier
driftless open-pr -w support_classifier
# Dry run: prints what it would open. Add --create only when you mean it.
This demo has only 4 eval rows. It proves install, gating, and a key-free pass/block loop. It is not production evidence. For a real workflow use a representative eval and
--generator llm(needs a provider key). See eval confidence.
Words you'll see
| Term | Meaning |
|---|---|
| Workflow | One LLM task in the repo (classifier, RAG answerer, agent). |
| Contract | driftless.yml — how to run the task, what may be edited, what “good” means. |
| Harness | Your command that runs the task and writes one JSON object per line. |
| Generator | Who writes the repair: none (no edits), fixture (bundled demo patch), llm (calls a provider). |
| Holdout | Eval rows saved for a final check; the repair loop never trains on them. |
Product proof
This is the actual output of the cold-install quickstart:
A larger offline migration was also run against the public
support-classifier-svc
testbed. It produced draft PR #4
with the generated scorecard, holdout evidence, prompt diff, and model update:
PR #4 is historical proof of a 290-label testbed run. The published CLI
reproduces a passing four-row repair with --generator fixture; regenerating
PR #4's exact patch still needs provider-backed --generator llm (or the
testbed's own simulator) and may differ.
Other bundled examples:
driftless copy-example rag-qa
driftless copy-example tool-agent
To put Driftless on an existing app, follow the
existing-repository walkthrough.
Start with scan and configure --apply, then review the draft contract
before repair or CI.
How it works
You describe the workflow once in driftless.yml: the command that runs it,
how to switch models, which files may be edited, and the quality bar. Driftless
runs your command under different models, compares results, repairs only
allowed files, checks the winner on holdout data, and opens a PR with the
evidence.
You own the workflow. Driftless orchestrates it.
Not a classifier? Pick a grading mode that matches the task:
eval.score_field/eval.pass_field— your command emits a numeric score or a pass/fail per record (summarization, codegen, agents).eval.fields— structured extraction, scored per field against gold labels.eval.judge— an LLM grades free-form output against a rubric. Rundriftless judge-check -w <workflow>before optimizing.
CLI reference
| Command | Purpose |
|---|---|
copy-example |
Copy a bundled example (support-classifier, rag-qa, tool-agent). |
init |
Scaffold a driftless.yml. |
init-policy |
Scaffold a .driftless/policy.yml (when to migrate). |
init-ci |
Scaffold .github/workflows/ for scan, migrate, refine, poll, plan, label audit, and judge check. |
scan |
Find probable LLM usage and at-risk models. |
plan |
Discover at-risk workflows and apply the migration policy (CI triage). |
plan --act |
Migrate + open a PR/issue for every actionable trigger. |
configure <workflow> |
Write .driftless/configure/<workflow>.yml; add --apply to create or append root driftless.yml. |
calibrate -w <w> |
Measure the baseline and suggest starting thresholds. |
compare -w <w> --to <model> |
Baseline vs target scorecard; add --enforce to fail CI when gates fail. |
migrate -w <w> --to <model> |
Repair + validate + produce migrated files. |
refine -w <w> |
Re-optimize the prompt for a changed eval dataset (model pinned). |
poll [--act] |
Detect external eval-dataset changes and refine on a meaningful change. |
validate -w <w> |
Check the contract parses and the harness runs. |
judge-check -w <w> |
Measure judge↔human agreement (--enforce to gate). |
audit-labels -w <w> |
Find duplicate inputs with disagreeing gold labels (--fail for CI). |
report |
Render the latest migration report. |
view |
Open the optimization run viewer (charts + attempt log). |
open-pr -w <w> |
Open a PR (or issue) from the latest migration result. |
Configuring when to migrate
plan reads an optional .driftless/policy.yml — the “when to propose a
change” layer. Scaffold it with driftless init-policy. An empty file behaves
like no file. It controls which triggers are enabled (deprecation is on and
forced; cost/quality/new_model are optional), thresholds a candidate must
clear, a cooldown_days for freshly released models, allow/deny globs, and an
ignore list. The engine still decides whether a candidate passes your eval —
policy only decides whether to propose it.
GitHub Action
A composite GitHub Action wraps the same CLI so scans and migrations can run in CI. After you have a working local contract:
- uses: driftless-dev/driftless@v0.3.5
with:
command: scan
See .github/workflows/ in this repo for scheduled scan, weekly plan --act,
and manually triggered migration examples.
Documentation
Start here
- Landing page — product overview.
- Hosted docs — install, quickstart, contract, CLI.
- Getting started — golden-path example, then adopt in your repo.
- Command chooser — “I want to do X, which command?”
- Known limits — what Driftless will and will not do.
- Eval confidence — when a pass is trustworthy.
- Cost and budgets — how eval loops spend money.
When you need them
- Upgrading to 0.3 — replace legacy
migration.allow_*withfiles.editable. - Use-case guides — model migration, dataset refine, CI, cost, labels, judges, RAG, agents.
- RAG and agents — contract patterns.
- Repair prompts and custom generators
- Example blocked issue and example success PR
- Run viewer
- Changelog
- Contributing
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file driftless-0.3.5.tar.gz.
File metadata
- Download URL: driftless-0.3.5.tar.gz
- Upload date:
- Size: 3.4 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
833ed2455cacc3a53f472e17b526331612ce624bc2f509fb1708fa7680316115
|
|
| MD5 |
ceea54d30a6ff35c67956aa754bfe96f
|
|
| BLAKE2b-256 |
ebaa0efe9cdfe55573d6bf2f6baafa9fd8a47e77acf3a42c4937ba225b1a4b99
|
Provenance
The following attestation bundles were made for driftless-0.3.5.tar.gz:
Publisher:
publish.yml on driftless-dev/driftless
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
driftless-0.3.5.tar.gz -
Subject digest:
833ed2455cacc3a53f472e17b526331612ce624bc2f509fb1708fa7680316115 - Sigstore transparency entry: 2480692999
- Sigstore integration time:
-
Permalink:
driftless-dev/driftless@4dfb5f8dcb4395491d9d3c1e8b03644997e45eea -
Branch / Tag:
refs/tags/v0.3.5 - Owner: https://github.com/driftless-dev
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@4dfb5f8dcb4395491d9d3c1e8b03644997e45eea -
Trigger Event:
release
-
Statement type:
File details
Details for the file driftless-0.3.5-py3-none-any.whl.
File metadata
- Download URL: driftless-0.3.5-py3-none-any.whl
- Upload date:
- Size: 2.5 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b7584d29e59bcfdbc7d219a49dc86e992a13c432552c63187d6ed0f4db801cfb
|
|
| MD5 |
529046b283bf05439d87de0efa2eeb33
|
|
| BLAKE2b-256 |
836ddf1f0448364732f433e82e9e8024d1c6bcebfa2d87ee2c0f2f462de53563
|
Provenance
The following attestation bundles were made for driftless-0.3.5-py3-none-any.whl:
Publisher:
publish.yml on driftless-dev/driftless
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
driftless-0.3.5-py3-none-any.whl -
Subject digest:
b7584d29e59bcfdbc7d219a49dc86e992a13c432552c63187d6ed0f4db801cfb - Sigstore transparency entry: 2480693045
- Sigstore integration time:
-
Permalink:
driftless-dev/driftless@4dfb5f8dcb4395491d9d3c1e8b03644997e45eea -
Branch / Tag:
refs/tags/v0.3.5 - Owner: https://github.com/driftless-dev
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@4dfb5f8dcb4395491d9d3c1e8b03644997e45eea -
Trigger Event:
release
-
Statement type: