|
8 min de lecture
|

Utiliser FHIR comme cadre de développement agentique

Résumé de l'article

Les agents de codage IA écrivent du code plausible rapidement, mais sans cadre solide, ils dérivent, inventent des structures de données et ne peuvent pas vérifier leur propre travail — un vrai problème en santé. FHIR s'avère être un ensemble de rails particulièrement efficace : un modèle de données fixe de 150+ ressources, une validation côté serveur à chaque écriture, une terminologie intégrée et des types générés donnent à l'agent une structure sur laquelle s'appuyer et une boucle de rétroaction serrée pour s'autocorriger. Nous avons reconstruit notre PHR interne deux fois avec Claude Code — de zéro, puis sur FHIR — et la version FHIR était plus petite, plus cohérente, et la seule qui valait la peine d'être conservée.

Résumer cet article avec :
ChatGPTPerplexityClaudeGrok

Les LLM écrivent du code plausible, et ils l'écrivent vite. Mais quiconque a piloté un agent de codage sur un projet dépassant le stade du jouet connaît le mode d'échec : donnez-lui assez de corde et il dérive. Les noms de champs changent d'une session à l'autre, le modèle de données mute, et les conventions d'hier se réinventent discrètement. Pour une page d'accueil, c'est une nuisance. Pour un logiciel de santé, « improviser » n'est pas une option.

Nous avons passé du temps au laboratoire de Health Samurai à tester une hypothèse : FHIR n'est pas seulement un standard de données — c'est un cadre inhabituellement bien adapté au développement assisté par IA. Cet article explique pourquoi, et ce qui s'est passé quand nous avons construit le même produit deux fois pour le vérifier.

Le développement agentique a besoin de rails

Pointez un agent capable vers une pile générique et quatre problèmes reviennent sans cesse :

  • Les agents dérivent. Sans modèle fixe, chaque session invente des noms de champs, des formes et des conventions légèrement différents. Les modifications cessent de se composer — chaque nouvelle fonctionnalité entre en conflit avec la précédente.
  • Des structures de données hallucinées. Demandez à un agent « d'ajouter des allergies » et il inventera joyeusement un schéma. Rien ne rejette une structure invalide avant qu'elle n'atteigne la production et que quelqu'un ne remarque que les données sont incorrectes.
  • Pas d'auto-validation. Une pile générique ne donne à l'agent aucun moyen de vérifier sa propre production au-delà de « est-ce que ça compile ? » — ce qui n'est pas la même question que « s'agit-il de données de santé correctes ? »
  • Les cadres génériques ne connaissent pas la santé. React, Rails et Django ne savent rien de Patient, Encounter ou Observation. Chaque projet réinvente la même modélisation du domaine de zéro, et l'agent la réinvente un peu différemment à chaque fois.

Le fil conducteur est l'absence de rails — un cadre solide et opinionné qui contraint ce que l'agent peut produire et lui indique immédiatement quand il se trompe. Plus les rails sont bons, moins l'agent a de marge pour dériver, et plus vite il peut se corriger.

FHIR comme cadre de travail

Voici l'idée clé : FHIR fournit déjà presque tous ces rails, et il les fournit spécifiquement pour la santé. Un modèle de données fixe répond au problème de dérive ; la validation côté serveur répond aux structures hallucinées et donne à l'agent un moyen de se vérifier lui-même ; et l'ensemble est natif au domaine de la santé par construction, de sorte que rien n'a besoin d'être remodélisé d'un projet à l'autre.

Une pile native FHIR comporte trois parties qui travaillent ensemble — le serveur FHIR est le backend, l'application est construite sur des SDK FHIR, et le développeur travaille aux côtés d'un copilote IA qui parle déjà FHIR. La majeure partie de cette pile est prête avant même que vous n'écriviez une ligne de code applicatif ; la seule partie que vous construisez réellement est l'application qui relie les pièces FHIR entre elles.

