HealthAdminBench

HealthAdminBench is a computer-use evaluation of healthcare administration workflows (prior authorization, appeals/denials, DME). The MedHELM scenario name is health_admin_bench. It is not OpenAI HealthBench (health_bench).

Paper: HealthAdminBench (Bedi et al., 2026). Upstream harness: som-shahlab/health-admin-bench.

This page covers how to clone MedHELM and HealthAdminBench, set the HAB path, install dependencies, and run the scenario with medhelm-run. For general MedHELM install, see Installation and Quick Start. API keys: Credentials.

What MedHELM runs

One MedHELM instance is one Playwright episode. The adapter routes the outer request to the internal deployment hab/harness. OpenAI-chat-compatible model_deployments run as HelmBackedAgent (each browser step is an inner AutoClient request). Native HAB agents (RandomAgent, Claude, Gemini) stay an override in health_admin_bench_model_map.yaml. The model completion is HAB EvaluationResult JSON. The leaderboard metric is health_admin_bench_score (subeval points / max, 0–1), under Administration and Workflow.

Get the code

You need two checkouts next to each other: MedHELM and HealthAdminBench. Clone HAB from som-shahlab/health-admin-bench (main). MedHELM calls HAB in-process (run_task(agent=..., llm_complete=...)).

# Parent directory for both repos (adjust as you like)
mkdir -p ~/src && cd ~/src

git clone https://github.com/PacificAI/medhelm.git
git clone https://github.com/som-shahlab/health-admin-bench.git

Expected layout:

~/src/
  medhelm/              # PacificAI/medhelm
  health-admin-bench/   # som-shahlab/health-admin-bench

The directories do not have to be siblings, but a single parent folder is easiest. Record the absolute path to the HAB checkout; MedHELM will not find task JSON files without it.

Set the HAB path

Export this in every shell that runs medhelm-run (or put it in ~/.zshrc / ~/.bashrc):

export HEALTH_ADMIN_BENCH_ROOT="$HOME/src/health-admin-bench"

Replace $HOME/src/health-admin-bench with the absolute path from git clone. You can also pass hab_root=/absolute/path/to/health-admin-bench on the run entry instead of the env var.

Check:

test -f "$HEALTH_ADMIN_BENCH_ROOT/run.py" && echo "HAB root OK"

Install dependencies

MedHELM needs Python 3.12. HealthAdminBench needs Python ≥ 3.10, uv, and Playwright Chromium. Node.js is only required if you run the local portals or build the helm-server UI.

Install uv if needed:

curl -LsSf https://astral.sh/uv/install.sh | sh
source "$HOME/.local/bin/env"

1. HealthAdminBench harness

cd "$HEALTH_ADMIN_BENCH_ROOT"
uv sync
uv run hab install          # Playwright Chromium + copy .env.local → .env

hab install is required even when you only drive HAB from MedHELM: it installs Chromium and creates HAB .env.

2. MedHELM with the HealthAdminBench extra

HealthAdminBench is not in the default MedHELM install (uv pip install -e .). The scenario code lives in this repo, but Playwright and HAB itself are opt-in — the same idea as [summarization] and [gated] in Installation.

Install MedHELM and the HAB package into the same MedHELM virtualenv. Playwright must be available in that env, not only in HAB’s .venv.

cd /path/to/medhelm
uv venv --python 3.12 .venv
source .venv/bin/activate
uv pip install -e ".[health-admin-bench]"   # MedHELM + Playwright extras (not default)
uv pip install -e "$HEALTH_ADMIN_BENCH_ROOT"  # HAB harness (separate repo)
python -m playwright install chromium
Extra What it adds
[health-admin-bench] Playwright, jmespath, loguru, pydantic-settings
Editable HAB install harness / run.py imports used by HealthAdminBenchClient

3. Leaderboard UI (optional, before helm-server)

A git clone does not ship a pre-built frontend. If you want the web UI:

cd /path/to/medhelm/helm-frontend
npm install
npm run build -- --outDir '../src/helm/benchmark/static_build' --emptyOutDir

Credentials

MedHELM agent and judge HTTP use prod_env/credentials.conf (HOCON), not HAB .env and not OPENAI_API_KEY. Create prod_env/ next to medhelm-run if needed (the directory is gitignored).

