MedVertical

BlogAgentic FHIR

Claude Should Not Guess FHIR: Validation Guardrails for AI-Assisted Development

Claude can generate plausible FHIR JSON. Trust requires a validation loop that identifies the runtime, protects data boundaries, explains the evidence, and revalidates every change.

Abstract agentic FHIR workflow showing resources moving through runtime planning, validation, issue explanation, controlled repair, and revalidation
André Sheydin
André Sheydin
Founder, MedVertical7 min read
fhirclaude-codevalidationai-agentsdeveloper-toolsopen-source

Claude can generate FHIR that looks right.

The JSON parses. The resource type exists. The fields sound plausible. A human reviewing the diff may not notice anything obviously wrong.

But plausible FHIR is not necessarily conformant FHIR. The resource may violate a profile cardinality, use a retired code, miss a required slice, reference the wrong canonical, or satisfy the base specification while failing the Implementation Guide used by the project.

That is the boundary AI-assisted FHIR development has to make explicit: the model can propose a change, but validation evidence has to verify whether it is technically conformant. Clinical and business acceptance remains a domain decision.

Generation is not validation

An AI agent can help write resources, mappings, FSH declarations, tests, and CI workflows. It can also explain an existing OperationOutcome in language that is easier to act on.

What it cannot do reliably from language-model knowledge alone is determine the current conformance state of a project. That answer depends on runtime evidence:

  • Which FHIR version is in scope?
  • Which profiles and package versions are installed?
  • Which terminology source is available?
  • Is the project generated from FSH or maintained as JSON?
  • Which validator produced the result?
  • Was the result full profile-aware validation or only a structural fallback?

Without those facts, an agent is reasoning from a description of the system rather than the system itself.

This is why validation cannot be a final prompt such as “check whether this looks valid.” It has to be a tool-backed loop.

A CI gate remains valuable, but it only evaluates the fixtures, packages, and runtime available during that run. CI validation alone does not establish whether live FHIR data remains conformant over time.

A concrete example

Suppose Claude generates an Observation that parses correctly and includes a plausible LOINC code. The project profile requires that code to come from a specific ValueSet and also requires a named slice that is absent from the resource.

A structural fallback can confirm that the JSON and base resource shape are valid. A profile- and terminology-aware validator can identify the missing slice and determine that the code is outside the required ValueSet. The agent can explain both findings, but it must not invent a replacement clinical code or populate the slice without project evidence.

Once a domain owner supplies the intended code and slice content, the agent can apply the change and rerun the same validator. That distinction also matters after deployment because terminology dependencies can change independently of application code.

The agent validation loop

A safe workflow has five distinct steps.

1. Inspect the project before changing it

The agent first identifies the local context: FHIR resources, SUSHI or FSH sources, generated artifacts, package declarations, existing CI workflows, configured validators, and possible privacy boundaries.

This matters because the visible JSON file may not be the source of truth. If a resource was generated from FSH, patching the generated file directly creates a fix that disappears on the next build.

2. Plan the validation runtime

Before running a check, the agent determines which validation path is actually available. Records for Claude Code can work with:

  1. configured Records MCP tools,
  2. a configured Records API,
  3. a local Records CLI,
  4. another profile-aware validator already available in the project, or
  5. a bounded local structural fallback.

The selected path must be named in the result. A structural check is useful, but it must not be presented as proof that the resource conforms to its profiles, terminology bindings, invariants, or reference rules.

3. Validate before proposing a fix

The current resource is validated before it is edited. That establishes the starting state and prevents the agent from attributing an issue to its own change when it already existed.

The result may be a fresh OperationOutcome, a report from an existing validator, or a clearly labeled structural finding. Explaining a supplied OperationOutcome is not the same as running a new validation, and the workflow has to preserve that distinction.

4. Separate mechanical fixes from domain decisions

Some findings can be repaired safely when the local evidence is unambiguous: malformed JSON, a primitive with the wrong JSON type, a field at the only valid FHIR path, or a CI command that invokes an existing validator incorrectly.

Other findings require a person with clinical, terminology, or project authority. An agent should not invent a clinical code, choose a status such as final, create an identifier, select a slice based on business meaning, or change a canonical URL without evidence that it is a typo.