Developer
AI Copilot Agent Skills
builds
PHR App You build this

FHIR SDK

FHIR Types FHIR Client

UI

React Components
FHIR REST
FHIR Server Ready
Data Model Validation Terminology SDC SQL on FHIR Subscriptions Access Control
Ready — FHIR spec, server, types, SDKs, AI copilots, agent skills You build — the app itself, wiring FHIR pieces together

Examinons ce que chaque couche apporte à l'agent.

Un modèle de données hérité, non conçu

FHIR R4 définit plus de 150 ressources de santé — Patient, Condition, Observation, Encounter, MedicationStatement, DocumentReference, et bien d'autres. Stockées nativement par un serveur FHIR comme Aidbox, elles n'exigent aucune conception de schéma.

FHIR R4 resource index — every resource grouped by category
La liste des ressources FHIR R4 : deux décennies de modélisation du domaine de la santé que vous héritez gratuitement.

Cela compte plus qu'il n'y paraît au premier abord. Quand l'agent a besoin de stocker des allergies, il n'invente pas une table — il utilise AllergyIntolerance, qui possède déjà les bons champs, les bonnes cardinalités et les bonnes liaisons. Les concepts de domaine personnalisés deviennent des ressources FHIR personnalisées — dans notre propre application, un PhrUser — avec leur propre StructureDefinition, et non pas une table sur mesure avec des colonnes inventées par l'agent. Vous héritez de deux décennies de modélisation du domaine de la santé, et l'agent aussi.

La validation comme boucle de rétroaction

Chaque écriture sur un serveur FHIR est validée par rapport à la StructureDefinition de la ressource : cardinalité, types, liaisons, invariants. Les données invalides n'entrent jamais dans la base de données.

Pour un développeur humain, c'est un filet de sécurité. Pour un agent, c'est quelque chose de plus précieux — une boucle de rétroaction précise et serrée. Au lieu d'une erreur 500 trois couches plus bas, l'agent reçoit quelque chose comme :

OperationOutcome: Patient.gender must be a code from
http://hl7.org/fhir/administrative-gender (male | female | other | unknown)

C'est exactement le type de signal sur lequel un agent s'autocorrige. La validation basée sur les profils vous permet de resserrer les règles pour votre propre projet — champs obligatoires, systèmes de codage fixes — sans écrire une seule ligne de code de validation. L'agent écrit moins, et le serveur lui indique immédiatement quand il se trompe.

Terminologie, formulaires et analytique — déjà résolus

Un serveur FHIR expédie de nombreux problèmes difficiles déjà résolus, et chacun est un problème que l'agent tenterait autrement de construire manuellement :

  • Terminologie. ValueSet, CodeSystem et les opérations comme $expand, $validate-code et $lookup sont intégrés. LOINC, SNOMED, RxNorm, ICD — tous accessibles via des points de terminaison FHIR standard. Votre application ne fournit pas un système de codage ; elle en interroge un (par exemple, Termbox, un serveur de terminologie FHIR dédié). La terminologie cesse d'être un billet « À faire : trouver une bibliothèque ».
  • SQL on FHIR. Définissez une ViewDefinition qui aplatit les ressources FHIR en colonnes tabulaires, puis interrogez la vue avec du SQL ordinaire. Les équipes d'analytique obtiennent du SQL pour les rapports ; les données restent en FHIR — pas de pipeline de transformation à écrire. Cela abaisse aussi la barre pour les tableaux de bord intégrés à l'application : un développeur d'application qui peine à agréger des ressources FHIR imbriquées peut écrire un simple GROUP BY contre une vue, de sorte qu'un graphique dans le produit et un rapport pour les analystes lisent à partir de la même définition. Et une ViewDefinition est elle-même une ressource FHIR, ce qui signifie que l'agent peut en écrire une — déclarer des colonnes est une tâche bien plus restreinte que de construire manuellement une logique de traversée sur des tableaux imbriqués.
  • Structured Data Capture (SDC). Les ressources Questionnaire FHIR décrivent des formulaires ; les utilisateurs les remplissent et les réponses sont stockées comme QuestionnaireResponse — liées, validées et consultables comme toute autre donnée FHIR. Les implémentations SDC apportent des constructeurs de formulaires, des moteurs de rendu, une logique d'extraction et des galeries de formulaires prêts à l'emploi.
