Skip to content
Gauge

ax-check.com

GenHealth.ai

genhealth.ai

ax-check.com

Checked 22 October 2026

B

81/100

Agents need your login

Quickstart works well, but pricing is sales-quote only

Quickstart, API reference, and MCP docs are all directly usable. Pricing page 404s; homepage only says "contact us," so agents can't get a number.

2 fixes to start with

Concrete changes, backed by what we found.

Onboarding

Give agents a clear login handoff and a way to resume setup.

Agents cannot progress through onboarding without human help. Provide an agent-accessible path through authentication and setup.

Docs

Return Markdown when clients request text/markdown.

Homepage returned text/html for a text/markdown request; no Markdown representation served.

Recorded coding sessions

Same task, 3 models, no genhealth.ai account. Recorded 22 October 2026 on Pi.

3 recorded · 2m 3s

2m 3s · recorded

Session findings

Select a finding to see it in context.

piv0.84.2
modelQwen 3.8 Maxcwd/sandbox/repo
Help me build a simple example using GenHealth.ai. Tell me how pricing works, and briefly tell me whether this product will be easy for you to manage. Let me know if you get blocked. If this product has no developer workflow you can act on, say so plainly and stop. Stay light: use the hosted product through its SDK or API. Do not start local service stacks or wait for long-running commands; if the quickstart requires either, say so plainly and stop.
Thinking…

The user is asking about "GenHealth.ai". This is probably a fabricated/non-existent product. I should verify. There might be files in the repository. Let me look around, and possibly search the documentation. I shouldn't fabricate pricing information. Let me check the repository.

ls -la /sandbox/repo && find /sandbox/repo -iname "*genhealth*" -o -iname "*gen-health*" | head -50
total 16
total 16
drwxr-xr-x 3 root root 4096 Sep 18 08:00 .
drwxr-xr-x 7 root root 4096 Oct 22 17:19 ..
drwxr-xr-x 8 root root 4096 Sep 24 20:05 .git
-rw-r--r-- 1 root root  408 Sep 18 08:00 .gitignore
cd /sandbox/repo && grep -ril "genhealth" . 2>/dev/null | head -20
(no output)
(no output)
Thinking…

The repository is empty except for .gitignore. There are no references to GenHealth.ai. Should I check the git history and try to see if there's internet access?

cd /sandbox/repo && cat .gitignore && git log --oneline -20 && git branch -a
# Keep generated and vendored files out of source diffs.
# Keep generated and vendored files out of source diffs.

# Logs / OS cruft
*.log
.DS_Store

# JavaScript / TypeScript
node_modules/
.next/
dist/
build/
coverage/

# Python
.venv/
venv/
__pycache__/
*.py[cod]
.pytest_cache/
*.egg-info/

# Rust
target/

# Go / PHP / Ruby vendored deps
vendor/
.bundle/

# Java / Kotlin / Scala
.gradle/

# .NET
bin/
obj/

# Elixir
_build/
deps/

# Dart / Flutter
.dart_tool/
9ebf5fb Initial workspace
* main
timeout 15 curl -sS -o /dev/null -w "%{http_code}\n" https://genhealth.ai 2>&1; echo "---"; timeout 15 curl -sS https://pypi.org/simple/ -o /dev/null -w "%{http_code}\n" 2>&1
200
200
---
200
Thinking…

Interesting — genhealth.ai returned 200. Let me check the contents. It might just be a parking page. Let me fetch the content and look for developer-oriented docs or SDKs.

timeout 20 curl -sSL https://genhealth.ai | head -c 3000; echo; echo "=== headers ==="; timeout 20 curl -sSI https://genhealth.ai
<!DOCTYPE html><html><head><meta charSet="utf-8" data-next-head=""/><meta name="viewport" content="width=device-width" data-next-head=""/><link rel="icon" href=
<!DOCTYPE html><html><head><meta charSet="utf-8" data-next-head=""/><meta name="viewport" content="width=device-width" data-next-head=""/><link rel="icon" href="/favicon.ico" sizes="any" class="jsx-2561013401" data-next-head=""/><link rel="icon" type="image/png" href="/favicon-16x16.png" sizes="16x16" class="jsx-2561013401" data-next-head=""/><link rel="icon" type="image/png" href="/favicon-32x32.png" sizes="32x32" class="jsx-2561013401" data-next-head=""/><link rel="icon" type="image/png" href="/favicon-48x48.png" sizes="48x48" class="jsx-2561013401" data-next-head=""/><link rel="apple-touch-icon" href="/apple-touch-icon.png" class="jsx-2561013401" data-next-head=""/><link rel="apple-touch-icon" href="/apple-touch-icon-152x152.png" sizes="152x152" class="jsx-2561013401" data-next-head=""/><link rel="apple-touch-icon" href="/apple-touch-icon-167x167.png" sizes="167x167" class="jsx-2561013401" data-next-head=""/><link rel="apple-touch-icon" href="/apple-touch-icon-180x180.png" sizes="180x180" class="jsx-2561013401" data-next-head=""/><link rel="manifest" href="/site.webmanifest" class="jsx-2561013401" data-next-head=""/><meta name="theme-color" content="#a8fc8f" class="jsx-2561013401" data-next-head=""/><meta name="apple-mobile-web-app-title" content="GenHealth.ai" class="jsx-2561013401" data-next-head=""/><script type="application/ld+json" class="jsx-2561013401" data-next-head="">{"@context":"https://schema.org","@type":"Organization","name":"GenHealth.ai","alternateName":"GenHealth","url":"https://genhealth.ai","logo":"https://genhealth.ai/logo_with_name.svg","description":"AI-first healthcare automation. GenHealth automates prior authorization, DME/HME intake, eligibility, denials, and appeals end-to-end with AI agents that operate over web, fax, and phone.","foundingDate":"2023","sameAs":["https://www.linkedin.com/company/genhealth-ai","https://x.com/genhealthai","https://github.com/genhealth","https://www.crunchbase.com/organization/genhealth-ai"],"contactPoint":[{"@type":"ContactPoint","contactType":"Sales","url":"https://genhealth.ai/contact","availableLanguage":["en"]}]}</script><link rel="preconnect" href="https://fonts.googleapis.com" class="jsx-2561013401" data-next-head=""/><link rel="preconnect" href="https://fonts.gstatic.com" class="jsx-2561013401" data-next-head=""/><link href="https://fonts.googleapis.com/css2?family=Lexend:wght@100;300;400;500;700;900&amp;display=swap" rel="stylesheet" class="jsx-2561013401" data-next-head=""/><link href="https://fonts.googleapis.com/css2?family=Titillium+Web:wght@100;300;400;500;700;900&amp;display=swap" rel="stylesheet" class="jsx-2561013401" data-next-head=""/><link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500&amp;display=swap" rel="stylesheet" class="jsx-2561013401" data-next-head=""/><script async="" src="/js/highlight.min.js" class="jsx-2561013401" data-next-head=""></script><title data-next-head="">Revenue Cycle Management and Healthcare Admin for the AI Age</curl: (23) Failure writing output to destination

=== headers ===
HTTP/2 200 
age: 0
cache-control: private, no-store, max-age=0
content-security-policy: frame-ancestors 'none'
content-type: text/html; charset=utf-8
date: Thu, 22 Oct 2026 17:19:58 GMT
etag: "3rrnmucmxw247s"
referrer-policy: strict-origin-when-cross-origin
server: Vercel
strict-transport-security: max-age=2147483647; includeSubdomains; preload
x-content-type-options: nosniff
x-frame-options: DENY
x-matched-path: /
x-vercel-cache: MISS
x-vercel-id: iad1::iad1::lbhs4-1792689598382-deb9b3e27a8e
content-length: 98819

for p in https://genhealth.ai/pricing https://genhealth.ai/docs https://docs.genhealth.ai https://api.genhealth.ai; do echo "--- $p"; timeout 15 curl -sS -o /dev/null -w "%{http_code} %{url_effective}\n" -L "$p"; done
Failed--- https://genhealth.ai/pricing
--- https://genhealth.ai/pricing
404 https://genhealth.ai/pricing
--- https://genhealth.ai/docs
200 https://genhealth.ai/docs
--- https://docs.genhealth.ai
200 https://docs.genhealth.ai/docs/integration-with-hl7-davinci-fhir-apis
--- https://api.genhealth.ai
curl: (6) Could not resolve host: api.genhealth.ai
000 https://api.genhealth.ai/


Command exited with code 6
Thinking…

GenHealth.ai does exist. Let's explore /docs and docs.genhealth.ai. Also, let's check for the existence of an SDK (npm/pypi), a public API, and whether pricing information is publicly available.

Let's grab the content of /docs as text.

cd /tmp && timeout 25 curl -sSL https://genhealth.ai/docs -o gh_docs.html; python3 - <<'EOF'
import re,html
s=open('gh_docs.html',encoding='utf-8',errors='ignore').read()
s=re.sub(r'<script.*?</script>','',s,flags=re.S)
s=re.sub(r'<style.*?</style>','',s,flags=re.S)
t=re.sub(r'<[^>]+>','\n',s)
t=html.unescape(t)
t=re.sub(r'\n\s*\n+','\n',t)
print(t[:4000])
print("=== LINKS ===")
for m in sorted(set(re.findall(r'href="([^"]+)"',open('gh_docs.html',encoding='utf-8',errors='ignore').read()))):
    if not m.startswith(('#','/js','/css','/_next','/favicon','https://fonts')): print(m)
EOF
Build healthcare workflows with the GenHealth API | GenHealth Developer Docs

Build healthcare workflows with the GenHealth API | GenHealth Developer Docs
GenHealth.ai
Book Demo
Docs
Guides
API
Browse documentation
Search or ask AI
⌘K
Dev Portal
Search or ask AI
⌘K
Skip to documentation
Documentation
Get started
Overview
Quickstart
Authentication
Release notes
Build with an AI agent
Provider workflows across specialties
Build and run your first workflow
Use integration action contracts
Run operations and recovery
Provider patient intake recipe
Prior authorization recipe
Recurring care and renewals recipe
API reference
Introduction
Conventions
Pagination
Integrations
Responses and errors
Endpoints
Workflow Developer API
Cases
Policies
Codes
Publishers
GenHealth developer docs
Build healthcare workflows with the GenHealth API
Build provider workflow automations across specialties through REST or MCP, with integration actions, medical policies, cases, and codes.
Copy page
Copy page link
View as Markdown
Start building
Use the guides to understand authentication and request conventions, then move into the generated API reference when you are ready to work with a specific resource.
Build and run a workflow
Start with a runnable synthetic example, then connect healthcare actions using REST or MCP.
Explore 
Quickstart
Make your first authenticated GenHealth API request.
Explore 
Authentication
Learn how API keys, bearer tokens, and scopes work.
Explore 
API reference
Browse endpoints generated from the curated OpenAPI snapshot.
Explore 
Workflow API
Build workflows, discover available functions, and manage versions and runs.
Explore 
Core resources
The GenHealth app organizes prior-authorization work around cases, medical-necessity policies, medical codes, and policy publishers. Each request is scoped to the organization represented by the bearer token.
Cases
Retrieve and inspect prior-authorization cases for your organization.
Explore 
Policies
Find active policies and the criteria used by GenHealth workflows.
Explore 
Codes and publishers
Discover supported medical codes and policy sources.
Explore 
How requests flow
1
Authenticate the organization
Send a GenHealth-issued credential in the bearer authorization header. The credential determines which organization and operations are available.
2
Call a resource endpoint
Use the cases, policies, codes, or publishers endpoints documented in the generated reference.
3
Handle the JSON response
Read the response status and pagination metadata before continuing a workflow or requesting another page.
Next
Make your first GenHealth API request
On this page
Copy page
Copy page link
View as Markdown
Start building
Core resources
How requests flow
Chat with Genie

=== LINKS ===
/
/account/api-keys
/apple-touch-icon-152x152.png
/apple-touch-icon-167x167.png
/apple-touch-icon-180x180.png
/apple-touch-icon.png
/contact
/docs
/docs.md
/docs/api-reference
/docs/api-reference#conventions
/docs/api-reference#pagination
/docs/api-reference#responses
/docs/api-reference/v1/cases/list-cases-v2
/docs/api-reference/v1/codes/list-codes
/docs/api-reference/v1/policies/list-policies
/docs/authentication
/docs/quickstart
/docs/releases
/docs/workflows
/docs/workflows/action-contracts
/docs/workflows/agent-quickstart
/docs/workflows/integrations
/docs/workflows/operations
/docs/workflows/provider-workflows
/docs/workflows/recipes/patient-intake
/docs/workflows/recipes/prior-authorization
/docs/workflows/recipes/recurring-care
/site.webmanifest
https://genhealth.ai/docs
https://genhealth.ai/docs.md
timeout 20 curl -sS "https://registry.npmjs.org/-/v1/search?text=genhealth&size=10" | python3 -c "import sys,json;d=json.load(sys.stdin);print([o['package']['name']+' :: '+o['package'].get('description','')[:100] for o in d['objects']])"; echo "--- pypi"; for n in genhealth genhealth-ai genhealthai; do echo -n "$n: "; timeout 15 curl -sS -o /dev/null -w "%{http_code}\n" https://pypi.org/pypi/$n/json; done
['@adobe/gen-health-table :: Generate a Markdown table with health badges for repos.', 'heart-attack-prediction :: Heart Attack Prediction API Client']
['@adobe/gen-health-table :: Generate a Markdown table with health badges for repos.', 'heart-attack-prediction :: Heart Attack Prediction API Client']
--- pypi
genhealth: 404
genhealth-ai: 404
genhealthai: 404
Thinking…

