All demos
Health-techLangGraph
Prior Authorization
Prior-auth determination + appeal draft — with a clinician gate on denials
Ready to replay
0.0s / 9.9sSecurity Pipeline
Input
Sandbox
Network
PII Scan
Injection
Vault
LLM Call
Result
Real run · LangGraph · python run.py · captured 2026-06-30 · SDK 1.3.0
Run it yourself View the agent code· with Declawhealth-tech/sandboxed/01-prior-auth-langgraph/run.py
"""Prior Authorization (LangGraph) — sandboxed with declaw, real GPT-4.1.
The appeal-letter step makes the SAME real gpt-4.1 call as the baseline,
but from inside a Firecracker microVM whose security proxy:
* Redacts PHI (member_id, email, ssn, phone) before the request body
leaves the VM. The OpenAI endpoint sees [REDACTED_*_n] tokens.
* Rehydrates those tokens in the inbound response so the agent code
receives the original PHI back, transparently.
* Locks egress to api.openai.com + pypi (for openai package install).
* Blocks the cloud metadata IP and everything else.
"""
from __future__ import annotations
import json
import sys
import textwrap
from pathlib import Path
from typing import Annotated, Literal, TypedDict
from langgraph.checkpoint.memory import MemorySaver
from langgraph.graph import END, START, StateGraph
REPO_ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(REPO_ROOT))
sys.path.insert(0, str(REPO_ROOT / "sandboxed"))
from shared.mock_phi import PATIENTS, PAYER_POLICIES # noqa: E402
from shared.declaw_helpers import ( # noqa: E402
LLM_DOMAINS, LLM_PIP, healthcare_llm_policy,
healthcare_untrusted_io_policy, llm_envs, run_python_in_sandbox,
)
from shared import governance as gov # noqa: E402
class PAState(TypedDict, total=False):
patient_id: str
requested_drug: str
policy_key: str
evidence: dict
policy: dict
packet: dict
submission_id: str
# A medical-necessity DENIAL is never autonomously binding — it is a
# recommendation held for a licensed clinician (CMS 42 CFR 422.101(c);
# CA SB 1120 / IL clinical-peer). Approval may be auto-issued.
status: Literal["pending", "approved", "pending_clinician_review"]
recommendation: str
reviewer: str
gate_status: str
denial_reasons: list[str]
appeal_letter: str
audit_log: Annotated[list[dict], "append-only audit trail"]
def fetch_chart_evidence(patient_id: str) -> dict:
p = PATIENTS[patient_id]
a1c = next((l for l in p.labs if l["name"] == "Hemoglobin A1c"), None)
return {
"patient_name": p.name,
"member_id": p.member_id,
"diagnoses": p.diagnoses,
"medications": p.medications,
"a1c": a1c,
"bmi": 34 if patient_id == "p-001" else None,
"notes": p.notes,
}
# ---------- Sandboxed payer submission (untrusted clearinghouse) ----------
PAYER_SUBMIT_SCRIPT = textwrap.dedent("""
import json
with open("/tmp/in.json") as f:
packet = json.load(f)
has_a1c = packet.get("evidence", {}).get("a1c") is not None
out = {
"submission_id": "PA-9001",
"status": "approved" if has_a1c else "denied",
"reasons": [] if has_a1c else ["missing_a1c"],
}
with open("/tmp/out.json", "w") as f:
json.dump(out, f)
""")
def submit_to_payer_sandboxed(packet: dict) -> dict:
pol = healthcare_untrusted_io_policy(allow_domains=["*.payer-clearinghouse.com"])
return run_python_in_sandbox("payer-submit", PAYER_SUBMIT_SCRIPT, pol, payload=packet)
# ---------- Sandboxed LLM appeal draft (real gpt-4.1, PII-redacting) ----------
APPEAL_SCRIPT = textwrap.dedent("""
import json
from openai import OpenAI
with open("/tmp/in.json") as f:
inp = json.load(f)
client = OpenAI()
resp = client.chat.completions.create(
model="gpt-4.1",
messages=[
{"role": "system", "content": (
"You are a clinical appeals specialist. Draft a concise, "
"professional prior-authorization appeal letter justifying "
"medical necessity. Cite the specific policy criteria the "
"patient meets. Plain text, no markdown. If you see "
"REDACTED_* tokens, treat them as opaque placeholders for "
"patient identifiers."
)},
{"role": "user", "content": json.dumps(inp)},
],
max_completion_tokens=600,
)
with open("/tmp/out.json", "w") as f:
json.dump({"letter": resp.choices[0].message.content}, f)
""")
def draft_appeal_sandboxed(packet: dict, reasons: list[str]) -> str:
pol = healthcare_llm_policy(allow_domains=LLM_DOMAINS)
out = run_python_in_sandbox(
"appeal-llm", APPEAL_SCRIPT, pol,
payload={"submission_id": packet.get("submission_id", "?"),
"denial_reasons": reasons, "packet": packet},
pip_packages=LLM_PIP, envs=llm_envs(),
)
return out["letter"]
# ---------- Graph ----------
def gather(state: PAState) -> PAState:
return {"evidence": fetch_chart_evidence(state["patient_id"]),
"audit_log": [{"node": "gather"}]}
def policy_check(state: PAState) -> PAState:
p = PATIENTS[state["patient_id"]]
pol = PAYER_POLICIES[state["policy_key"]]
if p.payer not in pol["payers"]:
raise ValueError(f"{p.payer} not covered by {state['policy_key']}")
return {"policy": pol, "audit_log": [{"node": "policy_check"}]}
def assemble_packet(state: PAState) -> PAState:
packet = {
"patient_id": state["patient_id"],
"drug": state["requested_drug"],
"evidence": state["evidence"],
"policy_criteria": state["policy"]["criteria"],
}
return {"packet": packet, "audit_log": [{"node": "assemble_packet"}]}
def submit(state: PAState) -> PAState:
print("[node submit] entering sandbox (untrusted clearinghouse)")
result = submit_to_payer_sandboxed(state["packet"])
# `result["status"]` is the automated medical-necessity RECOMMENDATION, not a
# binding decision — the clinician_review gate owns a denial.
return {
"submission_id": result["submission_id"],
"status": "pending",
"recommendation": gov.RECOMMEND_DENY if result["status"] == "denied"
else gov.RECOMMEND_APPROVE,
"denial_reasons": result["reasons"],
"audit_log": [{"node": "submit", "sandboxed": True,
"recommendation": result["status"]}],
}
def clinician_review(state: PAState) -> PAState:
"""Mandatory human gate on a medical-necessity DENIAL. An LLM/automated rule
may recommend, but a licensed clinician must own the denial before it is
issued (CMS 42 CFR 422.101(c); CA SB 1120 "Physicians Make Decisions Act";
IL clinical-peer). Approvals may be auto-issued; denials are held."""
if state.get("recommendation") == gov.RECOMMEND_DENY:
print(f"[node clinician_review] {gov.RECOMMEND_DENY} — "
f"{gov.PENDING_HUMAN_CONFIRMATION} (a {gov.REVIEWER_CLINICIAN} must own "
"this medical-necessity denial; not auto-denied)")
return {
"status": "pending_clinician_review",
"gate_status": gov.PENDING_HUMAN_CONFIRMATION,
"reviewer": gov.REVIEWER_CLINICIAN,
"audit_log": [{"node": "clinician_review",
"recommendation": gov.RECOMMEND_DENY,
"status": gov.PENDING_HUMAN_CONFIRMATION}],
}
print("[node clinician_review] RECOMMEND_APPROVE — approval may be auto-issued")
return {
"status": "approved",
"audit_log": [{"node": "clinician_review", "recommendation": gov.RECOMMEND_APPROVE}],
}
def draft_appeal(state: PAState) -> PAState:
print("[node draft_appeal] entering sandbox (real gpt-4.1, PII redacted+rehydrated at proxy)")
letter = draft_appeal_sandboxed(state["packet"], state["denial_reasons"])
return {"appeal_letter": letter,
"audit_log": [{"node": "draft_appeal", "sandboxed": True, "model": "gpt-4.1"}]}
def route_after_review(state: PAState) -> str:
# A recommended denial drafts an appeal (provider assist) while it is held
# for the clinician; an approval ends.
return "draft_appeal" if state.get("recommendation") == gov.RECOMMEND_DENY else END
def build_graph():
g = StateGraph(PAState)
g.add_node("gather", gather)
g.add_node("policy_check", policy_check)
g.add_node("assemble_packet", assemble_packet)
g.add_node("submit", submit)
g.add_node("clinician_review", clinician_review)
g.add_node("draft_appeal", draft_appeal)
g.add_edge(START, "gather")
g.add_edge("gather", "policy_check")
g.add_edge("policy_check", "assemble_packet")
g.add_edge("assemble_packet", "submit")
# Denial recommendation passes through the mandatory clinician gate.
g.add_edge("submit", "clinician_review")
g.add_conditional_edges("clinician_review", route_after_review,
{"draft_appeal": "draft_appeal", END: END})
g.add_edge("draft_appeal", END)
return g.compile(checkpointer=MemorySaver())
def main() -> None:
graph = build_graph()
initial: PAState = {
"patient_id": "p-003", # no A1c → guaranteed denial → appeal drafted
"requested_drug": "mepolizumab",
"policy_key": "mepolizumab_asthma",
}
config = {"configurable": {"thread_id": "demo-thread-sandboxed"}}
result = graph.invoke(initial, config=config)
print("\n=== Prior Auth Result (sandboxed, real LLM) ===")
print(f"Governance: {gov.governance_banner()}")
print(f"Patient: {result['patient_id']}")
print(f"Drug: {result['requested_drug']}")
print(f"Submission ID: {result.get('submission_id')}")
print(f"Recommendation: {result.get('recommendation')} -> status={result.get('status')}")
if result.get("recommendation") == gov.RECOMMEND_DENY:
print(f"Clinician gate: {result.get('gate_status')} — owner: {result.get('reviewer')}")
print(f"Reasons: {result['denial_reasons']}")
print("[NOTE] The denial is NOT issued autonomously — a licensed clinician "
"must own it (CMS 42 CFR 422.101(c) / CA SB 1120). The letter below is "
"drafted to assist, pending that review.")
print("\n--- Appeal Letter (gpt-4.1, PHI rehydrated by declaw proxy) ---")
print(result["appeal_letter"])
if __name__ == "__main__":
main()
View raw audit JSON
[
{
"atMs": 450,
"kind": "stage",
"payload": {
"stage": "input",
"status": "done",
"detail": "read input files in-VM"
}
},
{
"atMs": 1671,
"kind": "stage",
"payload": {
"stage": "sandbox",
"status": "done",
"detail": "2 Firecracker microVM(s) · own kernel · egress-locked"
}
},
{
"atMs": 2893,
"kind": "network",
"payload": {
"event": "egress_allowed",
"detail": {
"host": "api.openai.com",
"port": 443,
"reason": "allowlist"
}
}
},
{
"atMs": 4114,
"kind": "security",
"payload": {
"event": "pii_redaction",
"detail": {
"entities": [
{
"entity_type": "PERSON",
"masked_value": "REDACTED_PERSON_23",
"confidence": 0.85
}
],
"destination": "api.openai.com",
"rehydrated_on_reply": true
}
}
},
{
"atMs": 5336,
"kind": "audit",
"payload": {
"event": "pii_redaction",
"category": "security",
"detail": {
"entities": 1,
"destination": "api.openai.com",
"rehydrated": true
},
"timestamp": "2026-06-30T20:26:52.661174Z"
}
},
{
"atMs": 6557,
"kind": "security",
"payload": {
"event": "vault_brokered",
"detail": {
"keys": "OPENAI_API_KEY",
"host": "api.openai.com",
"injected_at": "egress proxy",
"exposure_to_vm": "none (declaw:vault-managed placeholder)"
}
}
},
{
"atMs": 7779,
"kind": "stage",
"payload": {
"stage": "llm",
"status": "done",
"detail": "model called from inside the microVM (PII redacted on the wire) · 20.0s real",
"durationMs": 1971
}
},
{
"atMs": 9000,
"kind": "decision",
"payload": {
"text": "Recommendation held for a LICENSED CLINICIAN — no autonomous coverage denial (CMS / state physician-review)"
}
}
]