Skip to content

Repository files navigation

downcoding-defense

Catch Medicare Advantage E/M downcoding on 835 remittance files and draft appeal packets — ready to mail — citing the relevant CMS and AMA standards.

Downcoding is when a payer pays a documented office visit at a lower level than it was billed (e.g. adjudicating a billed 99214 as a 99213), quietly shaving revenue off a claim. This tool parses your 835 remittances, flags downcoded E/M claims with conservative, specification-grade rules (plus an LLM classifier for edge cases), and generates a per-claim appeal-letter packet as a single PDF.

It runs fully self-hosted with no cloud — a local file in, a PDF out.

How it works

835 file
  -> parse_835         parse the X12 835 (pyx12)
  -> deidentify        split PHI off locally; nothing below sees it
  -> rules             deterministic same-family / repriced E/M downcode rules
  -> llm_classifier    LLM pass over the edge cases the rules left alone
  -> letter_generator  draft an appeal letter per downcode (Claude)
  -> pdf               assemble a mailable packet PDF (weasyprint)

Two compliance-minded properties are preserved from the hosted product:

  • PHI never reaches the LLM. Patient identity is stripped at the parse boundary (deidentify.py) and templated back into the finished letter locally, after the model returns.
  • Zero hallucinated citations. Letters may cite only entries in a curated CMS/AMA standards index (standards_index.py); any unknown citation token is rejected.

Quickstart

Requires Python 3.12+ and uv.

uv sync
export ANTHROPIC_API_KEY=sk-ant-...        # direct Anthropic API (the default)
uv run downcoding-defense run tests/fixtures/corpus/aetna_new_patient_downcode_carc45.835.txt -o packet.pdf

That parses the sample 835, detects the downcode, drafts an appeal letter, and writes packet.pdf.

PDF rendering uses WeasyPrint, which needs the native Pango/cairo libraries. On macOS: brew install pango. On Debian/Ubuntu: apt-get install libpango-1.0-0 libpangoft2-1.0-0. See the WeasyPrint install guide.

No API key handy? Run fully offline with deterministic stub letters (exercises the whole pipeline and the PDF render):

MOCK_EXTERNAL=true uv run downcoding-defense run \
  tests/fixtures/corpus/aetna_new_patient_downcode_carc45.835.txt -o packet.pdf

Configuration

Env var Purpose
ANTHROPIC_API_KEY Direct Anthropic API key (default LLM backend).
MOCK_EXTERNAL=true Offline deterministic mode — no LLM calls.
LLM_OPUS_MODEL Override the letter-drafting model id.
LLM_HAIKU_MODEL Override the edge-case classifier model id.

See .env.example for the full list, including the optional Vertex AI and Google Cloud Storage paths.

Optional backends

  • Vertex AI instead of the direct API: uv sync --extra vertex, set GCP_PROJECT_ID (and leave ANTHROPIC_API_KEY unset).
  • Google Cloud Storage object store (storage.py): uv sync --extra gcs, set STORAGE_BACKEND=gcs. The default is the local filesystem.

Development

uv run pytest                          # unit tests (run offline in mock mode)
uv run python -m evals.detection_fp    # false-positive rate on clean claims
uv run python -m evals.letter_quality  # zero hallucinated citations
uv run mypy src                        # type check

The tests/fixtures/ 835 corpus is synthetic and contains no real PHI.

License

AGPL-3.0-only. See LICENSE. Contributions require signing the Contributor License Agreement.

A hosted version — with intake, packet delivery, and outcome tracking — is in the works. Join the waitlist at receiptshealth.com.

About

Catch Medicare Advantage E/M downcoding on 835 remittances and draft CMS/AMA-cited appeal packets. Self-hosted, no cloud required.

Topics

Resources

Security policy

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages