Inspiration
Fewer than one in a hundred health-insurance denials is ever appealed, and a large share of the appeals that are filed succeed. The gap is not legal skill. It is unmanaged project work at the worst moment of someone's year: a filing deadline buried on page four of the denial letter, and the clause that would win the case sitting on page eighty-seven of a plan document nobody reads. A specialist solves it. Almost nobody can hire one.
There is a second, quieter injustice underneath the first. Your insurance card says Aetna. But on the self-funded employer plan that covers roughly two-thirds of US workers, Aetna does not pay your claim, your employer does, and the state insurance regulator most people would complain to has no power over that plan. Practices guess, complaints get dismissed for want of jurisdiction, and the patient never finds out why. Badger's core move is to read that fact off the denial letter itself and fight the right fight, at the right door.

What it does
Badger runs a prior-authorisation appeal as a weeks-long case, not a one-off letter.
- Reads the denial from a fax, an email, a FHIR PAS Bundle, or pasted text, stripping PHI on the way in before anything else sees it.
- Names why it was denied (step therapy, non-formulary, administrative, medical necessity) and who actually pays (self-funded, fully-insured, government, unknown), both from the letter's own required wording, with the exact sentences quoted as proof.
- Retrieves the payer's own coverage policy, the specialty guideline and the FDA label, and joins them. A case with a missing evidence lane is never drafted from.
- Drafts the appeal with Gemini over a grounded scaffold, quoting the plan's own criteria back to it and addressing the correct regulator for the funding regime.
- Refutes its own draft with a panel of skeptics before any human sees it. Only a survivor reaches the prescriber.
- Re-verifies every citation immediately before filing, so a policy that moved after signing cannot be filed against.
- Holds every deadline on the appeal ladder, daily, for the weeks the case runs.
- Opens the second door on day zero: the manufacturer bridge programme, so the drug can arrive while the appeal is pending, correctly forked so a Medicare or Medicaid patient is routed to a foundation rather than a federally barred copay card.
- Learns which arguments overturn which denials at which payer, and orders the next draft by that prior, without ever quoting it.
Every clinical output is a draft a prescriber signs, bound to the exact draft hash, and every step is written to a tamper-evident audit trail.
Why this needs an agent, not a rules engine
The deterministic parts are deliberately deterministic (see below). But three judgements genuinely require a model reasoning over cited evidence:
- Reading a denial that follows no template. The letters are scanned faxes, portal exports and free text. Naming the denial family and pulling the fields is language work, not pattern matching.
- Drafting an argument that quotes the plan back to itself. Turning a specific criterion, guideline and label into a coherent, plan-specific appeal is writing, not a mail merge.
- Refuting that draft before a human sees it. A panel of skeptics that tries to break the argument, and kills it on a fabricated citation, is reasoning.
How we built it
Badger is a Google ADK 2 Workflow graph, not a tree of agents. The design rule is that everything a regulator would ask about is a deterministic function node: the funding regime, the ladder rung, the retrieved citation, the fence, the signature authorisation, the audit event. Only the prose drafting and the adversarial review are model nodes (Gemini 3.5 Flash on Vertex AI). The split rule, stated once: a node must be a function node whenever the same input is required to produce the same output. That is 10 function nodes, 5 agent nodes, 1 task node (the signature hold), and a bench of specialists. The same graph is also deployed on Vertex AI Agent Engine (reasoningEngines/1371528055708712960), so the long-running case has a managed runtime and a durable session, not just a local runner.

