Validating FHIR resources against a profile before an agent writes them

An AI agent that builds FHIR resources will sometimes build them wrong. You can catch that before the write, with the HL7 validator, a server's $validate operation, or rules on the server itself. Here's what each checks.

The short answer

Check an agent-built FHIR resource against your profiles before you write it, and have the server check again when it stores it. The FHIR specification lists what validation can check: structure, cardinality, value domains, coding and CodeableConcept bindings, invariants, profiles, Questionnaire responses and business rules (the last defined outside the specification).1 You can run those checks with the HL7 validator jar, with a server’s $validate operation, or with rules on the server, such as HAPI’s repository validating interceptor.13

Business rules are the exception: the specification says they’re made outside it, such as checking for duplicates, checking that references resolve and checking that a user is authorized to do what they want.1 Those are yours to write. An agent can produce a perfectly valid resource that shouldn’t exist.

This post is about records and data quality, not clinical content: a valid resource can still be clinically wrong, and that’s not something a validator judges.

A FHIR server can accept a write and quietly drop a field. Deedglass reads the resource back and names what differs. Made-up resource.

What FHIR validation checks, and what it doesn’t

Checked by validation1 Example agent mistake it catches
Structure An element in the wrong place, an unknown element
Cardinality A required element missing, or repeated when it shouldn’t be
Value domains A date in the wrong format
Coding bindings A code not from the required value set
Invariants A rule like “either a value or a reason it’s absent” broken
Profiles Your implementation guide’s extra constraints not met
Business rules: made outside the specification1 Example
Duplicate detection A second Patient for the same person
Authorization A write the agent wasn’t allowed to make
References that resolve A reference to a Patient that doesn’t exist
Your workflow’s own rules An Observation dated in the future when your workflow forbids it

Three places to validate

HL7 validator jar $validate on the server Server-side rules
Runs Anywhere Java runs: CI, a sidecar, the agent’s tool On the FHIR server, on request On the server, on every write
Stores anything No No Only if valid
Knows your IG If you load it (-ig)1 If the server has the profiles1 If rules reference them3
Catches agent mistakes before the write Yes Yes At the write
Can be skipped by the agent Yes, if it’s a separate step Yes No

The last row is the reason to use server-side rules as well: anything the agent’s tool does voluntarily, a buggy or steered agent can skip.

Option 1: the HL7 validator jar

The validator is a Java jar provided as part of the specification.1 The current build is validator_cli.jar, which the core library’s README says can be downloaded from the project’s GitHub releases.2 The specification’s example runs it against a file with a FHIR version, and describes -profile to check a specific profile and -ig to load an implementation guide.1 By default it uses a terminology server for code checks.1

In practice, the jar fits two places in an agent setup:

  • In CI, against example resources your agent’s tools produce, so a change to the tool that breaks conformance fails the build.
  • In the write path, as a check the tool runs before sending, for teams who can afford the extra time per write.

For the exact flags of the version you run, use the validator’s own help output and the HL7 Confluence page the README points to.2

Option 2: the $validate operation

Servers can check a resource against a profile when you POST it to $validate with a profile parameter, and return an OperationOutcome listing the issues. The specification’s example:

Code What the screen or file shows, copied as is.

POST [base]/Observation/$validate?profile=http://hl7.org/fhir/StructureDefinition/heartrate

Not every server supports it, and many validate only against profiles already registered with them.1 When it works, it’s the simplest check for an agent’s tool: validate, read the OperationOutcome, and only write if there are no errors. Feed the issues back to the agent as an error to fix, not a reason to retry the same resource.

Option 3: rules on the server

Server-side validation is the check the agent can’t skip. On a HAPI FHIR JPA server, the repository validating interceptor validates resources before storage, for writes from the HTTP API and internal Java calls, and rejects non-conforming creates and updates by default.3 It also validates the result of a PATCH, which request-time validation can’t. Our HAPI validation post compares the two HAPI options in detail.

Putting it together for agent writes

A layered setup:

  1. The agent’s tool validates first with $validate or the jar, and refuses to send a resource with errors.
  2. The server validates again at storage, so a tool bug or a steered agent can’t store a non-conforming resource.
  3. A read-back after the write confirms what was stored; our post on FHIR writes that said success shows why that’s needed even after validation passes.
  4. Duplicate checks (conditional create, or a search first) and reference checks, the business rules you own.
  5. A person approves writes that need one, as described in AI agents writing to patient records.

A checklist

  • Your implementation guide’s profiles are what you validate against, not just base FHIR.
  • The agent’s tool validates before writing and reports issues instead of retrying.
  • The server validates at storage and rejects errors.
  • CI runs the validator against sample outputs of the agent’s tools.
  • A terminology setup that matches your code systems, or a documented decision to skip code checks.
  • Duplicate detection, reference checks and authorization written as your own business rules.

For the basics, see the FHIR glossary entry. To see what the agents configured on your machine could write, paste the config into the check page or run npx deedglass scan (how the grade works); to try tool-call rules in your browser, open the playground.

Written with AI assistance and checked against our claims register.

The takeaway

FHIR validation covers structure, cardinality, bindings, invariants and profiles; duplicates and authorization are your own rules. Validate twice.

Read nextValidating FHIR writes in HAPI: request validation, repository validation, agents Try it: install in 7 s

Related on this site

Terms

In the docs

More posts

Sources

  1. 1HL7 FHIR R4: Validating resources · hl7.org · checked 26 October 2026
  2. 2hapifhir/org.hl7.fhir.core README (validator_cli.jar) · github.com · checked 26 October 2026
  3. 3HAPI FHIR docs: Repository Validating Interceptor · hapifhir.io · checked 26 October 2026

Published 26 October 2026, sources last checked 26 October 2026. If something here is out of date, write to hello@deedglass.com.

Try it on your own setup

npx deedglass scan

Grades only your own setup. Nothing is uploaded.

Pricing