The correct behavior is not to maximize the number of automatic fixes. It is to stop at the boundary where a technical repair would become a domain decision.

5. Revalidate and report the delta

After a mechanical change, the agent runs the same validation path again. The useful result is not “fixed” but a comparison:

  • which findings were resolved,
  • which findings remain,
  • whether any new findings appeared,
  • which runtime produced both results, and
  • which remaining decisions require domain input.

Without revalidation, a patch is only another plausible suggestion.

Runtime labels are part of the evidence

AI tools tend to collapse different kinds of confidence into one answer. FHIR validation cannot afford that ambiguity.

A base structural check, a project-local profile validator, a terminology-enabled validation service, and a full Records run answer different questions. If the preferred validator is unavailable, a fallback may still catch malformed resources, but it cannot inherit the authority of the missing validator.

The agent should therefore expose the validation path and its limits rather than hide them behind a generic success message. The runtime label is not implementation metadata; it is part of the evidence needed to interpret the result.

Clinical data needs an explicit boundary

FHIR resources may contain identifiers, demographics, notes, references, and other protected health information. An agent workflow must not turn validation into an unnoticed data transfer.

Records for Claude Code is local-first. It uses local files, local helper scripts, and locally configured runtimes by default. Access to FHIR URLs, hosted validators, terminology services, package downloads, or API-backed validation is gated until that boundary has been explicitly configured or approved for the task.

When no full validator is available, the plugin can perform a limited structural fallback without sending the resource to an external service. For real patient data, the preferred paths remain a local CLI, a local MCP runtime, or a self-hosted service inside the approved environment.

“Local-first” describes the validation runtime and helper execution. It does not mean that Claude Code is a locally hosted model. Organizations still need to configure and approve Claude Code itself according to their security, privacy, and data-processing policies before using it with sensitive data.

Privacy is not a disclaimer added after the workflow. It changes which runtime the agent is allowed to choose.

Engine, agent workflow, and operational layer

The recent Records releases address three different responsibilities.

The open-source @records-fhir/validator is the TypeScript validation engine. Version 0.4.2 hardens slicing behavior, embedding surfaces, and explicit runtime policy gates.

Records for Claude Code 0.6.0 is the open-source agent workflow. It detects project context, plans the available runtime, applies privacy gates, explains validation issues, distinguishes safe repairs from domain decisions, and revalidates changes. It works without a Records platform account.

The commercial Records platform adds the operational layer around validation: scheduled runs, environment history, baselines, deltas, and reproducible evidence for data already moving through live systems.

These layers are related, but they are not interchangeable. An agent plugin does not replace a validator. A validator does not provide production history. And a production evidence layer does not remove the need to catch errors while code and mappings are being written.

What is available now

Records for Claude Code installs as a Claude Code plugin:

claude plugin marketplace add medvertical/claude-recordsclaude plugin install records@medvertical

The focused commands cover the main workflow:

/records:doctor ./ig/records:validate ./examples/records:explain-outcome operationoutcome.json/records:init-ci ./examples

The plugin is open source under the MIT license. Its local fallback is deliberately bounded, and full profile, terminology, invariant, and reference validation still requires an appropriate configured runtime and the relevant FHIR packages.

That limitation is a feature of a trustworthy agent workflow: it reports what it knows, names how it knows it, and stops where the evidence ends.

The rule for agentic FHIR

The useful question is not whether Claude can produce FHIR. It can.

The useful question is whether every generated or repaired resource can pass through a repeatable loop that validates the current state, protects the data boundary, constrains automatic repair, and proves the result after the change.

The operating rule is simple. Where validation evidence cannot resolve the choice, domain authority decides.

Claude may propose. Validation must verify.


André Sheydin

About the author

André Sheydin

André is the founder of MedVertical and a product and design lead based in Cologne. He has spent more than 25 years shaping digital products, platforms, and design systems across complex domains, including healthcare, pharma, automotive, and SaaS. His work focuses on turning technical requirements into product structures that teams can actually build and operate.

Records

See the validation layer behind the article.

Records deploys adjacent to your FHIR server and validates your data continuously, with profile context, terminology resolution, and reproducible evidence.