PHI redaction runs first, a deterministic pass plus an on-device Gemma NER layer via Ollama, and Model Armor on the cloud path, so nothing raw reaches storage or the model. Case state lives in Firestore; the API and the daily deadline heartbeat run on Cloud Run; the original denial PDF is kept in Cloud Storage; denials arrive over three channels, a fax over Telnyx with a signed webhook, a FHIR Da Vinci PAS Bundle, and a live Gmail channel (users.watch to a Pub/Sub push into Cloud Run, on a real inbox). The plan-sponsor identity corpus (DOL Form 5500) and the public precedent surface (external-review decisions) are indexed in BigQuery, with vector search over embeddings for the precedent recall. A per-case patient explainer is generated with Veo 3.1 and scored with Lyria, both called for real on Vertex AI.
The whole thing is eval-first. Twenty-five scorecards run over a frozen set of 200 synthetic denials, in pure standard library, in CI, and hard-fail on any regression. A reviewer can run python -m eval.run_eval with no key and no cloud and watch the numbers, run the ADK graph end to end, and re-verify the signed audit chain offline.
The mandatory three, each invoked on every case
- Google ADK: the Workflow graph in
api/graph/agent.py, running ongoogle-adk2.7, also deployed on Vertex AI Agent Engine. - Gemini 3.5 Flash on Vertex AI: the two model nodes,
draft_appealandreview_appeal, verified live on thebadger-256f2project. - Google Cloud: Firestore for case state, Cloud Run for the API and the heartbeat job, plus Cloud Storage, BigQuery, Pub/Sub, Scheduler, Model Armor and Secret Manager.
On the Gemini Enterprise Agent Platform
Against GEAP, Badger uses the pieces a regulated, weeks-long case needs. The whole ADK graph is deployed on Vertex AI Agent Engine as a managed Agent Runtime with a durable session (reasoningEngines/1371528055708712960), so a case that runs for weeks has a real hosted runtime, not just a local runner. Model Armor screens the prompt and the response around every Gemini call, catching prompt injection and PII on the cloud path, on top of the local Gemma redaction pass that runs first. Identity is enforced where it counts: a write requires a verified principal, and the sign-and-file action binds to the prescriber of record, whose NPI is read from the verified token and matched to the case, never taken from the request body. And in place of trace logs, governance is answered by something stronger for this domain: a hash-chained, Ed25519-signed audit trail in which editing any row, including a forged model attribution, is caught on an offline re-verification. Everything a regulator would ask about is a deterministic function node, and every one of those decisions sits in that signed ledger.
Validation and results
The headline is the funding-regime move, and it is a real before/after number, not a demo pair.
| What we measured | Result | What it shows |
|---|---|---|
| Funding regime, read from the letter (200 denials) | 42% to 99% | who can actually hear the appeal, from the letter's own required wording |
| Cases misrouted to a powerless state regulator | 116 to 0 | out of 200; the wrong-door failure, closed |
| Denial-family triage | 73.5% to 100% | why it was denied, named from the letter |
| Fabricated citations | 0 | every quoted policy line resolves to a real published paragraph |
| Eval scorecards, CI-gated | 25 / 25 green | regime, triage, retrieval, draft integrity, the fence, the human gate, memory, the second door, the audit chain, deadline arithmetic and stewardship, auth and identity, adversarial review, the patient explainer, PHI redaction, webhook security and idempotency, the FHIR channel, instrument selection, filing, the payer call, the open-set triage router, batch and email intake, multi-signal funding, provenance and the specialist bench, persistence and the EHR-check gate |
| Live | a fax to +1 888 527 3392 creates a real case | Gemini drafts it, and PHI never reaches storage or the model |
The audit trail is itself verifiable: every decision is hash-chained and Ed25519-signed, so editing any row (including a forged model attribution) is detected and localised on an offline re-verification.

Challenges we ran into
- Keeping the model out of the auditable path. The instinct in ADK is to make everything an agent. The discipline that makes Badger defensible was doing the opposite: pushing the regime, the deadline, the citation and the signature into deterministic function nodes and eval-ing each one, so the model only touches what genuinely needs judgement.
- PHI, before anything. Redaction had to run first and survive the field extraction, so the legal signal (the ERISA wording that decides the regime) is preserved while the name, MRN and SSN are gone before storage.
- An honest self-improvement boundary. An optimiser told to maximise an overturn score learns to write appeals that score well rather than appeals that are clinically honest. So Badger evolves its memory (which argument won, ranked by a Wilson lower bound), never its clinical instruction.
What this is NOT (the honesty section)
- Drafts only. A prescriber of record signs before anything files, and the signature binds to the exact draft body hash. Nothing is auto-filed.
- No invented policy. It quotes only real published paragraphs, and every citation re-verifies immediately before filing.
- Synthetic data. All patients are synthetic. It is a research prototype, rigorously evaluated, not a clinical product.
- The overturn rate is reserved, not faked. Until real case outcomes exist, Badger reports the metrics it can stand behind and marks the outcome rate as pending.
- It argues coverage, it does not practise medicine. US commercial and Medicare framing; it reasons about published criteria, not diagnosis.
What's next
The DOL Form 5500 sponsor index and the public precedent surface are already built (indexed in BigQuery, with vector search over the precedents), but wired behind honest gates: the next step is enabling those live lookups, alongside the EHR treatment-relationship check that is currently a documented, un-faked gate on the signature screen. Beyond that: live payer-policy ingestion past the seed corpus, Cloud KMS signing for the audit ledger in place of the demo key, and the peer-to-peer scheduling lane. Firebase SSO is built on the write path but deliberately held off, so a judge lands in the workspace with one click rather than a sign-up wall.
Try it
- Live workspace, no login: https://badger-256f2.web.app then "Skip the sign-up, show me the demo".
- Repository: github.com/faith-ogun/Badger (shared with testing@devpost.com and cloudhackathons@google.com)
- Architecture and the ADK 1 vs 2 split: see the media gallery diagrams.
Built with
Google ADK, Gemini 3.5 Flash (Vertex AI), Vertex AI Agent Engine, Gemma (Ollama), Veo 3.1, Lyria, Firestore, Cloud Run, Cloud Build, Cloud Storage, BigQuery, Pub/Sub, Cloud Scheduler, Model Armor, Secret Manager, Gmail API, Firebase Hosting, FastAPI, Python, Ed25519 (cryptography), React 19, Vite, Tailwind v4, Remotion, Telnyx (fax), FHIR (Da Vinci PAS).
Built With
- cloud-build
- cloud-run
- cloud-scheduler
- cloud-storage
- ed25519
- fastapi
- fhir
- firestore
- gemini-3.5-flash
- gemma
- github-actions
- google-adk
- google-cloud
- lyria
- ollama
- pub-sub
- python
- react
- remotion
- tailwind-css
- telnyx
- typescript
- veo
- vertex-ai
- vite
Log in or sign up for Devpost to join the conversation.