The short answer
SMART Backend Services is the HL7 profile for clients that access FHIR servers autonomously, with no user authorising each session.1 The agent registers a public key with the server once, then requests tokens using client_credentials and a JWT signed with its private key.1 It asks for system/ scopes, such as system/Observation.rs, and gets short-lived tokens: expires_in SHOULD NOT exceed 300 seconds, and refresh tokens shouldn’t be issued.11 Give each agent its own client. Backend Services tells the server which client acted; it doesn’t tell anyone which person asked, what rule allowed it, or whether the write stored what was meant.
Deedglass
The server said “saved”. Deedglass looked.
Deedglass reads it back
When Backend Services fits
The profile lists the conditions: the server can register the client and pre-authorise a defined set of FHIR resources; the client may run autonomously, or with user interaction that doesn’t include authorising access; it supports asymmetric client authentication; and there’s no compelling need for a user to authorise access at runtime.1
| Agent | Fits Backend Services? | Why |
|---|---|---|
| Overnight coding queue processor | Yes | No user present; fixed scope |
| HL7 v2 to FHIR interface agent | Yes | System-to-system |
| Prior auth submission agent | Yes, usually | Runs on a queue; scope by resource |
| Clinician’s chat assistant acting as that clinician | Usually no | Needs user context; use the app launch flow |
| Patient-facing assistant | No | Patient authorises; use patient scopes |
The profile is designed to work with FHIR Bulk Data but isn’t limited to it.1
The flow, step by step
Code What the screen or file shows, copied as is.
1. Register agent ──(public key / JWKS)──▶ authorization server (once)
2. Discover agent ──GET .well-known/smart-configuration──▶ FHIR server
3. Token agent ──POST token endpoint: grant_type=client_credentials,
client_assertion=<JWT signed with private key>,
scope=system/Observation.rs ...──▶ access token (≤ 300 s)
4. Call agent ──Authorization: Bearer <token>──▶ FHIR API
Step 1 is a SHALL: the client must register before it runs.1 Step 3 is repeated whenever the token expires; there’s no refresh token, so a stolen token is useful for minutes, not days.1
Scoping an agent
SMART v2 scopes have the form context/ResourceType.letters, where the letters are an in-order subset of cruds: create, read, update, delete, search.2 For Backend Services the context is system/.1 A scope can be narrowed with query parameters.2
| Agent task | Scopes to request | Not |
|---|---|---|
| Read lab results for coding | system/Observation.rs?category=laboratory |
system/*.cruds |
| Draft notes | system/DocumentReference.c |
.cud on everything |
| Submit prior auth | system/Claim.c, reads it needs |
Patient update rights |
| Interface engine writes | Only resource types it maps | Delete |
Two rules from the profile help. The scope of each access token SHOULD be limited to the resources requested, and a server SHOULD refuse requests for data the scopes don’t allow.1 Request per task, not per agent lifetime. A token that can only read laboratory Observations can’t be talked into updating a Patient, whatever text the agent reads along the way.
Pre-authorisation happens at registration: the server has already decided what the client may ever access, and scopes in each request narrow it further.1 Keep the registered ceiling tight too. Our SMART v2 scopes post has more examples.
What it doesn’t cover
Backend Services authenticates a client. That’s necessary and not enough for agents:
| Question after an incident | Answered by Backend Services? |
|---|---|
| Which client made the call? | Yes, by its registered key |
| Which person or workflow asked the agent to act? | No |
| Which rule allowed or held the write? | No |
| Did a person approve it? | No |
| Did the server store what the agent meant? | No |
The gaps are where agent-specific controls go: a policy layer that holds high-risk writes for a person, a read-back after each write, and a record linking the client to the request, the decision, the approver and the result. Our EHR write tiers post covers the policy side, and our open draft spec AAP-H records which agent acted, what the rules decided, who approved, what the agent claimed and what the system of record shows afterwards.3
Think about the incident review you’ll eventually run. The FHIR server’s log will say client coding-agent-prod updated Observation obs-17 at 02:14. To act on that, you need the next link: which queue item or person triggered the run, what the model was asked, what policy evaluated the write, and what the record looked like afterwards. If that chain only exists in the agent’s own logs, it’s only as reliable as the agent. Keep it somewhere the agent can’t edit.
One more trap: don’t let several agents share one client. With a shared key, the server’s logs can’t tell them apart, and revoking one revokes all.
A setup checklist
- Register one Backend Services client per agent, with its own key pair.1
- Keep private keys in a secrets manager; rotate them; publish public keys as a JWKS.
- Pre-authorise only the resource types the agent’s job needs.
- Request narrow
system/scopes per task; use query-parameter scopes where your server supports them.2 - Expect tokens of five minutes or less and no refresh tokens.1
- Put a policy layer between the agent and writes that need a person.
- Read back after every write and record the result.
Questions people ask
How long do SMART Backend Services tokens last?
Tokens are short-lived; expires_in SHOULD NOT exceed 300 seconds, five minutes.1
Can a backend service use patient or user scopes?
It’s not prohibited, but it needs out-of-band coordination to establish which user or patient applies.1 Most agents use system/ scopes.
Is Backend Services enough to secure an AI agent?
It’s the right way to authenticate. It doesn’t decide which actions need approval or check results, so add those.
For agent writes held, checked and recorded, see our healthcare page and the provenance spec; the FHIR write integrity study shows why read-backs matter. To try approvals and read-backs on a real database in your browser, open the playground; to grade what an agent can reach on your own machine, run npx deedglass scan (the grade, explained).
Written with AI assistance and checked against our claims register.