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.
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.
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.pdfThat 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| 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.
- Vertex AI instead of the direct API:
uv sync --extra vertex, setGCP_PROJECT_ID(and leaveANTHROPIC_API_KEYunset). - Google Cloud Storage object store (
storage.py):uv sync --extra gcs, setSTORAGE_BACKEND=gcs. The default is the local filesystem.
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 checkThe tests/fixtures/ 835 corpus is synthetic and contains no real PHI.
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.