Aidbox Form Builder — designing and testing a FHIR-native form
SDC en pratique : des formulaires natifs FHIR construits et testés dans Aidbox Form Builder.

Types et compétences pour l'agent

Les couches ci-dessus contraignent les données. Deux autres ferment la boucle autour de l'agent.

  • SDK typés. Parce que chaque ressource possède une StructureDefinition lisible par machine, les types client peuvent être générés plutôt qu'écrits — pour TypeScript, Python, C#, Java et d'autres. Le bénéfice pour un agent dépasse l'autocomplétion : un champ mal orthographié ou une mauvaise énumération échoue au niveau du type, avant qu'une requête ne soit envoyée, et une source de vérité unique générée est partagée par le serveur et le client, de sorte que les deux côtés d'une fonctionnalité ne peuvent pas diverger. Des générateurs disponibles publiquement font de cela une étape de construction, pas un projet.
  • Compétences d'agent. La couche la plus récente est une documentation rédigée pour les agents plutôt que pour les humains. Parce que FHIR est un standard public avec des API de serveur publiques, cette connaissance est réutilisable d'un projet à l'autre — comment formuler une requête de recherche, comment fonctionnent les politiques d'accès, quand recourir à SQL on FHIR — plutôt que quelque chose que chaque équipe doit réenseigner. Pointer un agent vers une documentation à jour l'empêche également de s'appuyer sur ce qu'un modèle a absorbé au moment de l'entraînement, ce qui, pour une spécification qui publie de nouvelles versions, est une vraie source de code faux mais affirmé avec assurance.

Ces deux éléments se configurent une seule fois, et l'agent en bénéficie ensuite à chaque tâche.

L'expérience : la même application, une fondation différente

La théorie ne coûte pas cher, alors nous l'avons testée. Notre terrain d'expérimentation était le Dossier de santé personnel (PHR) interne de Health Samurai — un vrai produit pour notre propre équipe et les familles dont elle prend soin. Sa portée est véritablement non triviale : gérer des dossiers pour soi-même et ses personnes à charge, saisir des conditions, médicaments, allergies et procédures, téléverser des PDF médicaux, des consultations par clavardage avec des médecins, un résumé du patient, et une assistance IA ancrée dans les propres données FHIR du patient.

Nous l'avons construit deux fois avec Claude Code — même portée, fondation différente. La première fois, nous avons laissé l'agent construire de zéro ; la deuxième fois, nous avons reconstruit toute l'application avec FHIR comme cadre.

v1 — de zérov2 — sur FHIR
PileReact + Node + Postgres ordinairesBackend Aidbox, types FHIR générés, composants UI Aidbox open source, compétences d'agent
Modèle de donnéesInventé par l'agent, par sessionFHIR R4, fixe
ValidationCe que l'agent a écritCôté serveur, à chaque écriture
Nouvelle fonctionnalitéRéenseigner les conventions dérivéesChoisir une ressource, générer les types, câbler l'interface
RésultatContinuait à dériverPlus petite, cohérente — celle qui valait la peine d'être conservée

Dans v1, l'agent a inventé son propre modèle de données, sa propre forme d'API, ses propres règles de validation. Chaque nouvelle fonctionnalité signifiait réenseigner à l'agent les conventions dont il s'était déjà éloigné. Dans v2, reconstruire la même application sur FHIR a produit une base de code plus petite et plus cohérente — l'agent s'est appuyé sur FHIR plutôt que de le réinventer.

