The platform, layer by layer.
Your product on top. Your EMR keys underneath. Between them, the server, the SDK, the skills and the workflows that every clinical-AI team otherwise writes from scratch.
The Kartha console, your own app, Claude Desktop or any MCP client.
Guardrail runtime, 50-skill catalog, 10 packaged agents, cohort workflows, sessions and streaming, REST and SSE on /v1.
fhir_read, fhir_search, fhir_create, fhir_update over any FHIR R4 resource. Auth, tenancy, routing gate, summarizer, notes search.
Epic, Oracle Health / Cerner, OpenEMR, GCP Healthcare API, MEDITECH, any FHIR R4 server.
What runs where
Everything in the two dark slabs deploys into your AWS, GCP, Azure or Databricks account. Model inference goes to your own provider, in your own account, at your own rates. The notes index lives in your Aurora or Lakebase pgvector. Nothing runs on Kartha-operated infrastructure.
Vendor auth quirks live in the provider layer, so the agents you write are EMR-agnostic. Any MCP client can connect straight to the server; the SDK is there when you want guardrails, skills and a runtime.
Integration platforms such as Redox and Particle move data between systems. Kartha is a different layer: the context, tools and guardrails an agent needs to act on EMR data once it is there.
The MCP FHIR server.
Four generic tools, one provider-agnostic image, a security model built so that neither the caller nor the model can point a request at the wrong hospital.
// read one resource, compact text back fhir_read({ resourceType: "Patient", id: "p-4471", outputFormat: "text" }) // search; bundles come back as tables in text mode fhir_search({ resourceType: "MedicationRequest", queryParams: "patient=p-4471&status=active", outputFormat: "compact-fhir" }) // create: double-locked, drafts only, verified before write fhir_create({ resourceType: "Observation", resource: { status: "preliminary", subject: { reference: "Patient/p-4471" }, … } })
Two-layer auth
Layer one decides who may call the server: a bearer token or a short-lived, customer-signed MCP-JWT. Layer two decides how the server reaches the EMR: it mints the token from your stored credentials, or forwards the caller's SMART token and never stores it.
Tenant by signed entitlement
One image serves many hospitals. Which EMR a request goes to is decided by an Ed25519-signed entitlement verified in the binary, never by a header, never by the LLM.
Routing gate
A call reaches only the provisioned endpoint for its tenant. Resource types and ids are shape-checked and URL segments escaped, so no input can traverse out of the FHIR base path.
Chart summarizer
A chart is 200K tokens. A deterministic, rule-based layer returns full FHIR, compact text, or a valid FHIR subset, cutting 70–90% of tokens with no LLM in the compression path. The id is always kept so you can re-read in full before acting.
Notes search
Optional. DocumentReference and Binary notes are chunked and embedded through your Bedrock into your pgvector, with forced row-level security and a TTL on the derived cache. Patient-scoped by construction.
Logs you can hand to an auditor
Bearer tokens, query values, keys and secrets are redacted at every level. Resource ids are pseudonymized with a keyed HMAC. Upstream FHIR bodies never reach the log.
The Agent SDK.
A TypeScript workspace for building clinical agents on the server, in your cloud. Agents are YAML, skills are Markdown, guardrails run on every call, and every turn is traced.
@kartha-health/client
MCP-JWT signing, the guardrail executor, and SMART-on-FHIR PKCE for apps where the clinician signs in themselves.
@kartha-health/agent
The runtime and agentic loop: prompt caching, full turn tracing, and guardrails enforced in code. Every retrieval is rebound to the session patient. Temporal bounds are re-injected when the model drops them.
@kartha-health/agent-server
POST /v1/sessions, streaming over SSE, and the same receipts the console shows, so your product can run headless.
@kartha-health/otel
Traces and token meters exported to your observability stack. No PHI in telemetry, by invariant.
--- name: sepsis-screening guideline: Surviving Sepsis Campaign 2021 · SIRS · qSOFA resources: [Observation, Condition, MedicationRequest, Encounter] output: result-card --- ## When to use Screen an adult inpatient for sepsis risk from the last 24h of vitals, labs and active infection diagnoses. ## Retrieval plan 1. Vitals (LOINC 8310-5, 8867-4, 9279-1, 8480-6) — last 24h only 2. Lactate (2524-7), WBC (6690-2), creatinine (2160-0) 3. Active Condition where category = encounter-diagnosis ## Result card SIRS criteria met · qSOFA score · evidence per criterion with timestamp · explicit "insufficient data" when a vital is missing
Fifty clinical skills, eight domains.
Expert-reviewed workflows written as Markdown and injected as context. Each one names its guideline, its retrieval plan and its output contract. Customer-authored skills always run, in every licensing state.
Medication safety
Reconciliation, drug interactions, adherence from dispense records, prescription appropriateness, opioid risk and MME.
Acute risk
Sepsis screening, pneumonia severity, VTE risk, fall risk, critical-value alerts.
Chronic disease
Diabetes panel review, renal function, cardiovascular risk scores, chronic pain review, disease registries.
Prevention and quality
Care gaps per USPSTF, immunization status per CDC schedules, preventive-care compliance, quality-measure dashboards.
Documentation
H&P, SOAP and progress notes, discharge summaries, procedure notes, transition-of-care summaries, referrals.
Transitions and operations
Discharge readiness, follow-up task generation, insurance coverage, demographics, panel overview.
Specialty
Oncology treatment timeline, pediatric growth assessment, prenatal visit workflow, mental-health screening instruments.
Regional packs
Guideline and code-system variants so the same skill reads correctly in another health system.
Your own
Author a skill in an afternoon with the same front matter and result-card contract. It runs on all three execution models without changes.
Clinical AI workflows for whole cohorts.
Take any skill and run it across a panel as durable, throttled jobs. One queue message per patient, a rate-limited worker, per-run results and a report that says exactly what ran and what did not.
skill: care-gap-identifier cohort: source: fhir_search query: "Patient?_has:Condition:patient:code=E11&active=true" throttle: per_second: 4 # respect the EMR rate limit output: bucket: s3://acme-clinical-runs/care-gaps/ report: honest # counts skipped, failed and partial runs
Code-driven, zero tool calls per patient
Batch chart abstraction retrieves by plan, not by prompt, so cost and latency are predictable across ten thousand charts.
Durable and throttled
SQS to a rate-limited Lambda worker, results to S3, status in DynamoDB. A queue-less offline runner exists for air-gapped tests.
An honest job report
Every run reports patients attempted, completed, skipped for missing data, and failed, with reasons. No silent gaps.
The console, and the receipt on every answer.
A reference clinical agent UI with 48 synthetic FHIR patients, the full skill catalog and ten packaged agents. Under every answer: a collapsible trace of each request, the raw response, the guardrail badges that fired, tokens and cost.
Clinicians do not have to trust that the agent was constrained. They can see which guardrail fired, on which call, and what the model actually received. The same trace is what your own product gets back from the API.
The console ships with an AWS App Runner deploy kit and runs against the synthetic patient set out of the box, so a security team can review the full behaviour before any real tenant is connected.
Try the sandbox on synthetic data, or ask for a walkthrough on your workload.
Three execution models. One skill format.
| Model | Who drives retrieval | Scope | Where it runs | Typical use |
|---|---|---|---|---|
| Interactive | The LLM, within guardrails | One session per patient | Console, your UI, Claude Desktop | Clinician asks a question and reads the trace |
| Headless | The LLM, within guardrails | One session per patient | Your product via /v1 REST and SSE | Your app embeds an agent with receipts |
| Cohort | Code, by retrieval plan | A whole panel | SQS, Lambda, S3 in your account | Care gaps across every diabetic patient, overnight |