Skip to main content

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 code
  • ghost_endpoint: endpoint exists in code but not in the OpenAPI spec
  • additive_drift: code accepts or returns fields not documented in the spec
  • destructive_drift: spec documents fields or schemas missing from code
  • type_drift: schema type, format, or enum values differ
  • nullability_drift: nullable behavior differs
  • required_drift: required flags differ
  • status_code_drift: documented and implemented status codes differ
  • parameter_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, or info

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:

  • j or Down: scroll down
  • k or 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 down
  • a: scroll explanation findings up
  • x: page explanation findings down
  • s: 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, or AMBIGUOUS
  • confidence: high, medium, or low
  • 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 codefix when 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 patches
  • code_patch_summary.md: summary of code patch suggestions
  • ambiguous.md: drift items that require manual review
  • backups/: original files when code patches are applied

Patch modes:

  • preview: write patch artifacts without modifying code
  • apply: 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/type are 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 key
  • GROQ_API_KEY: Groq API key using Groq's documented naming convention
  • GROK_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.yaml
  • tests/fixtures/apps/drift_lab_app
  • tests/fixtures/specs/simple.yaml
  • tests/fixtures/apps/simple_app
  • tests/fixtures/specs/with_refs.yaml
  • tests/fixtures/specs/circular_refs.yaml

There is also a larger standalone fixture under test/:

  • test/fastapi_app.py
  • test/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.yaml
  • patches/code_patch_summary.md
  • patches/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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

api_drift_agent-0.1.0.tar.gz (39.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

api_drift_agent-0.1.0-py3-none-any.whl (43.0 kB view details)

Uploaded Python 3

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

Hashes for api_drift_agent-0.1.0.tar.gz
Algorithm Hash digest
SHA256 2302189c7c35e822f89fdb0fb4eaa6d220337c3c8cedad5184ae8b9380264e28
MD5 055984aaeff4d5f4589123d6a99aaa0b
BLAKE2b-256 44bde4e4d4c28d69e5dff62c8d1a24f6807d52030b0effcb7632711dfb776a64

See more details on using hashes here.

File details

Details for the file api_drift_agent-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for api_drift_agent-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 66f6bb9016ab2e0307a088e0383f595d83b761b20f2f401011d0fef2fc067f7b
MD5 d9d58986c402b865e64e1d957e1dcd10
BLAKE2b-256 da0aa5462379824dae07697bccc9be1294419bcb468520249cc48e9d55740572

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page