Key Used by
openaiApiKey Public OpenAI deployments (openai/gpt-4o-…)
xaiApiKey Grok (xai/grok-…)
stanfordhealthcareApiKey + stanfordhealthcareEndpoint Package judges YAML and stanfordhealthcare/* Azure/APIM
azureApiKey + azureEndpoint A local azure/… row in prod_env/model_deployments.yaml

Example (public OpenAI):

openaiApiKey: sk-...
xaiApiKey: xai-...

Example (your Azure OpenAI resource; prefix of the deployment name is the credential prefix):

azureApiKey: ...
azureEndpoint: https://<resource>.openai.azure.com

You do not need openaiApiKey if the agent and judge both use Azure (azure/… or stanfordhealthcare/…).

HAB .env is only for hab_native agents (Claude / Gemini) and the OpenRouter judge fallback when the envelope has no MedHELM judge:

cd "$HEALTH_ADMIN_BENCH_ROOT"
echo 'ANTHROPIC_API_KEY=sk-ant-...' >> .env
echo 'GEMINI_API_KEY=...'           >> .env
echo 'OPENROUTER_API_KEY=sk-or-...' >> .env   # only if you skip jury_config_path

Do not commit .env or credentials.conf.

Portals

Hosted portals default to https://emrportal.vercel.app. To run a local EMR portal:

cd "$HEALTH_ADMIN_BENCH_ROOT/benchmark/v2/portals"
npm install && npm run dev

Then pass env_base_url=http://localhost:3002 in the run entry.

Parallelism

HealthAdminBench episodes are always serial. MedHELM --num-threads (default 4) is an in-process thread pool over make_request(), not HAB --max-parallel / -j. Playwright’s sync API and the harness os.chdir cannot overlap. If you pass --num-threads 4, MedHELM ignores it for HAB runs and still executes one episode at a time (you will see a warning). --num-threads 1 avoids the warning.

Smoke test (no frontier API)

simple/model1 maps to HealthAdminBench RandomAgent. Expect a failed episode on emr-easy-1: the random agent does not complete the workflow. This only checks that MedHELM can find HAB, launch Chromium, and write stats.

The default judge is still Stanford Healthcare. Without jury_config_path (or SHC keys), LLM-judge subevals score 0 with [COMPLETE_ERROR] and the episode still finishes. Pass a public or Azure judges YAML if you want a real judge on this smoke.

export HEALTH_ADMIN_BENCH_ROOT=/absolute/path/to/health-admin-bench
cd /path/to/medhelm
source .venv/bin/activate

medhelm-run --run-entries \
  "health_admin_bench:task_ids=emr-easy-1,max_steps=3,model=simple/model1,model_deployment=simple/model1" \
  --suite hab-poc --max-eval-instances 1 --num-threads 1
helm-summarize --suite hab-poc -o ./benchmark_output
helm-server --suite hab-poc -o ./benchmark_output --port 8000

Open http://localhost:8000. HealthAdminBench is under Administration and Workflow.

Optional standalone check (HAB CLI, same task):

cd "$HEALTH_ADMIN_BENCH_ROOT"
uv run hab run --model random --task emr-easy-1 --observation-mode axtree_only --prompt-mode general

Evaluated model (HelmBackedAgent)

If the run entry’s model_deployment exists and its client is OpenAIClient or a chat-compatible subclass (GrokChatClient, AzureOpenAIClient, OpenAI-API base_url), HealthAdminBenchClient builds HelmBackedAgent. No map row is required.

Public OpenAI (needs openaiApiKey):

export HEALTH_ADMIN_BENCH_ROOT=/absolute/path/to/health-admin-bench
cd /path/to/medhelm
source .venv/bin/activate

medhelm-run --run-entries \
  "health_admin_bench:task_ids=emr-easy-1,observation_mode=axtree_only,jury_config_path=src/helm/benchmark/static/health_admin_bench_judges.yaml,model=openai/gpt-4o-2024-05-13,model_deployment=openai/gpt-4o-2024-05-13" \
  --suite hab-poc --max-eval-instances 1 --num-threads 1

Grok:

medhelm-run --run-entries \
  "health_admin_bench:task_ids=emr-easy-1,observation_mode=axtree_only,jury_config_path=src/helm/benchmark/static/health_admin_bench_judges.yaml,model=xai/grok-4-0709,model_deployment=xai/grok-4-0709" \
  --suite hab-poc --max-eval-instances 1 --num-threads 1

Local OpenAI-compatible server: add a row in prod_env/model_deployments.yaml with helm.clients.openai_client.OpenAIClient and base_url. See Adding New Models.

Local Azure OpenAI (no public openaiApiKey): add a deployment whose name prefix matches the credential keys (azure → azureApiKey / azureEndpoint):

# prod_env/model_deployments.yaml
model_deployments:
  - name: azure/gpt-5-mini
    model_name: openai/gpt-5-mini-2025-08-07
    tokenizer_name: openai/o200k_base
    max_sequence_length: 400000
    client_spec:
      class_name: "helm.clients.azure_openai_client.AzureOpenAIClient"
      args:
        azure_openai_deployment_name: gpt-5-mini   # Azure deployment name
        api_version: "2024-06-01"

Point the judge at the same deployment (example prod_env/health_admin_bench_judges.yaml):

judges:
  - name: gpt
    model: openai/gpt-5-mini-2025-08-07
    model_deployment: azure/gpt-5-mini
medhelm-run --run-entries \
  "health_admin_bench:task_ids=emr-easy-1,observation_mode=axtree_only,is_gui=true,jury_config_path=prod_env/health_admin_bench_judges.yaml,model=openai/gpt-5-mini-2025-08-07,model_deployment=azure/gpt-5-mini" \
  --suite hab-azure --max-eval-instances 1 --num-threads 1

is_gui=true is a run-entry argument (headless=False). There is no medhelm-run --is-gui flag.

Stanford Healthcare Azure GPT-5 (needs stanfordhealthcareApiKey + stanfordhealthcareEndpoint): model_deployment=stanfordhealthcare/gpt-5-2025-08-07. Omit jury_config_path to reuse the package SHC judges.

Non-OpenAI-chat clients fail closed unless src/helm/benchmark/static/health_admin_bench_model_map.yaml sets backend: hab_native (RandomAgent, Claude, Gemini).

Judges

Reuse HealthBench get_annotator_models_from_config(jury_config_path). The first YAML judge is copied onto the episode envelope. HAB LLMJudge still runs inside evaluate_episode (portal `` state, JSON parse, majority vote). Only the HTTP call goes through AutoClient via llm_complete.

HAB may pass system, temperature, max_tokens, and a native judge model id (often gpt-5.4 from the task JSON). MedHELM uses envelope judge_model / judge_model_deployment for the AutoClient Request — it does not treat HAB’s native id as a MedHELM model name. A one-argument complete(prompt) -> str still works.

If the callback raises (timeout, missing key, Azure/auth), HAB records [COMPLETE_ERROR] Type: message, scores that run 0, and continues majority vote. The episode returns a structured eval row instead of aborting grade(). Extra HTTP retries stay on HAB’s native path only.

  • Default: package helm.benchmark.scenarios.medhelm.judges.yaml (Stanford Healthcare → stanfordhealthcareApiKey).
  • Public OpenAI judge: jury_config_path=src/helm/benchmark/static/health_admin_bench_judges.yaml (openaiApiKey).
  • Local Azure judge: jury_config_path=prod_env/health_admin_bench_judges.yaml as above.
  • Override: judge_model / judge_model_deployment.

Do not set the judge to hab/harness. Do not use the evaluated model as judge unless the run spec sets them equal on purpose. Keep HAB’s JSON grader contract {score, reasoning, evidence_quote} — HealthBench <score> tags parse as 0.

Run-spec arguments

Commas separate args, so multiple task ids use +:

health_admin_bench:task_ids=emr-easy-1+emr-easy-2,task_set=prior_auth,difficulty=easy,model=...,model_deployment=...
Argument Default Notes
task_ids (all matching filters) e.g. emr-easy-1
task_set prior_auth prior_auth | appeals_denials | dme | all
difficulty easy easy | medium | hard | all
prompt_mode general zero_shot | general | task_specific
observation_mode axtree_only axtree_only for HelmBackedAgent; screenshot_only / both are later
action_space dom dom | coordinate
env_base_url https://emrportal.vercel.app local: http://localhost:3002
hab_root $HEALTH_ADMIN_BENCH_ROOT absolute path to the HAB checkout
max_steps HAB defaults (easy ≈ 20) cap episode length for smoke tests
is_gui false true shows Chromium. Put this in the run entry, not as medhelm-run --is-gui.
jury_config_path package judges.yaml (SHC) see Judges above
judge_model / judge_model_deployment first judge in that YAML run-entry override

--max-eval-instances N still applies after the scenario loads tasks. For all 20 prior-auth easy tasks use task_ids=emr-easy-1+…+emr-easy-20 (or task_set=prior_auth,difficulty=easy) and --max-eval-instances 20.

After a run:

helm-summarize --suite <suite> -o ./benchmark_output
helm-server --suite <suite> -o ./benchmark_output --port 8000

Troubleshooting

Symptom Fix
Task JSON / run.py not found Export HEALTH_ADMIN_BENCH_ROOT or pass hab_root=. MedHELM also looks at ./health-admin-bench and ../health-admin-bench relative to cwd (not the package install path). Clone som-shahlab/health-admin-bench (main).
ModuleNotFoundError: harness / HAB imports uv pip install -e "$HEALTH_ADMIN_BENCH_ROOT" into the MedHELM venv.
Playwright browser missing source .venv/bin/activate && python -m playwright install chromium (MedHELM venv).
The api_key client option must be set / openaiApiKey should be specified HelmBackedAgent reads prod_env/credentials.conf, not HAB .env. Match the key to the deployment prefix (openaiApiKey, azureApiKey, stanfordhealthcareApiKey).
Judge looks for Stanford credentials / stanfordhealthcareApiKey Default judges YAML is SHC. Pass jury_config_path= to a public OpenAI or local Azure judges file.
[COMPLETE_ERROR] / judge run_scores=[0,0,0] Callback failed (missing key, timeout, auth). Episode still finishes; fix credentials or jury_config_path.
prod_env/cache does not exist Create it once (mkdir -p prod_env/cache). Cache paths are stored absolute so HAB os.chdir does not resolve prod_env/cache under the HAB checkout.
OPENROUTER_API_KEY is required Only if no MedHELM judge is on the envelope. Prefer jury_config_path.
no agent for model X / not OpenAI-chat-compatible Use OpenAIClient / GrokChatClient / AzureOpenAIClient, or a hab_native map row.
missing evaluated_model / evaluated_model_deployment Set model= and model_deployment= on the run entry. The client fails with that message instead of a generic no-agent miss.
invalid prompt_mode / observation_mode / action_space Use zero_shot | general | task_specific, screenshot_only | axtree_only | both, dom | coordinate. The client lists those values in the error.
must not be hab/harness Agent and judge deployments cannot be hab/harness.
GUI never opens is_gui=true inside the run-entry string, not --is-gui on medhelm-run.
ModuleNotFoundError: helm.benchmark.static_build Build the frontend (step 3).
Warning about --num-threads Harmless; HAB episodes stay serial. Use --num-threads 1 to silence it.
Hosted portal changed Pin env_base_url or run local portals on :3002.

Summary

Step Command
Clone MedHELM git clone https://github.com/PacificAI/medhelm.git
Clone HAB git clone https://github.com/som-shahlab/health-admin-bench.git
Point MedHELM at HAB export HEALTH_ADMIN_BENCH_ROOT=/absolute/path/to/health-admin-bench
Install HAB cd "$HEALTH_ADMIN_BENCH_ROOT" && uv sync && uv run hab install
Install MedHELM extra uv pip install -e ".[health-admin-bench]" && uv pip install -e "$HEALTH_ADMIN_BENCH_ROOT"
Smoke test medhelm-run --run-entries "health_admin_bench:task_ids=emr-easy-1,max_steps=3,model=simple/model1,model_deployment=simple/model1" --suite hab-poc --max-eval-instances 1 --num-threads 1