CLI agent for detecting OpenAPI and FastAPI contract drift.
Project description
api-drift-agent
api-drift-agent detects drift between an OpenAPI 3.x contract and a FastAPI codebase.
It is built around two layers:
- a deterministic analyzer that parses the OpenAPI document, statically walks the FastAPI source tree, and reports exact contract differences
- an optional explanation layer that asks an LLM to decide whether the spec or code should be treated as the source of truth and to propose patch artifacts
The tool is useful when a FastAPI app and its published OpenAPI contract start evolving separately. It highlights missing endpoints, extra endpoints, schema mismatches, status-code differences, undocumented fields, required/nullability drift, and parameter drift.
Highlights
- OpenAPI YAML/JSON parsing for OpenAPI 3.x contracts
- Static FastAPI route analysis across single-file and router-based apps
- Pydantic model extraction for request and response schemas
- Deterministic drift classification with stable IDs
- Interactive Rich TUI for local inspection
- JSON output for CI and automation
- Optional explain mode with either Ollama or Groq
- Patch preview artifacts for spec and code-review workflows
- Config-file defaults via
.drift-check.yml - Ignore rules for known or intentional drift
- Test fixtures for realistic FastAPI/OpenAPI drift cases
Installation
Use Python 3.11 or newer.
pip install -e .[dev]
The CLI entrypoint is:
drift-check
Quick Start
Run the deterministic drift check:
drift-check --spec openapi.yaml --src ./app
Run against the included drift lab fixture:
drift-check --spec tests/fixtures/specs/drift_lab.yaml --src tests/fixtures/apps/drift_lab_app
If you omit --spec or --src, the interactive TUI prompts for the missing paths:
drift-check
Emit JSON for CI:
drift-check --spec openapi.yaml --src ./app --output-format json --output-file drift-report.json
Fail the command when error-severity drift exists:
drift-check --spec openapi.yaml --src ./app --output-format json --exit-code
Video Demo
https://github.com/user-attachments/assets/755ae9f6-fec0-4c4d-94cd-be6ab2d69c8f
What The Tool Detects
api-drift-agent compares normalized endpoint contracts from the spec and code.
It can report:
missing_endpoint: endpoint exists in the OpenAPI spec but not in FastAPI codeghost_endpoint: endpoint exists in code but not in the OpenAPI specadditive_drift: code accepts or returns fields not documented in the specdestructive_drift: spec documents fields or schemas missing from codetype_drift: schema type, format, or enum values differnullability_drift: nullable behavior differsrequired_drift: required flags differstatus_code_drift: documented and implemented status codes differparameter_drift: path/query/header/cookie parameters differ
Each drift item includes:
- stable drift ID
- endpoint
- category
- location
- detail
- spec evidence
- code evidence
- severity:
error,warning, orinfo
Interactive TUI
By default, non-JSON output opens a Rich TUI-style view.
The TUI includes:
- header with current phase
- run summary panel
- agent explanation panel
- deterministic drift panel
- footer with severity totals and scroll controls
The deterministic drift appears as soon as the static comparison is complete. If explain mode is enabled, the agent runs after that while the deterministic output remains visible.
TUI Controls
After the scan completes, the TUI remains open in an interactive terminal.
Deterministic drift panel:
jor Down: scroll downkor Up: scroll up- PageDown or Space: page down
- PageUp: page up
- Home: jump to top
- End: jump to bottom
Explainability panel:
z: scroll explanation findings downa: scroll explanation findings upx: page explanation findings downs: page explanation findings up
Exit:
q- Esc
- Enter
The panels show visual cues such as top, bottom, up more, down more, and current scroll position.
Explain Mode
Explain mode asks an LLM to inspect each drift item and produce an AgentFinding.
An agent finding contains:
- source of truth:
CODE,SPEC, orAMBIGUOUS - confidence:
high,medium, orlow - reasoning
- optional patch recommendation
The explainability panel shows:
- source-of-truth decision
- endpoint
- confidence
- reasoning
- drift category and location
- patch target/type/location when available
- patch content preview when available
manual review / no automatic codefixwhen no safe patch is available
Ollama Explain Provider
Ollama is the default explain provider.
Install and run Ollama, then pull the default model:
ollama pull qwen2.5-coder:7b
Run explain mode:
drift-check --spec openapi.yaml --src ./app --explain
Use a different Ollama model:
drift-check --spec openapi.yaml --src ./app --explain --model qwen2.5-coder:14b
Groq Explain Provider
Groq is supported through its OpenAI-compatible chat completions API.
Set an API key in the environment:
export GROQ_KEY=your-key
or in .env:
GROQ_KEY=your-key
The tool also accepts GROQ_API_KEY. GROK_KEY is accepted as a backwards-compatible alias from an earlier typo.
Run Groq explain mode:
drift-check --spec openapi.yaml --src ./app --explain --explain-provider groq
Use another Groq model:
drift-check --spec openapi.yaml --src ./app --explain --explain-provider groq --groq-model llama-3.1-8b-instant
Default Groq model:
llama-3.3-70b-versatile
When GROQ_KEY or GROQ_API_KEY is present and you run the interactive TUI, the CLI asks whether to enable explain mode and whether to use Ollama or Groq.
Patch Generation
Patch artifacts are generated only when explain mode is enabled and --patch-dir is set.
Example:
drift-check --spec openapi.yaml --src ./app --explain --patch-dir patches --patch-mode preview
Patch outputs can include:
spec_patched.yaml: preview of the OpenAPI spec after applying safe spec patchescode_patch_summary.md: summary of code patch suggestionsambiguous.md: drift items that require manual reviewbackups/: original files when code patches are applied
Patch modes:
preview: write patch artifacts without modifying codeapply: apply eligible code patches after safety checks
Code patch application is conservative:
- target file must exist
- file must not have uncommitted changes
- generated Python must parse successfully
- backup is written before modification
Spec patch application is also defensive:
- OpenAPI path keys such as
/api/users/{user_id}are handled as literal path keys - list indexes such as
parameters/0/schema/typeare supported - malformed model-generated patch locations are recorded as patch errors instead of crashing the run
JSON Output
Use JSON output for automation:
drift-check --spec openapi.yaml --src ./app --output-format json
The JSON payload contains:
- run ID
- timestamp
- spec path
- source path
- spec endpoint count
- code endpoint count
- drift items
- severity summary
- optional agent findings
- optional patch report
Example shape:
{
"run_id": "abc12345",
"timestamp": "2026-04-23T12:00:00+00:00",
"spec_path": "openapi.yaml",
"src_path": "./app",
"spec_endpoints": 12,
"code_endpoints": 13,
"items": [],
"summary": {
"error": 0,
"warning": 0,
"info": 0,
"total": 0
}
}
Write JSON to a file:
drift-check --spec openapi.yaml --src ./app --output-format json --output-file drift-report.json
Configuration
You can define defaults in .drift-check.yml in the current working directory.
spec: openapi.yaml
src: ./app
patch_dir: ./patches
explain_provider: groq
ignore:
- endpoint: "GET /health"
category: "ghost_endpoint"
CLI flags override config values.
Ignore Rules
Ignore rules let you suppress known or intentional drift.
Each rule can match:
- endpoint pattern
- drift category
Endpoint patterns use shell-style matching through fnmatch.
Example:
ignore:
- endpoint: "GET /health"
category: "ghost_endpoint"
- endpoint: "GET /internal/*"
Environment Variables
Supported environment variables:
GROQ_KEY: Groq API keyGROQ_API_KEY: Groq API key using Groq's documented naming conventionGROK_KEY: accepted as a legacy alias
The CLI also reads these values from .env in the current working directory.
CLI Reference
--spec PATH
Path to the OpenAPI YAML or JSON file.
--src PATH
Path to the FastAPI project root or source directory.
--explain
Enable the LLM-backed explanation layer.
--explain-provider ollama|groq
Choose the explain provider. Defaults to ollama.
--model MODEL
Ollama model name. Defaults to qwen2.5-coder:7b.
--groq-model MODEL
Groq model name. Defaults to llama-3.3-70b-versatile.
--patch-dir PATH
Directory for patch artifacts. Defaults to patches through the CLI flow.
--patch-mode preview|apply
Patch behavior. Defaults to preview.
--output-format rich|json
Output format. Defaults to rich, which uses the TUI.
--output-file PATH
Write the JSON payload to a file. This can be used with either output format.
--exit-code
Exit with code 1 when error-severity drift exists.
Project Architecture
src/drift_agent/
agent/
core.py # Ollama/Groq agent orchestration and response parsing
prompts.py # system prompt and tool schema
tools.py # agent tool dispatch
code_analyzer/
walker.py # source tree discovery
extractor.py # FastAPI route/model extraction
resolver.py # type/schema resolution helpers
context_tools/
coverage.py # coverage lookup helper
git.py # git context helper
search.py # source search helper
toolkit.py # tool container used by agent
diff_engine/
classifier.py # stable drift IDs
comparator.py # deterministic contract comparison
patch_generator/
code_patch.py # code patch application
spec_patch.py # OpenAPI patch application
generator.py # patch report orchestration
spec_parser/
parser.py # OpenAPI parsing
resolver.py # schema/ref resolution
cli.py # Typer CLI and Rich TUI
types.py # shared dataclasses
errors.py # project error types
Test Fixtures
The repository includes fixtures under tests/fixtures/.
Important fixtures:
tests/fixtures/specs/drift_lab.yamltests/fixtures/apps/drift_lab_apptests/fixtures/specs/simple.yamltests/fixtures/apps/simple_apptests/fixtures/specs/with_refs.yamltests/fixtures/specs/circular_refs.yaml
There is also a larger standalone fixture under test/:
test/fastapi_app.pytest/openapi.yaml
That fixture is useful for manually testing broader FastAPI and OpenAPI behavior.
Development
Run all tests:
python -m pytest -q
Compile-check key files:
python -m py_compile src/drift_agent/cli.py src/drift_agent/agent/core.py
Run the fixture drift check:
drift-check --spec tests/fixtures/specs/drift_lab.yaml --src tests/fixtures/apps/drift_lab_app
Run fixture drift check with JSON output:
drift-check --spec tests/fixtures/specs/drift_lab.yaml --src tests/fixtures/apps/drift_lab_app --output-format json
GitHub Actions
The repository includes a workflow at:
.github/workflows/drift-check.yml
Use JSON output and --exit-code for CI-style enforcement.
Limitations
- Static FastAPI analysis is best-effort and focuses on common FastAPI/Pydantic patterns.
- Highly dynamic route registration may not be detected.
- Explain mode depends on the selected model and can be slow on large drift reports.
- LLM-produced patches are treated defensively and may be marked ambiguous.
- Groq explain mode requires network access and a valid API key.
- Ollama explain mode requires a local Ollama runtime and the selected model.
Typical Workflows
Local Contract Review
drift-check --spec openapi.yaml --src ./app
Use the TUI to inspect drift, then decide whether to update code or spec.
Explain And Patch Preview
drift-check --spec openapi.yaml --src ./app --explain --patch-dir patches --patch-mode preview
Review:
patches/spec_patched.yamlpatches/code_patch_summary.mdpatches/ambiguous.md
CI Drift Gate
drift-check --spec openapi.yaml --src ./app --output-format json --output-file drift-report.json --exit-code
The command exits with 1 if error-severity drift exists.
Status
Implementation progress is summarized in WORK_DONE.md.
Project details
Release history Release notifications | RSS feed
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 api_drift_agent-0.1.0.tar.gz.
File metadata
- Download URL: api_drift_agent-0.1.0.tar.gz
- Upload date:
- Size: 39.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2302189c7c35e822f89fdb0fb4eaa6d220337c3c8cedad5184ae8b9380264e28
|
|
| MD5 |
055984aaeff4d5f4589123d6a99aaa0b
|
|
| BLAKE2b-256 |
44bde4e4d4c28d69e5dff62c8d1a24f6807d52030b0effcb7632711dfb776a64
|
File details
Details for the file api_drift_agent-0.1.0-py3-none-any.whl.
File metadata
- Download URL: api_drift_agent-0.1.0-py3-none-any.whl
- Upload date:
- Size: 43.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
66f6bb9016ab2e0307a088e0383f595d83b761b20f2f401011d0fef2fc067f7b
|
|
| MD5 |
d9d58986c402b865e64e1d957e1dcd10
|
|
| BLAKE2b-256 |
da0aa5462379824dae07697bccc9be1294419bcb468520249cc48e9d55740572
|