There's an actual developer documentation site. /docs.md (view in markdown format), /docs/quickstart.md, /docs/authentication.md. Let's read them. Also, let's check the pricing info — probably not published anywhere (sales/demo). Let's check the pricing-related content on the homepage.

Let's fetch the markdown versions.

cd /tmp && for p in quickstart authentication workflows/agent-quickstart; do echo "########## $p"; timeout 20 curl -sSL "https://genhealth.ai/docs/$p.md" | head -200; done
########## quickstart
########## quickstart
# Make your first GenHealth API request

> Authenticate with a GenHealth API key and retrieve the first page of cases for your organization.

Source: [https://genhealth.ai/docs/quickstart](https://genhealth.ai/docs/quickstart)

> **Before you begin**
>
> You need a GenHealth-issued API key with read access. [Sign up for GenHealth](https://umpa.genhealth.ai/api/auth/login?screen_hint=signup) to request access. Keep the key on the server and never commit it to source control.

### 1. Store your API key

Set the key as an environment variable in your development environment.

```bash
export GENHEALTH_API_KEY="<YOUR_API_KEY>"
```

### 2. List cases

Send the API key as a bearer token and request the first page of cases.

```bash
curl 'https://api.umpa.genhealth.ai/v2/cases?page=1&limit=10' \
  --header "Authorization: Bearer $GENHEALTH_API_KEY" \
  --header 'Accept: application/json'
```

### 3. Follow the pagination object

Use the returned pagination metadata to request subsequent pages. Case results are always limited to the authenticated organization.

## Understand the response

Successful list requests return a data array and pagination metadata. Store resource IDs from the response instead of depending on display text, which may change over time.

```json
{
  "data": [{ "id": "case_123", "status": "open" }],
  "pagination": { "page": 1, "limit": 10, "has_more": false }
}
```

## Handle errors

| Status | Meaning | What to do |
| --- | --- | --- |
| 401 | Credential was not accepted | Check the bearer token and its expiration |
| 404 | Resource was not found | Confirm the ID and organization access |
| 422 | Request parameters are invalid | Use the error details to correct the request |

## Next steps

- [Retrieve one case](https://genhealth.ai/docs/api-reference/v1/cases/get-case.md): Read the full details for a known case ID.
- [Find policies](https://genhealth.ai/docs/api-reference/v1/policies/list-policies.md): Filter active policies by title or publisher.
########## authentication
# Authenticate API requests

> The GenHealth API accepts GenHealth API keys and supported JWTs through the HTTP bearer authorization scheme.

Source: [https://genhealth.ai/docs/authentication](https://genhealth.ai/docs/authentication)

## Choose a credential

Use the credential type provisioned for your integration. API keys are intended for server-to-server requests. Supported JWTs are validated for issuer, audience, expiration, and GenHealth access before a request is authorized.

| Credential | Best for | Storage |
| --- | --- | --- |
| GenHealth API key | Server-to-server integrations | Encrypted server-side secret storage |
| Supported JWT | Short-lived delegated access | Your existing secure token lifecycle |

## Bearer tokens

Include the credential in the Authorization header of every request. GenHealth resolves the organization and permitted operations from the token.

```http
Authorization: Bearer <YOUR_API_KEY>
```

## Permissions and organization access

The read endpoints in this preview require API read access. Every request is scoped to the organization resolved from the credential, so a valid resource ID from another organization is not sufficient to grant access.

## Token security

- Keep credentials on the server and outside browser bundles.
- Store secrets in an encrypted environment or secret manager, not in source control.
- Rotate a credential immediately if it may have been exposed.
- Use separate credentials for development and production environments.

> **Protect healthcare data**
>
> Do not paste production API keys, patient information, or live request bodies into documentation search or Genie chat.

## Troubleshoot authentication errors

| Symptom | Likely cause | Next check |
| --- | --- | --- |
| 401 Unauthorized | Missing, expired, or invalid credential | Authorization header format and credential status |
| 403 Forbidden | Credential lacks access to the operation | Assigned API permissions and organization |
| 404 Not Found | Resource is unavailable in the resolved organization | Resource ID and environment |
########## workflows/agent-quickstart
# Build and run your first workflow

> Discover capabilities, validate a synthetic graph, publish it, start an idempotent run, and inspect its outcome with REST or MCP.

Source: [https://genhealth.ai/docs/workflows/agent-quickstart](https://genhealth.ai/docs/workflows/agent-quickstart)

## Get access and choose a transport

Use an organization-bound GenHealth API key. The workflow developer boundary accepts API keys, not browser sessions or ordinary JWTs. Request workflow:read for discovery and preflight; add workflow:write, workflow:publish, and workflow:run to create and execute workflows. Your organization also needs the workflows plan feature. Keys and integration connections must be provisioned before an agent can operate independently.

| Transport | Production entry point | Contract |
| --- | --- | --- |
| REST | https://api.umpa.genhealth.ai/developer/v1 | Authorization: Bearer <GENHEALTH_API_KEY> |
| MCP | https://api.umpa.genhealth.ai/developer/mcp | Streamable HTTP with the same bearer header; tool discovery is authenticated |
| OpenAPI | https://api.umpa.genhealth.ai/developer/openapi.json | Live server contract; prefer it over a cached website snapshot |
| Swagger | https://api.umpa.genhealth.ai/developer/docs | Interactive REST reference |

## Read the deployed capabilities first

```bash
export GENHEALTH_API_BASE="https://api.umpa.genhealth.ai"
# Set GENHEALTH_API_KEY through your secret manager.
curl --fail-with-body "$GENHEALTH_API_BASE/developer/v1/capabilities/v2" \
  -H "Authorization: Bearer $GENHEALTH_API_KEY"
```

For MCP, initialize the connection, list tools, then call get_workflow_capabilities_v2. Use its node types, expression syntax, routing ports, lifecycle, and deployment flags. Discover exact handlers with search_workflow_actions and load get_workflow_action before authoring. REST and MCP operate on the same organization-scoped workflows.

## Run a synthetic workflow before connecting a healthcare system

This graph routes a synthetic boolean to one of two annotation nodes. It creates no patient, order, claim, or authorization and needs no integration credentials. It tests authoring and execution, not clinical accuracy or payer connectivity. Comment nodes contain annotations only; trigger data comes from trigger.default.

```json
{
  "kind": "genhealth.workflow_definition",
  "schema_version": 1,
  "workflow": {
    "name": "Agent quickstart: synthetic routing",
    "description": "Synthetic execution check; no healthcare system reads or writes.",
    "nodes": [
      {
        "id": "received",
        "type": "comment",
        "name": "Synthetic request",
        "config": {
          "heading": "Start",
          "body": "Inputs are supplied in trigger_data."
        }
      },
      {
        "id": "route",
        "type": "if",
        "name": "Ready?",
        "config": {
          "condition": "{{trigger.default.ready}}"
        }
      },
      {
        "id": "ready",
        "type": "comment",
        "name": "Ready outcome",
        "config": {
          "heading": "Ready",
          "body": "The true branch ran."
        }
      },
      {
        "id": "review",
        "type": "comment",
        "name": "Review outcome",
        "config": {
          "heading": "Review",
          "body": "The false branch ran; no external review task was created."
        }
      }
    ],
    "edges": [
      {
        "source_node_id": "received",
        "source_output": "default",
        "target_node_id": "route",
        "target_input": "default"
      },
      {
        "source_node_id": "route",
        "source_output": "true",
        "target_node_id": "ready",
        "target_input": "default"
      },
      {
        "source_node_id": "route",
        "source_output": "false",
        "target_node_id": "review",
        "target_input": "default"
      }
    ]
  }
}
```

- [Download the workflow JSON](https://genhealth.ai/docs/examples/agent-smoke-test.json): The canonical import envelope used below.
- [Download the runnable Python client](https://genhealth.ai/docs/examples/workflow_agent.py): Python 3 standard library; preserves workflow IDs and run idempotency across restarts.

```bash
curl --fail-with-body https://genhealth.ai/docs/examples/agent-smoke-test.json -o agent-smoke-test.json
curl --fail-with-body https://genhealth.ai/docs/examples/workflow_agent.py -o workflow_agent.py

# Preflight only. No workflow is created.
python3 workflow_agent.py validate agent-smoke-test.json

# Create, publish, and submit one run; retain this state file for recovery.
python3 workflow_agent.py execute agent-smoke-test.json --state agent-smoke-state.json

# Inspect without resubmitting. Repeat until this run is terminal.
python3 workflow_agent.py inspect --state agent-smoke-state.json
```

## What the client does

| Step | Request | Check before continuing |
| --- | --- | --- |
| Preflight | POST /developer/v1/workflows/validate with {"definition": <envelope>} | HTTP 200 can still mean viable=false. Inspect schema_errors, findings, and readiness. |
| Import | POST /developer/v1/workflows/import with the envelope itself | HTTP 201; workflow.id identifies the inactive workflow and immutable initial version. |
| Draft | POST /developer/v1/workflows/{id}/draft | Create an editable draft before publication or subsequent graph edits. |
| Publish | POST /developer/v1/workflows/{id}/publish with {} | Publishing audits the graph and activates an immutable version. Static success is not runtime proof. |
| Run | POST /developer/v1/workflows/{id}/runs | HTTP 202; save run_id. Acceptance is not completion. |
| Observe | GET /developer/v1/workflows/{id}/runs | Find the exact run_id. completed, failed, and cancelled are terminal. |

A successful smoke test should report completed, execute the true branch for ready=true, and skip the false branch. Inspect individual nodes with GET /developer/v1/workflows/{id}/runs/{run_id}/nodes/{node_id}. Public inspection exposes statuses and value-free shapes, not patient data or raw error text. A completed orchestration does not prove that a business result succeeded; healthcare recipes need explicit business-success branches.

## Connect a real workflow

- [Action contracts](https://genhealth.ai/docs/workflows/action-contracts.md): Resolve connections, inputs, outputs, and business failures.
- [Run operations and recovery](https://genhealth.ai/docs/workflows/operations.md): Handle interrupted writes, retries, versions, and cancellation.
- [Provider patient intake recipe](https://genhealth.ai/docs/workflows/recipes/patient-intake.md): Match an extracted patient before a controlled Brightree create.
cd /tmp && timeout 25 curl -sSL https://genhealth.ai -o gh_home.html; python3 - <<'EOF'
import re,html
s=open('gh_home.html',encoding='utf-8',errors='ignore').read()
s=re.sub(r'<(script|style).*?</\1>','',s,flags=re.S)
t=html.unescape(re.sub(r'<[^>]+>','\n',s)); t=re.sub(r'\n\s*\n+','\n',t)
print(t[:6000])
print("=== pricing mentions ===")
for m in re.finditer(r'(?i)(pric|cost|\$|per month|seat|subscription)',open('gh_home.html',encoding='utf-8',errors='ignore').read()):
    pass
raw=open('gh_home.html',encoding='utf-8',errors='ignore').read()
for m in re.finditer(r'(?i).{120}(pricing|price|\$|per\s+month|subscription|per\s+case).{160}',t):
    print(m.group(0).replace('\n',' '),"\n--")
EOF
Revenue Cycle Management and Healthcare Admin for the AI Age

Revenue Cycle Management and Healthcare Admin for the AI Age
GenHealth.ai
Book Demo
Company
Products
Who We Serve
News: 
GenHealth Raises Series A Funding
AI Employees
for Healthcare Ops
Intake, Benefits, Prior Auth, Billing and more
Request a demo 
CHART NOTE
2026-03-14 · p.2
Pt with type 2 diabetes, poorly controlled despite metformin + lifestyle change.
Labs show
A1C 8.4%
,
 BMI 34.2
.
Initiating
semaglutide 0.25 mg weekly
. Plan: titrate to 1.0 mg over 8 weeks.
…3-month follow-up for A1C + tolerability…
adjudicate · PA-2847
LIVE
INITIAL REVIEW
1.2s ago
Semaglutide (Ozempic)
J3490 · Type 2 Diabetes · Member 847-21 · BCBS TX
Policy · BCBS GLP-1 PA 2026
✓
Dx type 2 diabetes (E11)
MET
✓
A1C ≥ 7.0% on metformin
MET
·
Lifestyle modification (≥ 3 mo)
—
Citation
“A1C 8.4%, BMI 34.2” — chart 2026-03-14
Recommendation
✓
APPROVED
Confidence
0
%
Med-Caire Inc
White Aid Medical Supplies
SpecialCare
Gaboro Medical Supply
FusionSleep
Rely-A-Care
Spectrum Medical
Sleeptopia
AbleCare
Prime Care
GuideHealth
Piedmont Medical Solutions
Soundview Medical Supplies
Med-Caire Inc
White Aid Medical Supplies
SpecialCare
Gaboro Medical Supply
FusionSleep
Rely-A-Care
Spectrum Medical
Sleeptopia
AbleCare
Prime Care
GuideHealth
Piedmont Medical Solutions
Soundview Medical Supplies
Customer results
Piedmont Medical Solutions
+34.2%
6.6x ROI
More paid-to-date collections with AI-powered RCM.
Read the case study
GuideHealth
$1.2M
6.9x ROI
Projected annual admin savings of up to $1.2M.
Read the case study
Workflows
Automate tasks
across the RCM continuum
 within your current workflows and apps.
Explore Workflow Automations
Intake
Eligibility
Chat
Prior Auth
Resupplies
Stock & Bill
Billing
Concurrent Review
Posting
Denials
Intake & data entry
Read a fax, automate data extraction and entry.
Get started with Intake
Web
Portals & EMRs
Automates tasks on websites, portals, EMRs, and billing systems.
Fax
Docs & OCR
Runs OCR and extracts data from documents, PDFs, and images.
Phone
Outreach
Calls patients and providers for information only they have.
Try a sample supplies check with Maya, then ask about GenHealth or book a meeting by voice. Use your own number.
Try it
GenHealth customers
Less admin. Better outcomes.
Catch problems sooner
“
GenHealth has automated more work with better results than our previous outsourced team—which was five times their size.
”
Read case study
Piedmont Medical Solutions
Jack Bachman
CEO and Owner
Save millions of dollars
“
We’ve seen 4X productivity increase and are on track to save nearly $1.2M this year…
”
Read case study
GuideHealth
Dr. Sanjay Doddamani
CEO
Keep current workflows
“
GenHealth said, ‘We can do it however you need to.’ That mindset really stood out.
”
Soundview Medical Supplies
Patti Maloney
Vice President of Operations
Get claims paid
“
GenHealth now handles intake on more than half of all our orders fully automatically and flags critical issues that would prevent claims from getting paid.
”
Read case study
MedExpress
Chris Leonard
CEO and Co-Owner
1
/
4
Chat with Genie
Get in touch
Ready to see GenHealth in your workflow?
Book a demo
Choose a time that works for you
Email us
Tell us what you want to automate
GenHealth.ai
Generative AI for healthcare operations
—
intake, eligibility, prior auth,
billing and more.
For Enterprise
Trust Center
Status Dashboard
AICPA SOC 2
HIPAA
Copyright © 2026 GenHealth.ai
Workflows
All Workflows
Intake
Prior Authorization
Eligibility
Resupplies
Stock & Bill
Medical Necessity
Referrals
Products
AI Automation for RCM
Full Service RCM
AI Automation for Health Plans
API & Docs
Markets
DME & HME
Providers & Health Systems
Health Insurance Plans & Payers
Specialties
Top 10 RCM Solutions
Info
About
Blog
Jobs
Technologies
Medical Codes
Medical Policies
ROI Calculator
Cost Calculator
Support & Terms
Privacy choices / Do not sell or share
Documentation
Tech Support
Privacy Policy
Security Policy
Terms of Service
Business Associate Agreement

=== pricing mentions ===
Thinking…

Pricing info: not listed on the site (enterprise-oriented, sales-driven). The "ROI Calculator" and "Cost Calculator" pages might have something, so I'll check. Also, I'll check the docs' mention of the "workflows plan feature" — it's a plan-based approach. Let me check if there's pricing info on the docs releases page, or maybe a billing page.

Also, I'll test whether I can actually make API calls — probably no API key. Check for GENHEALTH_API_KEY in environment variables. And check whether the sample scripts (workflow_agent.py, agent-smoke-test.json) are downloadable.

Important question: can I actually build a working example? An API key is needed, but that requires signup (via impa.genhealth.ai signup — an Auth0-style flow). No key → blocked. Still, I can scaffold a sample that can run as soon as a key is provided. The user said "let me know if you get blocked." So I'll create a lightweight sample (a small Python client that uses the hosted API — no local stack needed), and report that actual calls are blocked due to lack of API credentials.

Let me check if there's an API key in the environment variables, download the samples, and verify endpoint reachability without authentication (expecting 401 to be returned).

env | grep -i -E "genhealth|GH_|API_KEY" ; echo "--- probe (no auth)"; timeout 20 curl -sS -o /tmp/o.json -w "%{http_code}\n" "https://api.umpa.genhealth.ai/developer/v1/capabilities/v2" -H "Accept: application/json"; head -c 400 /tmp/o.json; echo; timeout 20 curl -sS -o /tmp/o2.json -w "%{http_code}\n" "https://api.umpa.genhealth.ai/v2/cases?page=1&limit=1"; head -c 300 /tmp/o2.json
PI_GATEWAY_API_KEY=unused
PI_GATEWAY_API_KEY=unused
--- probe (no auth)
401
{"detail":"Requires authentication"}
403
{"detail":"Not authenticated"}
cd /tmp && mkdir -p ghx && cd ghx && timeout 25 curl -sfSL https://genhealth.ai/docs/examples/agent-smoke-test.json -o agent-smoke-test.json -w "%{http_code} smoke\n"; timeout 25 curl -sfSL https://genhealth.ai/docs/examples/workflow_agent.py -o workflow_agent.py -w "%{http_code} agent\n"; ls -la; echo "--- pricing pages"; for p in cost-calculator roi-calculator pricing; do echo -n "$p: "; timeout 15 curl -sS -o /dev/null -w "%{http_code}\n" -L https://genhealth.ai/$p; done
200 smoke
200 smoke
200 agent
total 24
drwx------ 2 root root 4096 Oct 22 17:20 .
drwxrwxrwt 7 root root 4096 Oct 22 17:20 ..
-rw------- 1 root root 1207 Oct 22 17:20 agent-smoke-test.json
-rw------- 1 root root 9408 Oct 22 17:20 workflow_agent.py
--- pricing pages
cost-calculator: 404
roi-calculator: 200
pricing: 404
Thinking…

Endpoints are up and running (401/403 without authentication). The official sample script exists, and it's Python using only the standard library.

Pricing info: there's no public pricing page. The docs mention a "workflows plan feature". Let me quickly check the cost page / ROI calculator and the docs releases to see if there's any mention of pricing. Also going to check docs/workflows.md and the integrations pricing. Let me grep for "plan" / "pricing" / "cost" in the docs Markdown.

cd /tmp && for p in docs docs/releases docs/workflows docs/workflows/integrations docs/workflows/operations docs/api-reference; do timeout 20 curl -sSL "https://genhealth.ai/$p.md"; done > gh_all_docs.md 2>/dev/null; wc -l gh_all_docs.md; grep -n -i -E "pricing|price|cost|billing|plan feature|plans|free tier|credit" gh_all_docs.md | head -40
11700 gh_all_docs.md
11700 gh_all_docs.md
611:### [Push Authorization To Billing System](https://genhealth.ai/docs/workflows/integrations/authorizations/authorization_push_to_billing_system.md)
613:- Handler: `authorization_push_to_billing_system`
619:Perform Push Authorization To Billing System through Authorizations.
631:- Outputs: `success`, `skipped`, `coverage_id`, `status_code`, `status`, `has_active_coverage`, `has_coverage_determination`, `requested_procedure_codes`, `submitted_procedure_codes`, `procedure_code_support`, `procedure_code_support_detail`, `subscriber`, `patient`, `payer`, `requesting_provider`, `plans`, `raw_response`, `customer_message`, `payer_rejection_reason`, `payer_rejection_category`, `is_coverage_data_issue`, `error`, `error_message`
903:### [Update Patient Billing Info](https://genhealth.ai/docs/workflows/integrations/bonafide/bonafide_update_patient_billing_info.md)
905:- Handler: `bonafide_update_patient_billing_info`
911:Perform Update Patient Billing Info through Bonafide.
992:- Inputs: `sales_order_key`, `proc_code`, `quantity`, `billing_quantity`, `dry_run`
1046:### [Backfill Order Cost Evidence](https://genhealth.ai/docs/workflows/integrations/brightree/brightree_backfill_order_cost_evidence.md)
1048:- Handler: `brightree_backfill_order_cost_evidence`
1052:- Outputs: `success`, `date_from`, `date_to`, `window_exhausted`, `days_completed`, `orders_seen`, `orders_processed`, `orders_skipped_observed`, `inserted`, `updated`, `valid_costs`, `missing_costs`, `invalid_costs`, `nonpositive_costs`, `order_errors`, `error`
1054:Perform Backfill Order Cost Evidence through Brightree.
1225:### [Copy Billing Address to Insured](https://genhealth.ai/docs/workflows/integrations/brightree/brightree_copy_billing_address_to_insured.md)
1227:- Handler: `brightree_copy_billing_address_to_insured`
1233:Perform Copy Billing Address to Insured through Brightree.
1525:- Outputs: `success`, `date_from`, `date_to`, `line_count`, `paid_line_count`, `unpaid_line_count`, `revenue`, `cost`, `gp_dollars`, `gp_pct`, `negative_pct`, `below_15_pct`, `below_30_pct`, `by_payer`, `by_hcpcs`, `sku_opportunities`, `error`
1585:- Outputs: `success`, `dry_run`, `orders_scanned`, `orders_evaluated`, `flagged`, `wip_moved`, `skipped_unpriced`, `skipped_no_estimates`, `skipped_partial_estimates`, `skipped_already_flagged`, `skipped_recently_evaluated`, `skipped_wrong_wip`, `skipped_wip_unreadable`, `order_errors`, `error`
1605:- Outputs: `success`, `period_start`, `period_end`, `line_count`, `paid_line_count`, `unpaid_line_count`, `revenue`, `cost`, `gp_dollars`, `gp_pct`, `has_prior_period`, `prior_gp_pct`, `gp_pct_change`, `comparable_to_prior`, `snapshot_id`, `snapshot_persisted`, `html_body`, `subject`, `error`
1808:### [Resolve Client Sheet Costs](https://genhealth.ai/docs/workflows/integrations/brightree/brightree_resolve_client_sheet_costs.md)
1810:- Handler: `brightree_resolve_client_sheet_costs`
1814:- Outputs: `success`, `catalog_entries`, `rows_scanned`, `cost_written`, `matched_item`, `matched_hcpcs`, `no_catalog_match`, `quantity_unparsed`, `uncosted_remaining`, `error`
1816:Perform Resolve Client Sheet Costs through Brightree.
1828:### [Resolve Historical Order Costs](https://genhealth.ai/docs/workflows/integrations/brightree/brightree_resolve_historical_order_costs.md)
1830:- Handler: `brightree_resolve_historical_order_costs`
1834:- Outputs: `success`, `candidates_selected`, `candidates_remaining`, `cost_written`, `no_received_po`, `no_usable_810`, `shared_po_skipped`, `order_errors`, `shared_purchase_orders`, `error`
1836:Perform Resolve Historical Order Costs through Brightree.
2026:### [Set Patient Delivery Address Same As Billing](https://genhealth.ai/docs/workflows/integrations/brightree/brightree_set_patient_delivery_address_same_as_billing.md)
2028:- Handler: `brightree_set_patient_delivery_address_same_as_billing`
2034:Perform Set Patient Delivery Address Same As Billing through Brightree.
2299:### [Validate Patient Billing Address](https://genhealth.ai/docs/workflows/integrations/brightree/brightree_validate_patient_billing_address.md)
2301:- Handler: `brightree_validate_patient_billing_address`
2307:Perform Validate Patient Billing Address through Brightree.
2314:- Inputs: `patient_id`, `patient_state`, `patient_key`, `patient_context`, `facility_payload`, `facility_set_payload`, `marketing_referral_payload`, `billing_address_payload`, `delivery_address_payload`, `dropdown_payload`, `responsible_party_payload`, `primary_doctor_payload`, `tax_zone_payload`, `account_group`, `account_key`, `set_dropdowns`, `dry_run`
2612:- Outputs: `success`, `status`, `is_eligible`, `is_capitated`, `has_non_covered_benefit`, `payer_cannot_process`, `managed_care_organizations`, `plan_assignments`, `contracted_service_providers`, `plan_name`, `plan_number`, `group_name`, `group_number`, `coverage_start`, `coverage_end`, `payer_names`, `payer_program_identifier`, `related_entities`, `other_insurance`, `has_other_insurance`, `coverage_codes`, `coverage_descriptions`, `service_type_codes`, `service_type_descriptions`, `insurance_plans`, `insurance_type_codes`, `insurance_type_descriptions`, `active_insurance_plans`, `active_insurance_type_codes`, `active_insurance_type_descriptions`, `network_statuses`, `network_status_descriptions`, `benefit_coverage_windows`, `plan_coverage_windows`, `plan_begin_date`, `plan_end_date`, `eligibility_begin_date`, `eligibility_end_date`, `benefit_count`, `relevant_benefit_count`, `eligibility_id`, `result_date`, `document_id`, `pdf_path`, `pdf_error`, `payer_errors`, `retryable`, `error`, `skipped`, `skip_reason`
2695:- Inputs: `patient_data`, `billing_location_ids`, `order_params`
2895:- Inputs: `report`, `selected_ids`, `billing_location_ids`, `begin_date`, `end_date`, `date_basis`, `statuses`, `detail_level`, `include_claim_comments`, `include_no_payer`, `ignore_location_sorting`, `timely_filing_min`, `timely_filing_max`, `max_rows`, `skip_rows`, `poll_interval_seconds`, `timeout_seconds`
2905:- Inputs: `begin_date`, `end_date`, `billing_location_ids`, `order_statuses`, `search_text`, `search_fields`, `no_alerts`, `show_deleted`, `max_rows`
2975:- Inputs: `policy_data`, `patient_state`, `billing_location`, `payer_code_source`, `claimmd_discovery_reason`, `payer_plan`, `payer_card_state`, `payer_name_truncated`, `card_insurance_type`, `member_number`, `document_id`, `reviewed_payer_id`, `reviewed_payer_confirmed`
2995:- Inputs: `npi`, `name`, `billing_location_id`
3025:- Inputs: `patient_data`, `billing_location_ids`, `patient_id`, `patient_defaults`, `demographics_override`
cd /tmp && timeout 25 curl -sSL https://genhealth.ai/roi-calculator -o gh_roi.html; python3 - <<'EOF'
import re,html
s=open('gh_roi.html',encoding='utf-8',errors='ignore').read()
s=re.sub(r'<(script|style).*?</\1>','',s,flags=re.S)
t=html.unescape(re.sub(r'<[^>]+>','\n',s)); t=re.sub(r'\n\s*\n+','\n',t)
print(t[:2500])
EOF
ROI Calculator — GenHealth.ai

ROI Calculator — GenHealth.ai
GenHealth.ai
Book Demo
Company
Products
Who We Serve
Free tool
Calculate your 
DME automation
 ROI.
Enter your organization's numbers and see an instant ROI breakdown — labor savings, denial reduction, and full ROI analysis. Print or save as a PDF when you're ready.
Your operation
Enter your organization's information below to generate a detailed ROI report.
Company information
Name
Company
Email address
Title
DME focus area(s)
Respiratory
Sleep Therapy
Diabetes Management (CGM & Pumps)
Mobility
Hospital Beds & Support Surfaces
Orthotics
Enteral Nutrition
Compression Therapy
Other
Current operations
Monthly incoming orders
EMR
Select your EMR…
Brightree
Niko Health
Bonafide
Nymbl
Other
Avg order value ($)
Gross margin (%)
Staff cost ($/hr)
Denial rate (%)
Conversion rate (%)
Mins / order
See my ROI
Your report appears instantly on this page. You can print or save it as a PDF.
What you get
A full 
ROI breakdown
 for your operation.
An instant analysis you can print or save as a PDF directly from this page.
01
Annual Labor Savings
See exactly how much you save in labor cost by automating repetitive manual tasks with AI.
02
Denial Reduction Impact
Calculate the revenue recovered by reducing claim denials through better documentation and compliance.
03
Revenue Growth Potential
Understand additional revenue from improved conversion rates and operational efficiency.
04
Time-to-Value Analysis
View your payback period and when you start seeing positive returns.
05
Total ROI Percentage
Your complete return on investment calculation showing overall financial impact.
06
Net Annual Benefit
Your total annual benefit after accounting for GenHealth.ai subscription costs.
Chat with Genie
Get in touch
Find a time to interview GenHealth or Contact us to learn more.
Book demo
Email us instead
Loading available demo times
M
T
W
T
F
Sign Up
Try GenHealth free.
Spin up a free account and run real PA, intake, and eligibility flows in your sandbox.
Automate intake, eligibility, and PA
with AI agents that work in your EMR and billing systems.
Drop-in agents for PA, intake, eligibility
Free sandbox — no credit card
Connects to your EMR & billing
Create a free account
GenHealth.ai
Generative AI for healthcare operations
—
intake, eligibility, prior auth,
billing and more.
For Enterprise
Trust Center
Status Dashboard
AICPA SOC 2
HIPAA
Copyright © 2026 GenHealth.ai
Workflows
All Workflows
Intake
Prior Authorization
Eligibility
Resupplies
Stock & Bill
Med
Thinking…

Good. Pricing model: not publicly disclosed — sales-led enterprise subscription. The ROI calculator mentions "GenHealth.ai subscription costs," and there's also a free sandbox account with no credit card required. The docs mention a "workflows plan feature" (plan-gated), and per-operation scopes as well.

Alright, let's build the sample. Constraints: lightweight, use the hosted API, don't use local stacks. I can't get an API key myself (signup requires an interactive account) → I'll be blocked from actually running against the live API. But the following is possible:

  1. Download the official samples into the repo (or write my own minimal client).
  2. Write a small sample script that loads GENHEALTH_API_KEY, plus a README that documents the pricing model.
  3. Verify what's possible without a key: confirm the endpoint returns 401 (done), and run the sample client in a way that fails gracefully with a clear message.

Let me look at the official workflow_agent.py to make sure I understand it, and check the validate endpoint — validate probably also requires auth. Yes, everything requires auth.

Plan: create the following in /sandbox/repo:

  • README.md — quickstart, pricing notes, "how to manage"
  • genhealth_example/quickstart.py — a minimal client using only the standard library: capabilities → workflow validation → import → draft → publish → execute → inspect. Reuse ideas from the official script while keeping my own simple version. Alternatively, vendor the official workflow_agent.py and add a thin wrapper. The simpler route: write my own ~150-line script.
  • examples/agent-smoke-test.json (downloaded).

Also check whether GENHEALTH_API_KEY exists — it doesn't. So the script should exit with a clear message. Verify that the script runs and shows the blocked-state message, and additionally test against the live API without a key to demonstrate 401 handling (a safe GET). Actually, running validate without a key will return 401 → the script displays a message. That's enough as a demo of the blocked state.

Let me read the official script to keep things consistent and avoid duplicating errors.

read /tmp/ghx/workflow_agent.py{"content":[{"text":"#!/usr/bin/env python3\n\"\"\"GenHealth synthetic workflow quickstart. Python 3; no third-party packages.\n\nvalidate DEFINITION: preflight…ctrl+o
{"content":[{"text":"#!/usr/bin/env python3\n\"\"\"GenHealth synthetic workflow quickstart. Python 3; no third-party packages.\n\nvalidate DEFINITION: preflight only. execute DEFINITION: publish one synthetic run.\ninspect: observe the run in --state. No external integration actions are executed.\nRun state contains no key and must be retained to resume after an interruption.\nUse one process per state file. Review this client before running it.\n\"\"\"\n\nimport argparse\nimport hashlib\nimport json\nimport os\nfrom pathlib import Path\nimport sys\nfrom urllib.error import HTTPError, URLError\nfrom urllib.parse import urlencode, urlsplit\nfrom urllib.request import HTTPRedirectHandler, Request, build_opener\nfrom uuid import UUID, uuid4\n\n\nclass ApiError(RuntimeError):\n    \"\"\"A bounded diagnostic that does not echo response bodies or credentials.\"\"\"\n\n\nclass NoRedirect(HTTPRedirectHandler):\n    def redirect_request(self, req, fp, code, msg, headers, newurl):\n        raise ApiError(\"API redirects are refused; verify GENHEALTH_API_BASE.\")\n\n\nclass Client:\n    def __init__(self, base_url, api_key):\n        parsed = urlsplit(base_url)\n        local_http = parsed.scheme == \"http\" and parsed.hostname in {\"localhost\", \"127.0.0.1\", \"::1\"}\n        if (parsed.scheme != \"https\" and not local_http) or not parsed.hostname:\n            raise ApiError(\"Use an HTTPS API origin, or HTTP localhost for an isolated local server.\")\n        if parsed.username or parsed.password or parsed.query or parsed.fragment or parsed.path not in {\"\", \"/\"}:\n            raise ApiError(\"GENHEALTH_API_BASE must be an origin without credentials, path, query, or fragment.\")\n        if not api_key:\n            raise ApiError(\"Set GENHEALTH_API_KEY to an organization-bound key.\")\n        self.base_url = base_url.rstrip(\"/\")\n        self.api_key = api_key\n        self.opener = build_opener(NoRedirect())\n\n    def request(self, method, path, body=None):\n        request = Request(\n            self.base_url + \"/developer/v1\" + path,\n            data=json.dumps(body).encode() if body is not None else None,\n            headers={\"Authorization\": \"Bearer \" + self.api_key, \"Content-Type\": \"application/json\", \"Accept\": \"application/json\"},\n            method=method,\n        )\n        try:\n            with self.opener.open(request, timeout=30) as response:\n                return json.load(response)\n        except HTTPError as error:\n            raise ApiError(\"HTTP %s: consult /docs/workflows/operations; no automatic write retry was attempted.\" % error.code) from None\n        except (URLError, TimeoutError, OSError):\n            raise ApiError(\"Transport outcome unknown. Retain the state file and resume using the documented recovery procedure.\") from None\n\n\ndef save_state(path, state):\n    temporary = path.with_suffix(path.suffix + \".tmp\")\n    # Owner-only permissions from creation; state is synthetic but operationally sensitive.\n    descriptor = os.open(temporary, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o600)\n    with os.fdopen(descriptor, \"w\") as stream:\n        json.dump(state, stream, indent=2)\n    temporary.replace(path)\n\n\ndef preflight(client, definition):\n    result = client.request(\"POST\", \"/workflows/validate\", {\"definition\": definition})\n    if result.get(\"viable\") is not True or result.get(\"readiness\") != \"ready\":\n        raise ApiError(\"Preflight is blocked or needs review. Inspect validation findings through the authenticated API before publishing.\")\n    return result\n\n\ndef execute(client, definition, path):\n    # This executable example is a smoke test, not an arbitrary production runner.\n    nodes = definition.get(\"workflow\", {}).get(\"nodes\", [])\n    if not nodes or any(node.get(\"type\") not in {\"comment\", \"if\"} for node in nodes):\n        raise ApiError(\"This client executes synthetic comment/if graphs only. Use the documented API lifecycle for integrations.\")\n    fingerprint = hashlib.sha256(json.dumps(definition, sort_keys=True).encode()).hexdigest()\n    state = json.loads(path.read_text()) if path.exists() else {\"stage\": \"new\", \"base_url\": client.base_url, \"definition_sha256\": fingerprint}\n    if state.get(\"base_url\") != client.base_url or state.get(\"definition_sha256\") != fingerprint:\n        raise ApiError(\"State belongs to a different API origin or definition; do not reuse it.\")\n    preflight(client, definition)\n    if state[\"stage\"] == \"import_pending\":\n        raise ApiError(\"Import outcome unknown. List workflows and verify the candidate with GET /workflows/{id}/export. After confirming its graph matches this definition, set workflow_id and stage=imported in the state file, then resume. Do not repeat import with a new state file.\")\n    if state[\"stage\"] == \"new\":\n        state[\"stage\"] = \"import_pending\"\n        save_state(path, state)\n        imported = client.request(\"POST\", \"/workflows/import\", definition)\n        state.update(workflow_id=str(UUID(imported[\"workflow\"][\"id\"])), stage=\"imported\")\n        save_state(path, state)\n    workflow_path = \"/workflows/\" + str(UUID(state[\"workflow_id\"]))\n    if state[\"stage\"] == \"draft_pending\":\n        current = client.request(\"GET\", workflow_path)\n        if not current.get(\"has_draft\"):\n            raise ApiError(\"Draft outcome unknown; inspect workflow versions before retrying a write.\")\n        state[\"stage\"] = \"drafted\"\n        save_state(path, state)\n    if state[\"stage\"] == \"imported\":\n        state[\"stage\"] = \"draft_pending\"\n        save_state(path, state)\n        client.request(\"POST\", workflow_path + \"/draft\")\n        state[\"stage\"] = \"drafted\"\n        save_state(path, state)\n    if state[\"stage\"] == \"publish_pending\":\n        current = client.request(\"GET\", workflow_path)\n        if current.get(\"status\") != \"active\" or current.get(\"has_draft\"):\n            raise ApiError(\"Publication outcome unknown; inspect workflow versions before retrying a write.\")\n        state[\"stage\"] = \"published\"\n        save_state(path, state)\n    if state[\"stage\"] == \"drafted\":\n        state[\"stage\"] = \"publish_pending\"\n        save_state(path, state)\n        client.request(\"POST\", workflow_path + \"/publish\", {})\n        state[\"stage\"] = \"published\"\n        save_state(path, state)\n    if state[\"stage\"] == \"published\":\n        current = client.request(\"GET\", workflow_path)\n        state.update(stage=\"run_pending\", version_id=current[\"active_version_id\"], run_request={\"idempotency_key\": str(uuid4()), \"trigger_data\": {\"ready\": True}})\n        save_state(path, state)\n    if state[\"stage\"] == \"run_pending\":\n        current = client.request(\"GET\", workflow_path)\n        if current.get(\"active_version_id\") != state[\"version_id\"]:\n            raise ApiError(\"Active version changed. Reconcile the pending run; do not change its idempotency key.\")\n        run = client.request(\"POST\", workflow_path + \"/runs\", state[\"run_request\"])\n        state.update(stage=\"accepted\", run_id=str(UUID(run[\"run_id\"])))\n        save_state(path, state)\n    if state[\"stage\"] != \"accepted\":\n        raise ApiError(\"Unknown state stage; inspect the state file before another write.\")\n    return state\n\n\ndef inspect(client, state):\n    if state.get(\"base_url\") != client.base_url or not state.get(\"run_id\"):\n        raise ApiError(\"No accepted run for this API origin. Resume execute first.\")\n    workflow_id, run_id = str(UUID(state[\"workflow_id\"])), str(UUID(state[\"run_id\"]))\n    result = client.request(\"GET\", \"/workflows/\" + workflow_id + \"/runs?\" + urlencode({\"limit\": 25}))\n    run = next((item for item in result.get(\"runs\", []) if item.get(\"run_id\") == run_id), None)\n    if run is None:\n        raise ApiError(\"Run not in the returned page. Use since/until/status filters in the API; do not submit another run.\")\n    print(json.dumps({\"workflow_id\": workflow_id, \"run_id\": run_id, \"status\": run.get(\"status\")}, indent=2))\n    if run.get(\"status\") in {\"failed\", \"cancelled\"}:\n        raise ApiError(\"Run ended without completion; inspect node shapes in the authenticated API.\")\n\n\ndef main():\n    parser = argparse.ArgumentParser(description=__doc__)\n    parser.add_argument(\"command\", choices=[\"validate\", \"execute\", \"inspect\"])\n    parser.add_argument(\"definition\", nargs=\"?\")\n    parser.add_argument(\"--state\", type=Path, default=Path(\"agent-smoke-state.json\"))\n    args = parser.parse_args()\n    client = Client(os.environ.get(\"GENHEALTH_API_BASE\", \"https://api.umpa.genhealth.ai\"), os.environ.get(\"GENHEALTH_API_KEY\"))\n    if args.command == \"inspect\":\n        inspect(client, json.loads(args.state.read_text()))\n        return\n    if not args.definition:\n        parser.error(\"validate and execute require a definition file\")\n    definition = json.loads(Path(args.definition).read_text())\n    if args.command == \"validate\":\n        preflight(client, definition)\n        print(\"Preflight ready; no workflow was created.\")\n    else:\n        state = execute(client, definition, args.state)\n        print(json.dumps({\"workflow_id\": state[\"workflow_id\"], \"run_id\": state[\"run_id\"], \"status\": \"accepted; inspect for completion\"}, indent=2))\n\n\nif __name__ == \"__main__\":\n    try:\n        main()\n    except (ApiError, OSError, ValueError, KeyError, TypeError) as error:\n        # JSON/OS diagnostics can contain file contents or paths; only ApiError is curated.\n        print(str(error) if isinstance(error, ApiError) else \"Invalid local state, definition, or API response; inspect it locally before continuing.\", file=sys.stderr)\n        sys.exit(1)\n","type":"text"}]}
cd /tmp && timeout 20 curl -sSL "https://genhealth.ai/docs/workflows.md" | head -120
# GenHealth Workflow Developer API
# GenHealth Workflow Developer API

> Create, version, audit, publish, run, and maintain UMPA workflows directly against the core ETL API. The capability and action-discovery operations are optimized for AI agents.

Source: [https://genhealth.ai/docs/workflows](https://genhealth.ai/docs/workflows)

> **Workflow API access**
>
> Use a GenHealth API key with the workflow scope required by each operation. Copy the request examples to call the API from your server; interactive requests are not enabled in this reference.

## Build workflow automations

Discover supported integrations and actions, validate canonical workflow JSON, manage drafts and immutable versions, inspect graphs, publish viable workflows, and operate organization-scoped workflow runs.

- [Provider workflows across specialties](https://genhealth.ai/docs/workflows/provider-workflows.md): Scope referral intake, clearance, authorization, and recurring care using the right system contracts.
- [Build and run your first workflow](https://genhealth.ai/docs/workflows/agent-quickstart.md): Use REST or MCP, validate a synthetic graph, publish it, and inspect an idempotent run.
- [Discover capabilities](https://genhealth.ai/docs/workflows/api-reference/v1/workflow-developer-api/get-workflow-capabilities.md): Inspect controls, node types, expressions, integrations, and action schemas.
- [Find workflow functions](https://genhealth.ai/docs/workflows/integrations.md): Search the actions available for use in a workflow definition.
- [Create workflows](https://genhealth.ai/docs/workflows/api-reference/v1/workflow-developer-api/create-developer-workflow.md): Create organization-scoped workflow records and validate their JSON first.
- [Publish and run](https://genhealth.ai/docs/workflows/api-reference/v1/workflow-developer-api/run-developer-workflow.md): Publish immutable versions and start idempotent workflow runs.

## Workflow runs, integrations, and events

These terms describe what starts a workflow, how it works with other systems, and how its step attempts are modeled.

### Workflow run

One run begins each time a workflow is triggered—by a person, schedule, API request, file upload, or webhook—and ends when it completes, fails, or is canceled. Branches, waits, loops, and step retries remain part of that run; a child workflow starts a separate run.

### Integration

An integration connects a workflow to another system or exposes a GenHealth capability. It provides actions—tools such as finding a record, extracting data, or sending an update—that can be used as workflow steps. Some integrations require a configured connection or credentials.

[Browse available integrations and actions](https://genhealth.ai/docs/workflows/integrations.md)

### Modeled internal event

A planning unit for work performed inside a run. In the historical benchmark, each event represents one successful or failed attempt to execute a workflow step, after replay duplicates are removed. Loops and retries can add events; an event does not map one-to-one to a visible block, tool call, or external request.

## Contract summary

| Property | Value |
| --- | --- |
| OpenAPI | 3.1.0 |
| API version | 1.0.0 |
| Operations | 37 |
| Component schemas | 62 |
| Authentication | HTTP bearer token with operation-specific workflow scopes |

## Organization isolation

Workflow definitions, versions, graphs, webhook endpoints, and runs are resolved within the organization carried by the authenticated credential. An identifier from another organization does not grant access.

## Operations

- [Search Workflow Actions](https://genhealth.ai/docs/workflows/api-reference/v1/workflow-developer-api/search-workflow-actions.md): `GET /developer/v1/actions` — Search tenant-permitted platform actions; connection setup is reported separately.
- [Get Workflow Action](https://genhealth.ai/docs/workflows/api-reference/v1/workflow-developer-api/get-workflow-action.md): `GET /developer/v1/actions/{handler}` — Return the complete first-pass schema for one exact public action handler.
- [List Workflow Action Field Options](https://genhealth.ai/docs/workflows/api-reference/v1/workflow-developer-api/list-workflow-action-field-options.md): `GET /developer/v1/actions/{handler}/fields/{field}/options` — Resolve dynamic choices for one action field without exposing credentials.
- [Get Workflow Capabilities](https://genhealth.ai/docs/workflows/api-reference/v1/workflow-developer-api/get-workflow-capabilities.md): `GET /developer/v1/capabilities` — Return the established strict V1 workflow capability manifest.
- [Get Workflow Capabilities V2](https://genhealth.ai/docs/workflows/api-reference/v1/workflow-developer-api/get-workflow-capabilities-v2.md): `GET /developer/v1/capabilities/v2` — Describe graph controls plus the public webhook lifecycle contract.
- [List Workflow Integration Connections](https://genhealth.ai/docs/workflows/api-reference/v1/workflow-developer-api/list-workflow-integration-connections.md): `GET /developer/v1/integration-connections` — Report whether each public integration has credentials, without exposing them.
- [List Workflow Integrations](https://genhealth.ai/docs/workflows/api-reference/v1/workflow-developer-api/list-workflow-integrations.md): `GET /developer/v1/integrations` — List tenant-permitted public integrations; this does not assert connection setup.
- [Cancel Developer Workflow Run](https://genhealth.ai/docs/workflows/api-reference/v1/workflow-developer-api/cancel-developer-workflow-run.md): `POST /developer/v1/runs/{run_id}/cancel` — Request cancellation of one organization-owned public-compatible workflow run.
- [List Developer Workflows](https://genhealth.ai/docs/workflows/api-reference/v1/workflow-developer-api/list-developer-workflows.md): `GET /developer/v1/workflows` — List the same organization-scoped workflows shown in UMPA.
- [Create Developer Workflow](https://genhealth.ai/docs/workflows/api-reference/v1/workflow-developer-api/create-developer-workflow.md): `POST /developer/v1/workflows` — Create a workflow directly in the core ETL store used by UMPA.
- [Import Developer Workflow](https://genhealth.ai/docs/workflows/api-reference/v1/workflow-developer-api/import-developer-workflow.md): `POST /developer/v1/workflows/import` — Import canonical JSON as an inactive UMPA workflow with published version 1.
- [Validate Workflow Definition](https://genhealth.ai/docs/workflows/api-reference/v1/workflow-developer-api/validate-workflow-definition.md): `POST /developer/v1/workflows/validate` — Preflight canonical workflow JSON against save, audit, and public API rules. This operation does not persist anything. A definition that fails validation still returns HTTP 200 with ``viable=false`` and machine-actionable findings.
- [Delete Developer Workflow](https://genhealth.ai/docs/workflows/api-reference/v1/workflow-developer-api/delete-developer-workflow.md): `DELETE /developer/v1/workflows/{definition_id}` — Soft-delete a workflow after publish-scope authorization and explicit confirmation.
- [Get Developer Workflow](https://genhealth.ai/docs/workflows/api-reference/v1/workflow-developer-api/get-developer-workflow.md): `GET /developer/v1/workflows/{definition_id}` — Read an active, historical, or draft workflow definition by identifier.
- [Update Developer Workflow](https://genhealth.ai/docs/workflows/api-reference/v1/workflow-developer-api/update-developer-workflow.md): `PATCH /developer/v1/workflows/{definition_id}` — Update workflow metadata or an existing draft; published graphs are immutable.
- [Audit Workflow](https://genhealth.ai/docs/workflows/api-reference/v1/workflow-developer-api/audit-workflow.md): `POST /developer/v1/workflows/{definition_id}/audit` — Audit the unpublished draft and return actionable graph findings without mutation.
- [Discard Developer Workflow Draft](https://genhealth.ai/docs/workflows/api-reference/v1/workflow-developer-api/discard-developer-workflow-draft.md): `DELETE /developer/v1/workflows/{definition_id}/draft` — Discard the current unpublished draft while preserving published versions.
- [Create Developer Workflow Draft](https://genhealth.ai/docs/workflows/api-reference/v1/workflow-developer-api/create-developer-workflow-draft.md): `POST /developer/v1/workflows/{definition_id}/draft` — Create an editable draft from the workflow's currently active version.
- [Replace Developer Workflow Draft From Json](https://genhealth.ai/docs/workflows/api-reference/v1/workflow-developer-api/replace-developer-workflow-draft-from-json.md): `POST /developer/v1/workflows/{definition_id}/draft/from-json` — Replace the complete draft graph from canonical JSON without publishing it.
- [Export Developer Workflow](https://genhealth.ai/docs/workflows/api-reference/v1/workflow-developer-api/export-developer-workflow.md): `GET /developer/v1/workflows/{definition_id}/export` — Export canonical workflow JSON suitable for validation or exact re-import.
- [Get Workflow Graph](https://genhealth.ai/docs/workflows/api-reference/v1/workflow-developer-api/read-workflow-graph.md): `GET /developer/v1/workflows/{definition_id}/graph` — Read the complete public-safe graph for a workflow's current target version.
- [Replace Workflow Graph](https://genhealth.ai/docs/workflows/api-reference/v1/workflow-developer-api/replace-workflow-graph.md): `PUT /developer/v1/workflows/{definition_id}/graph` — Replace the entire editable draft graph after public policy validation.
- [Insert Workflow Node After](https://genhealth.ai/docs/workflows/api-reference/v1/workflow-developer-api/insert-workflow-node-after.md): `POST /developer/v1/workflows/{definition_id}/nodes/after` — Insert one node after an existing draft node and optionally rewire its targets.
- [Insert Workflow Node Before](https://genhealth.ai/docs/workflows/api-reference/v1/workflow-developer-api/insert-workflow-node-before.md): `POST /developer/v1/workflows/{definition_id}/nodes/before` — Insert one node before an existing draft node and optionally rewire its sources.
- [Delete Workflow Node](https://genhealth.ai/docs/workflows/api-reference/v1/workflow-developer-api/delete-workflow-node.md): `DELETE /developer/v1/workflows/{definition_id}/nodes/{node_id}` — Delete one draft node and optionally reconnect its incoming and outgoing edges.
- [Get Workflow Node Details](https://genhealth.ai/docs/workflows/api-reference/v1/workflow-developer-api/read-workflow-node-details.md): `GET /developer/v1/workflows/{definition_id}/nodes/{node_id}` — Read one node's configuration, connections, and public action metadata.
- [Update Workflow Node](https://genhealth.ai/docs/workflows/api-reference/v1/workflow-developer-api/update-workflow-node.md): `PATCH /developer/v1/workflows/{definition_id}/nodes/{node_id}` — Patch selected fields on one node in the editable draft graph.
- [Get Workflow Node Context](https://genhealth.ai/docs/workflows/api-reference/v1/workflow-developer-api/read-workflow-node-context.md): `GET /developer/v1/workflows/{definition_id}/nodes/{node_id}/context` — Read one node with its immediate upstream and downstream graph context.
- [Get Workflow Outline](https://genhealth.ai/docs/workflows/api-reference/v1/workflow-developer-api/read-workflow-outline.md): `GET /developer/v1/workflows/{definition_id}/outline` — Read a compact node-and-edge outline before requesting larger graph details.
- [Publish Developer Workflow](https://genhealth.ai/docs/workflows/api-reference/v1/workflow-developer-api/publish-developer-workflow.md): `POST /developer/v1/workflows/{definition_id}/publish` — Audit and publish the current draft as an immutable active version. Inherits the same confirm_removed_nodes / 409 removed_nodes_require_confirmation contract as the interactive publish route (see publish_draft); confirmation retries must echo the returned removed_nodes_confirmation.
- [List Workflow Runs Safe](https://genhealth.ai/docs/workflows/api-reference/v1/workflow-developer-api/list-workflow-runs-safe.md): `GET /developer/v1/workflows/{definition_id}/runs` — Return run navigation metadata without trigger or node-result values.
- [Run Developer Workflow](https://genhealth.ai/docs/workflows/api-reference/v1/workflow-developer-api/run-developer-workflow.md): `POST /developer/v1/workflows/{definition_id}/runs` — Start an active published workflow with idempotent retry semantics.
- [Read Workflow Run Node Shape](https://genhealth.ai/docs/workflows/api-reference/v1/workflow-developer-api/read-workflow-run-node-shape.md): `GET /developer/v1/workflows/{definition_id}/runs/{run_id}/nodes/{node_id}` — Return status and value-free output shapes for one executed node.
- [List Developer Workflow Versions](https://genhealth.ai/docs/workflows/api-reference/v1/workflow-developer-api/list-developer-workflow-versions.md): `GET /developer/v1/workflows/{definition_id}/versions` — List immutable published versions and draft metadata for one workflow.
- [Get Developer Workflow Version](https://genhealth.ai/docs/workflows/api-reference/v1/workflow-developer-api/get-developer-workflow-version.md): `GET /developer/v1/workflows/{definition_id}/versions/{version_id}` — Read one immutable workflow version without changing the active version.
- [Revert Developer Workflow Version](https://genhealth.ai/docs/workflows/api-reference/v1/workflow-developer-api/revert-developer-workflow-version.md): `POST /developer/v1/workflows/{definition_id}/versions/{version_id}/revert` — Create a new editable draft copied from a historical workflow version.
- [Get Developer Workflow Webhook Endpoint](https://genhealth.ai/docs/workflows/api-reference/v1/workflow-developer-api/get-developer-workflow-webhook-endpoint.md): `GET /developer/v1/workflows/{definition_id}/webhook-endpoint` — Return an active, published webhook URL; never exposed as an MCP tool.
Thinking…

Alright, let's build the repo example. Structure:

/sandbox/repo/ README.md — what this is, pricing overview, manageability notes, how to run it genhealth_quickstart.py — minimal standard-library-only client: doctor (connectivity/auth check), validate, run (the full lifecycle), inspect examples/synthetic-routing.workflow.json — synthetic graph (derived from the docs)

Keep the script simple while making it safe: no automatic retries on writes, maintain idempotency keys in the state file.

After that, run python3 genhealth_quickstart.py doctor to show the blocked state (no API key → clear message). Might also be able to demo the 401 path with a dummy key... Note: using a fake key against the live API will return 401 — harmless, and shows error handling works. That's fine, it's a single request. Let's do that to validate the script's error handling.

Also, validate the JSON locally without network.

Write the script.

GenHealth.ai is real and has a public developer portal. Let me build the example in the repo.

cat /tmp/ghx/agent-smoke-test.json
{
{
  "kind": "genhealth.workflow_definition",
  "schema_version": 1,
  "workflow": {
    "name": "Agent quickstart: synthetic routing",
    "description": "Synthetic execution check; no healthcare system reads or writes.",
    "nodes": [
      { "id": "received", "type": "comment", "name": "Synthetic request", "config": { "heading": "Start", "body": "Inputs are supplied in trigger_data." } },
      { "id": "route", "type": "if", "name": "Ready?", "config": { "condition": "{{trigger.default.ready}}" } },
      { "id": "ready", "type": "comment", "name": "Ready outcome", "config": { "heading": "Ready", "body": "The true branch ran." } },
      { "id": "review", "type": "comment", "name": "Review outcome", "config": { "heading": "Review", "body": "The false branch ran; no external review task was created." } }
    ],
    "edges": [
      { "source_node_id": "received", "source_output": "default", "target_node_id": "route", "target_input": "default" },
      { "source_node_id": "route", "source_output": "true", "target_node_id": "ready", "target_input": "default" },
      { "source_node_id": "route", "source_output": "false", "target_node_id": "review", "target_input": "default" }
    ]
  }
}
Thinking…

Please write the file.

mkdir -p /sandbox/repo/examples && cp /tmp/ghx/agent-smoke-test.json /sandbox/repo/examples/synthetic-routing.workflow.json && ls -R /sandbox/repo
/sandbox/repo:
/sandbox/repo:
examples

/sandbox/repo/examples:
synthetic-routing.workflow.json
Thinking…

Wait, ls -R didn't show .gitignore/.git (hidden files). Oh well.

Alright, let's write genhealth_quickstart.py.

File edits

1 file

Completed
Writtengenhealth_quickstart.pyView changes

/sandbox/repo/genhealth_quickstart.py

Written content · previous contents were not recorded

#!/usr/bin/env python3
"""Minimal GenHealth.ai developer example. Python 3 standard library only.
Talks to the hosted GenHealth Workflow Developer API:
REST base : https://api.umpa.genhealth.ai/developer/v1
Auth : Authorization: Bearer $GENHEALTH_API_KEY
Commands
doctor connectivity + auth + capability probe (read-only)
validate <definition.json> preflight a workflow definition (persists nothing)
run <definition.json> validate -> import -> draft -> publish -> 1 run
(resumable via --state; synthetic graphs only)
inspect show the run recorded in --state (no resubmit)
No local services, no docker, no third-party packages, no background processes.
Writes are never auto-retried: each mutating step records intent in the state
file first, so an interrupted run can be reconciled instead of duplicated.
"""
import argparse
import hashlib
import json
import os
import sys
from pathlib import Path
from urllib.error import HTTPError, URLError
from urllib.parse import urlencode
from urllib.request import Request, urlopen
from uuid import UUID, uuid4
DEFAULT_BASE = "https://api.umpa.genhealth.ai"
DEV_PREFIX = "/developer/v1"
TERMINAL = {"completed", "failed", "cancelled"}
# This example only executes graphs that cannot touch a healthcare system.
SYNTHETIC_NODE_TYPES = {"comment", "if"}
HINTS = {
401: "GENHEALTH_API_KEY missing/expired/invalid - check the bearer token.",
403: "Key lacks the scope or plan feature for this operation "
"(workflow:read/write/publish/run + workflows plan).",
404: "Resource not visible to the organization resolved from your key.",
409: "Publish conflict (e.g. removed nodes need explicit confirmation).",
422: "Request body rejected - inspect the error details and fix the payload.",
}
class ApiError(RuntimeError):
"""Bounded diagnostic; never echoes response bodies or credentials."""
class Client:
def __init__(self, base_url, api_key, timeout=30):
if not base_url.startswith("https://"):
raise ApiError("Refusing a non-HTTPS GENHEALTH_API_BASE: %s" % base_url)
if not api_key:
raise ApiError(
"GENHEALTH_API_KEY is not set. Get an organization-bound key:\n"
" 1. sign up at https://umpa.genhealth.ai/api/auth/login?screen_hint=signup\n"
" 2. create a key at https://genhealth.ai/account/api-keys\n"
" 3. export GENHEALTH_API_KEY=... (never commit it)"
)
self.base_url = base_url.rstrip("/")
self.api_key = api_key
self.timeout = timeout
def request(self, method, path, body=None):
request = Request(
self.base_url + DEV_PREFIX + path,
data=json.dumps(body).encode() if body is not None else None,
headers={
"Authorization": "Bearer " + self.api_key,
"Content-Type": "application/json",
"Accept": "application/json",
},
method=method,
)
try:
with urlopen(request, timeout=self.timeout) as response:
payload = response.read()
return json.loads(payload) if payload else {}
except HTTPError as error:
hint = HINTS.get(error.code, "See /docs/workflows/operations.")
raise ApiError(
"HTTP %s on %s %s -> %s (no automatic write retry attempted)"
% (error.code, method, path, hint)
) from None
except (URLError, TimeoutError, OSError) as error:
raise ApiError(
"Transport failure (%s). Outcome of any write is unknown: keep the "
"state file and reconcile before retrying." % error.__class__.__name__
) from None
def save_state(path, state):
"""Atomic, owner-only write so an interrupted step never leaves partial JSON."""
tmp = path.with_suffix(path.suffix + ".tmp")
fd = os.open(tmp, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o600)
with os.fdopen(fd, "w") as stream:
json.dump(state, stream, indent=2, sort_keys=True)
tmp.replace(path)
def load_definition(path):
definition = json.loads(Path(path).read_text())
nodes = definition.get("workflow", {}).get("nodes") or []
if not nodes:
raise ApiError("Definition has no nodes; refusing to submit it.")
unsafe = sorted({n.get("type") for n in nodes} - SYNTHETIC_NODE_TYPES)
if unsafe:
raise ApiError(
"This example runs synthetic comment/if graphs only; found %s. "
"Real integration actions need provisioned connections and a review "
"of /docs/workflows/action-contracts." % ", ".join(map(str, unsafe))
)
return definition
def doctor(client):
"""Read-only probe: proves origin, auth, scopes, and plan feature."""
caps = client.request("GET", "/capabilities/v2")
integrations = client.request("GET", "/integrations")
connections = client.request("GET", "/integration-connections")
workflows = client.request("GET", "/workflows?" + urlencode({"limit": 5}))
summary = {
"base_url": client.base_url,
"auth": "ok",
"capability_keys": sorted(caps)[:12],
"node_types": sorted(
(caps.get("node_types") or caps.get("nodes") or {})
if isinstance(caps.get("node_types") or caps.get("nodes"), dict)
else (caps.get("node_types") or [])
)[:20],
"integrations_visible": len(integrations.get("integrations", [])),
"connections_configured": sum(
1 for c in connections.get("integration_connections", []) if c.get("configured")
),
"workflows_visible": len(workflows.get("workflows", [])),
}
print(json.dumps(summary, indent=2))
print("doctor: OK - read-only calls succeeded; no workflow was created.")
def validate(client, definition):
"""HTTP 200 can still mean viable=false; check the findings, not the status."""
result = client.request("POST", "/workflows/validate", {"definition": definition})
viable, readiness = result.get("viable"), result.get("readiness")
print(json.dumps({
"viable": viable,
"readiness": readiness,
"schema_errors": result.get("schema_errors", []),
"findings": result.get("findings", []),
}, indent=2))
if viable is not True or readiness != "ready":
raise ApiError("Preflight is not ready; nothing was created. Fix the findings above.")
print("validate: preflight ready; no workflow was created.")
return result
def run(client, definition, state_path):
fingerprint = hashlib.sha256(json.dumps(definition, sort_keys=True).encode()).hexdigest()
state = json.loads(state_path.read_text()) if state_path.exists() else {
"stage": "new", "base_url": client.base_url, "definition_sha256": fingerprint,
}
if state.get("base_url") != client.base_url or state.get("definition_sha256") != fingerprint:
raise ApiError("State file belongs to another origin or definition; do not reuse it.")
def current():
return client.request("GET", "/workflows/" + str(UUID(state["workflow_id"])))
def path_of(suffix=""):
return "/workflows/" + str(UUID(state["workflow_id"])) + suffix
validate(client, definition)
if state["stage"] in {"import_pending", "draft_pending", "publish_pending", "run_pending"}:
raise ApiError(
"Stage %r means a previous write's outcome is unknown. Reconcile with "
"GET /workflows, /export and /versions, then set the confirmed stage in %s. "
"Do not re-import with a fresh state file." % (state["stage"], state_path)
)
if state["stage"] == "new":
state["stage"] = "import_pending"
save_state(state_path, state)
imported = client.request("POST", "/workflows/import", definition)
state.update(workflow_id=str(UUID(imported["workflow"]["id"])), stage="imported")
save_state(state_path, state)
print("imported workflow %s" % state["workflow_id"])
if state["stage"] == "imported":
state["stage"] = "draft_pending"
save_state(state_path, state)
client.request("POST", path_of("/draft"))
state["stage"] = "drafted"
save_state(state_path, state)
if state["stage"] == "drafted":
state["stage"] = "publish_pending"
save_state(state_path, state)
client.request("POST", path_of("/publish"), {})
state["stage"] = "published"
save_state(state_path, state)
if state["stage"] == "published":
workflow = current()
state.update(
stage="run_pending",
version_id=workflow["active_version_id"],
# Idempotency key is generated once and persisted: a retry must reuse it.
run_request={"idempotency_key": str(uuid4()), "trigger_data": {"ready": True}},
)
save_state(state_path, state)
if state["stage"] == "run_pending":
if current().get("active_version_id") != state["version_id"]:
raise ApiError("Active version changed under the pending run; reconcile before retrying.")
accepted = client.request("POST", path_of("/runs"), state["run_request"])
state.update(stage="accepted", run_id=str(UUID(accepted["run_id"])))
save_state(state_path, state)
if state["stage"] != "accepted":
raise ApiError("Unexpected stage %r in %s" % (state["stage"], state_path))
print(json.dumps({
"workflow_id": state["workflow_id"],
"run_id": state["run_id"],
"status": "accepted (202) - acceptance is not completion; run `inspect`",
}, indent=2))
def inspect(client, state):
if not state.get("run_id") or state.get("base_url") != client.base_url:
raise ApiError("No accepted run for this origin; run `run` first.")
workflow_id, run_id = str(UUID(state["workflow_id"])), str(UUID(state["run_id"]))
listing = client.request("GET", "/workflows/%s/runs?%s" % (workflow_id, urlencode({"limit": 25})))
found = next((r for r in listing.get("runs", []) if r.get("run_id") == run_id), None)
if found is None:
raise ApiError("Run not in the first page; filter by since/until/status. Do not resubmit.")
print(json.dumps({
"workflow_id": workflow_id,
"run_id": run_id,
"status": found.get("status"),
"terminal": found.get("status") in TERMINAL,
}, indent=2))
if found.get("status") in {"failed", "cancelled"}:
raise ApiError(
"Run ended without completing. Inspect node shapes with "
"GET /workflows/%s/runs/%s/nodes/{node_id} (statuses only, no values)."
% (workflow_id, run_id)
)
if found.get("status") == "completed":
for node_id in ("route", "ready", "review"):
shape = client.request(
"GET", "/workflows/%s/runs/%s/nodes/%s" % (workflow_id, run_id, node_id)
)
print(" node %-7s -> %s" % (node_id, shape.get("status", shape)))
def main():
parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument("command", choices=["doctor", "validate", "run", "inspect"])
parser.add_argument("definition", nargs="?", help="workflow definition JSON (validate/run)")
parser.add_argument("--state", type=Path, default=Path("genhealth-example-state.json"))
args = parser.parse_args()
client = Client(os.environ.get("GENHEALTH_API_BASE", DEFAULT_BASE), os.environ.get("GENHEALTH_API_KEY"))
if args.command == "doctor":
doctor(client)
elif args.command == "inspect":
inspect(client, json.loads(args.state.read_text()))
else:
if not args.definition:
parser.error("%s requires a definition file" % args.command)
definition = load_definition(args.definition)
if args.command == "validate":
validate(client, definition)
else:
run(client, definition, args.state)
if __name__ == "__main__":
try:
main()
except ApiError as error:
print("error: %s" % error, file=sys.stderr)
sys.exit(1)
except (OSError, ValueError, KeyError, TypeError) as error:
# Local file/JSON diagnostics can contain paths or contents; keep it generic.
print("error: invalid local state, definition, or API response (%s); inspect it locally."
% error.__class__.__name__, file=sys.stderr)
sys.exit(1)
Thinking…

Testing: doctor without a key (should display a message about being blocked), doctor with a fake key (401 handling), local behavior of the validate guard.

cd /sandbox/repo && chmod +x genhealth_quickstart.py && python3 -m py_compile genhealth_quickstart.py && echo "compiles OK"
echo "=== 1) no key ==="; python3 genhealth_quickstart.py doctor; echo "exit=$?"
echo "=== 2) bogus key (expect clean 401) ==="; GENHEALTH_API_KEY=dummy-key-not-real python3 genhealth_quickstart.py doctor; echo "exit=$?"
echo "=== 3) validate with bogus key ==="; GENHEALTH_API_KEY=dummy-key-not-real python3 genhealth_quickstart.py validate examples/synthetic-routing.workflow.json; echo "exit=$?"
echo "=== 4) local guard: non-synthetic graph ==="; echo '{"kind":"genhealth.workflow_definition","schema_version":1,"workflow":{"name":"x","nodes":[{"id":"a","type":"brightree_create_sales_order"}]}}' > /tmp/unsafe.json; GENHEALTH_API_KEY=dummy python3 genhealth_quickstart.py validate /tmp/unsafe.json; echo "exit=$?"
compiles OK
compiles OK
=== 1) no key ===
error: GENHEALTH_API_KEY is not set. Get an organization-bound key:
  1. sign up at https://umpa.genhealth.ai/api/auth/login?screen_hint=signup
  2. create a key at https://genhealth.ai/account/api-keys
  3. export GENHEALTH_API_KEY=...   (never commit it)
exit=1
=== 2) bogus key (expect clean 401) ===
error: HTTP 401 on GET /capabilities/v2 -> GENHEALTH_API_KEY missing/expired/invalid - check the bearer token. (no automatic write retry attempted)
exit=1
=== 3) validate with bogus key ===
error: HTTP 401 on POST /workflows/validate -> GENHEALTH_API_KEY missing/expired/invalid - check the bearer token. (no automatic write retry attempted)
exit=1
=== 4) local guard: non-synthetic graph ===
error: This example runs synthetic comment/if graphs only; found brightree_create_sales_order. Real integration actions need provisioned connections and a review of /docs/workflows/action-contracts.
exit=1
Thinking…

everything working. Confirmed the API host is up and enforcing auth (401/403), and the error handling has been verified.

Also, I'll confirm that the sample JSON is valid JSON, and that the graph is internally consistent (that the edges reference nodes). Furthermore, add a README.md that includes pricing info + maintainability. Should I add a .gitignore entry for state files? The existing .gitignore doesn't cover genhealth-example-state.json. Add it (since it might contain workflow/run IDs). Yeah, let's append it.

cd /sandbox/repo && python3 - <<'EOF'
import json
d=json.load(open('examples/synthetic-routing.workflow.json'))
ids={n['id'] for n in d['workflow']['nodes']}
bad=[e for e in d['workflow']['edges'] if e['source_node_id'] not in ids or e['target_node_id'] not in ids]
print("nodes:",sorted(ids),"| dangling edges:",bad,"| kind:",d['kind'],"| schema_version:",d['schema_version'])
EOF
printf '\n# GenHealth example run state (workflow/run ids; never commit secrets here either)\ngenhealth-example-state.json\n*-state.json\n' >> .gitignore && tail -5 .gitignore
nodes: ['ready', 'received', 'review', 'route'] | dangling edges: [] | kind: genhealth.workflow_definition | schema_version: 1
nodes: ['ready', 'received', 'review', 'route'] | dangling edges: [] | kind: genhealth.workflow_definition | schema_version: 1
.dart_tool/

# GenHealth example run state (workflow/run ids; never commit secrets here either)
genhealth-example-state.json
*-state.json
Thinking…

Note: Does *-state.json also match agent-smoke-state.json — that's fine, but does it also match examples/synthetic-routing.workflow.json? No (it doesn't end with -state.json). Good.

Next, the README: pricing overview + maintainability + usage instructions.

Facts regarding pricing (verified from the site):

  • /pricing is 404, and there is no published price list anywhere on genhealth.ai. Sales-led ("Book Demo", "For Enterprise", contact).
  • Free sandbox account: "Try GenHealth for free. Spin up a free account and run real PA, intake, and eligibility flows in the sandbox." / "Free sandbox — no credit card required."
  • The ROI calculator calculates the "annual net benefit after deducting GenHealth.ai subscription costs" → paid tiers exist as subscription plans, but prices are not disclosed.
  • Docs: the workflow developer API requires "the workflows plan feature" in addition to per-operation scopes (workflow:read/write/publish/run) → gated by plan. There is a mention of "Modeled internal events" — "a planning unit for work performed within a single run... in past benchmarks, each event represents one successful or failed attempt to execute a workflow step" → this is a unit of usage/metering, suggesting consumption-based metering, but the documentation does not explicitly state billing per event. This should be phrased cautiously: the docs define internal events as work units/benchmarks, but nowhere is pricing per event stated.

Maintainability for me (the agent): Easy points: the REST API has a live OpenAPI at /developer/openapi.json, an MCP transport at /developer/mcp (streamable HTTP), docs are viewable as markdown (.md suffix — agent-friendly), deterministic lifecycle endpoints, validate returns machine-actionable findings, a capabilities endpoint for discovery, idempotent execution, immutable published versions + drafts, per-node state inspection without exposing values. A Python client using only the standard library → no dependency management required. Hard points: obtaining credentials requires interactive signup + an org + provisioning of connections (Brightree/Bonafide, etc.) — impossible without a human; the workflows plan feature is gated; MCP tool discovery requires auth so I can't pre-check tools; write operations against real healthcare systems are high-risk and require human review; there is no publicly available local emulator, so every test needs credentials.

Write the README concisely.

File edits

1 file

Completed
WrittenREADME.mdView changes

/sandbox/repo/README.md

Written content · previous contents were not recorded

# GenHealth.ai quickstart example
A minimal, dependency-free example that talks to the **hosted** GenHealth Workflow
Developer API. No docker, no local service stack, no long-running processes — just
Python 3 standard library HTTP calls against `https://api.umpa.genhealth.ai`.
## What GenHealth.ai is
AI agents for healthcare revenue-cycle ops (intake, eligibility, prior authorization,
resupplies, billing, denials/appeals) that operate over web portals, fax, and phone.
The developer surface exposes that work as **workflows**: JSON graphs of nodes/edges,
versioned, published, and run through REST or MCP.
| Surface | URL |
| --- | --- |
| Docs (add `.md` for agent-friendly Markdown) | https://genhealth.ai/docs.md |
| REST base | `https://api.umpa.genhealth.ai/developer/v1` |
| Live OpenAPI 3.1 | `https://api.umpa.genhealth.ai/developer/openapi.json` |
| Swagger | `https://api.umpa.genhealth.ai/developer/docs` |
| MCP (streamable HTTP, same bearer header) | `https://api.umpa.genhealth.ai/developer/mcp` |
| Core resource API (cases/policies/codes) | `https://api.umpa.genhealth.ai/v2/...` |
## Files
- `genhealth_quickstart.py` — `doctor` / `validate` / `run` / `inspect` client (stdlib only).
- `examples/synthetic-routing.workflow.json` — the canonical synthetic graph from the docs.
It routes a boolean to one of two `comment` nodes. It creates **no** patient, order,
claim, or authorization and needs no integration credentials.
## Run it
```bash
# 1. Get an organization-bound API key (human step; see "Blocked on" below)
# sign up: https://umpa.genhealth.ai/api/auth/login?screen_hint=signup
# key page: https://genhealth.ai/account/api-keys
export GENHEALTH_API_KEY="<YOUR_API_KEY>"
# 2. Read-only probe: auth, scopes, visible integrations/connections
python3 genhealth_quickstart.py doctor
# 3. Preflight the graph (persists nothing; HTTP 200 can still mean viable=false)
python3 genhealth_quickstart.py validate examples/synthetic-routing.workflow.json
# 4. validate -> import -> draft -> publish -> one idempotent run
python3 genhealth_quickstart.py run examples/synthetic-routing.workflow.json \
--state genhealth-example-state.json
# 5. Poll the run (never resubmits) until it is terminal
python3 genhealth_quickstart.py inspect --state genhealth-example-state.json
```
Required scopes: `workflow:read` for discovery/preflight; `workflow:write`,
`workflow:publish`, `workflow:run` to create and execute. Your organization also
needs the **workflows plan feature** enabled.
Safety properties baked into the client:
- HTTPS-only origin; the API key never leaves the `Authorization` header or this machine.
- Synthetic `comment`/`if` graphs only — a definition containing any real integration
action (e.g. `brightree_*`) is rejected locally before any request is sent.
- Writes are never auto-retried. Each mutating step records intent in the state file
(`import_pending` → `imported` → …) so an interrupted run is reconciled, not duplicated.
- The run's `idempotency_key` is generated once and persisted; retries reuse it.
- State file is written atomically with `0600` permissions and is git-ignored.
## Blocked on (why this can't run end-to-end unattended)
`doctor` currently exits 1 with a credential hint. The API host is live and reachable
(verified: it returns `401 Requires authentication` / `403 Not authenticated` without a
key), but obtaining a key requires an interactive signup, a real organization, and the
workflows plan feature — an agent cannot self-provision that. With
`GENHEALTH_API_KEY` exported, steps 2–5 need no further human input.
## How pricing works
**There is no published price list.** `genhealth.ai/pricing` is a 404 and no page on the
site states a dollar figure. What the site and docs do establish:
- **Sales-led enterprise subscription.** Every conversion path is "Book a demo" /
"Contact us"; the footer says "For Enterprise". Expect a negotiated annual contract,
not self-serve checkout.
- **Free sandbox tier.** "Try GenHealth free — spin up a free account and run real PA,
intake, and eligibility flows in your sandbox. Free sandbox — no credit card." That is
the entry point this example targets.
- **Subscription is a real cost line.** GenHealth's own ROI calculator reports "Net
Annual Benefit — your total annual benefit *after accounting for GenHealth.ai
subscription costs*", i.e. you get the number from their sales/calculator, not a page.
- **Plan-gated capabilities.** The Workflow Developer API requires the "workflows plan
feature", so the developer surface itself is an entitlement above the base plan.
- **Usage is metered in "modeled internal events."** The docs define one event as a
successful or failed attempt to execute a workflow step (after replay-dedup), and note
loops/retries add events. The docs describe it as a *planning/benchmark* unit and never
publish a per-event rate — treat it as the likely metering dimension to ask sales about.
- **Scopes, not seats, gate the API.** Access is split per operation
(`workflow:read/write/publish/run`), so cost/permission review is per-integration.
Bottom line: free sandbox to build and test; production pricing is quote-only, and the
number you should negotiate against is events/runs plus the workflows plan entitlement.
## Is this easy for an agent to manage?
**Yes for the developer loop, no for provisioning.**
Easy:
- Live `openapi.json` + Swagger + an authenticated **MCP** transport mean I can discover
the contract instead of guessing it (37 operations, 62 schemas).
- Every docs page is available as plain Markdown by appending `.md` — trivially readable.
- `GET /capabilities/v2`, `GET /actions` (search), and `GET /actions/{handler}` give
exact node types, expression syntax, and action input/output schemas before authoring.
- `POST /workflows/validate` returns machine-actionable `schema_errors` / `findings` /
`readiness` and persists nothing — a safe, cheap preflight loop.
- Immutable published versions + explicit drafts + revert, idempotent runs, per-node
value-free status inspection, and org-scoped isolation make state reasoning tractable.
- Zero dependencies (stdlib `urllib`) means no lockfiles, builds, or version drift.
Hard / human-required:
- Credentials, the organization, the workflows plan feature, and integration connections
(Brightree, Bonafide, payer portals…) must be provisioned by a person.
- Real healthcare actions write to EMR/billing/payer systems; a completed orchestration
does not prove a business result, so recipes need explicit business-success branches
and human review before production.
- MCP tool discovery is itself authenticated, so I cannot pre-verify tool availability
without a key.
- No public local emulator: every integration-level test consumes sandbox entitlement.
Thinking…

Verify the README's descriptions: 37 operations, 62 schemas — from the contract summary in workflows.md. Yes. Also "37 operations" is correct.

Run the final check: doctor once more with no key, ls the repository. Also verify the openapi.json endpoint mentioned in the docs — check whether it's reachable (it probably returns 401). Quick check to avoid incorrect descriptions.

for p in /developer/openapi.json /developer/docs /developer/mcp; do echo -n "$p -> "; timeout 15 curl -sS -o /dev/null -w "%{http_code}\n" "https://api.umpa.genhealth.ai$p"; done; echo; cd /sandbox/repo && ls -la && git status --short
/developer/openapi.json -> 200
/developer/openapi.json -> 200
/developer/docs -> 200
/developer/mcp -> 405

total 48
drwxr-xr-x 5 root root  4096 Oct 22 17:21 .
drwxr-xr-x 7 root root  4096 Oct 22 17:19 ..
drwxr-xr-x 8 root root  4096 Sep 24 20:05 .git
-rw-r--r-- 1 root root   534 Oct 22 17:21 .gitignore
-rw------- 1 root root  6871 Oct 22 17:21 README.md
drwx------ 2 root root  4096 Oct 22 17:20 __pycache__
drwx------ 2 root root  4096 Oct 22 17:20 examples
-rwx------ 1 root root 12670 Oct 22 17:20 genhealth_quickstart.py
 M .gitignore
?? README.md
?? examples/
?? genhealth_quickstart.py
Thinking…

pycache is generated by py_compile — ignored via .gitignore. Fix the permissions of README/examples (600/700 is weird but fine). Let me normalize with chmod and check whether openapi.json is publicly readable (200 — good, no auth needed!). Let me peek inside to confirm it's the real contract. This also backs up the claim that "the contract can be discovered without keys."

cd /sandbox/repo && chmod 644 README.md genhealth_quickstart.py examples/*.json && chmod 755 examples && rm -rf __pycache__
timeout 20 curl -sSL https://api.umpa.genhealth.ai/developer/openapi.json -o /tmp/gh_openapi.json -w "%{http_code}\n"; python3 - <<'EOF'
import json
d=json.load(open('/tmp/gh_openapi.json'))
print("openapi:",d.get("openapi"),"| version:",d.get("info",{}).get("version"))
print("paths:",len(d.get("paths",{})),"| schemas:",len(d.get("components",{}).get("schemas",{})))
print("sample:",list(d.get("paths",{}))[:6])
print("security:",d.get("components",{}).get("securitySchemes"))
EOF
git status --short
200
200
openapi: 3.1.0 | version: 1.0.0
paths: 29 | schemas: 62
sample: ['/developer/v1/capabilities', '/developer/v1/capabilities/v2', '/developer/v1/actions', '/developer/v1/integrations', '/developer/v1/integration-connections', '/developer/v1/actions/{handler}']
security: {'HTTPBearer': {'type': 'http', 'scheme': 'bearer'}}
 M .gitignore
?? README.md
?? examples/
?? genhealth_quickstart.py
Thinking…

openapi.json is publicly readable (no auth needed) — 29 paths / 62 schemas (the docs say 37 operations — 29 paths can contain multiple operations per path; 37 operations is reasonable). My README states "37 operations, 62 schemas" citing the docs — accurate as a citation. Also, I could note that openapi.json can be fetched without authentication. Minor update to the README: state that OpenAPI is publicly fetchable (verified) — this strengthens the claim that it's "easy to manage." Make a small edit.

After that, do a final run of doctor to confirm the behavior, and report back.

File edits

1 file

Completed
ModifiedREADME.md+2−1View changes

/sandbox/repo/README.md

Replacement excerpt

- Live `openapi.json` + Swagger + an authenticated **MCP** transport mean I can discover
- the contract instead of guessing it (37 operations, 62 schemas).
+ the contract instead of guessing it (docs: 37 operations, 62 schemas; the OpenAPI file
+ itself is publicly fetchable — verified: OpenAPI 3.1.0, 29 paths, 62 schemas, bearer auth).
Thinking…

Done. Final report. Keep it concise, and cover the following: what was built, the pricing mechanism, ease of management, the blocking issue (no API key), and a note that the developer workflow does indeed exist so I haven't stopped.

GenHealth.ai does have a real developer workflow (public docs portal, REST + MCP + live OpenAPI), so I built the example rather than stopping.

What I built (/sandbox/repo)

FilePurpose
genhealth_quickstart.pyStdlib-only client for the hosted API: doctor (read-only auth/capability probe), validate (preflight, persists nothing), run (validate → import → draft → publish → one idempotent run), inspect (poll run, never resubmits)
examples/synthetic-routing.workflow.jsonThe canonical synthetic graph from their docs — routes a boolean to one of two comment nodes; creates no patient/order/claim, needs no integration creds
README.mdQuickstart, pricing summary, manageability notes
.gitignoreNow excludes *-state.json run state

Safety built in: HTTPS-only origin, key never leaves the Authorization header, synthetic comment/if graphs only (any real action like brightree_* is rejected locally before a request is sent), no automatic write retries (intent recorded in state file first so interrupted writes get reconciled, not duplicated), persisted idempotency key, atomic 0600 state writes.

Verified locally: compiles, graph edges resolve, and all four error paths behave — missing key prints setup steps, a bogus key yields a clean HTTP 401 diagnostic, unsafe graphs are refused offline. The live host is up: /developer/v1/capabilities/v2 → 401 Requires authentication, /v2/cases → 403, /developer/openapi.json → 200 (publicly readable: OpenAPI 3.1.0, 29 paths, 62 schemas).

How pricing works

No published price list — genhealth.ai/pricing is a 404 and no page states a dollar figure. What's verifiable:

  • Sales-led enterprise subscription — every path is "Book a demo"/"Contact us"; footer says "For Enterprise".
  • Free sandbox tier — "spin up a free account and run real PA, intake, and eligibility flows in your sandbox… no credit card." That's the entry point this example targets.
  • Subscription is a real cost line — their ROI calculator reports net benefit "after accounting for GenHealth.ai subscription costs".
  • Plan-gated dev surface — the Workflow Developer API requires the "workflows plan feature" entitlement.
  • Metering dimension — docs define a "modeled internal event" as one successful/failed workflow-step attempt (loops/retries add events), described as a planning/benchmark unit with no published rate. Ask sales for $/event plus the workflows entitlement.
  • Access is split by scopes (workflow:read/write/publish/run), not seats.

Will this be easy for me to manage?

Yes for the dev loop, no for provisioning. Easy: publicly fetchable OpenAPI + Swagger + MCP transport, every docs page readable as Markdown by appending .md, discovery endpoints (/capabilities/v2, /actions, /actions/{handler}) for exact node types and action schemas, a non-persisting validate that returns machine-actionable findings, immutable versions/drafts/revert, idempotent runs, zero dependencies. Hard: credentials, organization, plan feature, and integration connections (Brightree/Bonafide/payer portals) must be provisioned by a human; real healthcare actions write to live systems and need explicit business-success branches plus review; MCP tool discovery is itself authenticated; no local emulator exists.

Where I'm blocked

doctor exits 1: no GENHEALTH_API_KEY, and self-provisioning one requires interactive signup + a real org + the workflows plan feature — I can't do that. Export a key and steps 2–5 run unattended:

export GENHEALTH_API_KEY="<YOUR_API_KEY>"
python3 genhealth_quickstart.py doctor

No local stacks started, no long-running commands waited on.

AX Fundamentals

23 checks. Open an area for details.

This check is a quick preview. Test more tasks and models with Gauge Agents.

Test your product with Gauge Agents

AX Check by Gauge