En pratique, cela se manifeste dans le code ordinaire. Les types générés combinés à un ensemble de compétences Claude Code open source pour travailler avec Aidbox ont permis à l'agent d'écrire une création de patient comme celle-ci, sans aucun schéma à concevoir :

// The agent writes against generated types — the shape is not up for negotiation
const patient = await aidbox.create<Patient>({
  resourceType: "Patient",
  name: [{ given: [body.givenName], family: body.familyName }],
  birthDate,
  gender: body.gender || undefined,
  active: true,
});
// ...and the server validates it on write.

Rien de remarquable, ce qui est précisément le but : il n'y avait aucune décision à prendre sur les noms de champs ou le stockage, et rien dont l'agent pourrait s'éloigner à la prochaine session.

Trois enseignements se sont démarqués :

  1. Moins de code. Le cadre gère les parties ennuyeuses — schéma, API, validation — de sorte que l'agent en écrit simplement moins.
  2. Une boucle de rétroaction plus serrée. Le serveur rejette les écritures invalides avec des erreurs précises, et l'agent s'autocorrige — pas d'erreur 500 mystérieuse trois couches plus bas.
  3. Les fonctionnalités deviennent des conversations, pas des projets. Ajouter un concept clinique est une seule étape — choisir une ressource FHIR, générer les types, câbler l'interface — pas cinq.

L'exemple le plus clair : nous avons demandé une fonctionnalité de résumé du patient. Sur une pile générique, cela signifie concevoir un schéma de résumé, décider comment référencer les dossiers sous-jacents, et construire une API autour de cela. Sur FHIR, l'agent a utilisé la ressource Composition — le propre modèle du standard pour un document clinique structuré et sectionné — et l'a implémentée proprement : des sections référençant les ressources Condition, MedicationStatement et AllergyIntolerance existantes du patient, sans schéma sur mesure inventé. Une fonctionnalité qui aurait été un petit projet est devenue une seule conversation, parce que FHIR l'avait déjà modélisée.

Comment l'essayer vous-même

Si vous souhaitez donner à votre agent les mêmes rails, la recette de départ est courte :

  • Choisissez un serveur FHIR comme backend (par exemple, Aidbox).
  • Générez les types FHIR avec @atomic-ehr/codegen pour que l'agent code contre de vraies structures.
  • Installez les compétences Claude Code pour que l'agent parle FHIR dès le départ.

Le code source du PHR est également ouvert, si vous souhaitez voir un exemple complet : github.com/HealthSamurai/phr.

Et ensuite : retirer le programmeur de la boucle ?

Voici la question que l'expérience a soulevée. Si FHIR donne à un agent suffisamment de structure pour construire une vraie application — que se passe-t-il si l'utilisateur de l'agent n'est pas du tout un développeur ?

Imaginez une plateforme où les médecins construisent leurs propres applications, en itérant avec un assistant IA en langage courant, et ces applications se branchent directement sur l'infrastructure existante de l'organisation de santé :

  • Les médecins comme bâtisseurs — pas d'équipe de développement intermédiaire ; décrivez le flux de travail, obtenez une application fonctionnelle.
  • Itérer avec l'IA — modifier un formulaire, ajuster une règle, ajouter un résumé. Une conversation, pas un billet.
  • S'intègre à la pile hospitalière — parle FHIR au DSE, respecte l'authentification, l'audit et les politiques existants. Pas un silo, mais un citoyen de l'infrastructure.

C'est le même pari que toute cette expérience, un niveau au-dessus : FHIR comme fondation qui permet à l'IA de construire des logiciels de santé pour les personnes qui en ont réellement besoin.


Vous souhaitez discuter de l'application de cette approche à votre propre pile ? Contactez Aleksandr Kislitsyn, ou explorez le dépôt PHR open source et ses compétences Claude Code.

Partager cet article
Comments
Comments
Sign in
Loading comments...
Subscribe to our blog

Get the latest articles on FHIR, interoperability, and healthcare IT.