Seize vrais appels à des pharmacies, zéro prix, et la raison mesurée : l'agent parle par-dessus le pharmacien
Les pharmacies ont payé environ 43 cents pour trente metformine, un chiffre que le CMS publie chaque semaine à partir des factures. Ce que vous payez est différent à chaque comptoir et publié nulle part, donc la seule façon de le savoir est de téléphoner. Sticker donne à un agent téléphonique CALL-E un médicament et un code postal, lit le registre fédéral NPI, appelle les pharmacies que vous autorisez, et joint chaque prix cité au NADAC du CMS. Seize vrais appels dans un code postal de Manhattan ont produit zéro prix et zéro refus. Le flux d'événements de la plateforme a montré pourquoi : 24 collisions sur 15 appels tracés où l'agent ouvrait son tour pendant que le pharmacien parlait encore. Signalé en amont comme le problème no 415, pris par un mainteneur le jour même. La contribution fusionnée comme PR no 404 après cinq passes de révision. Zéro est un résultat si vous dites comment vous l'avez obtenu.

Le chiffre qui est publié, et celui qui ne l'est pas
Les pharmacies ont payé en moyenne environ 43 cents pour trente comprimés de metformine. C'est le coût d'acquisition moyen national que le gouvernement fédéral publie chaque semaine, relevé sur les factures des pharmacies, et n'importe qui peut le consulter. Ce que vous payez est un autre chiffre. Il est différent à chaque comptoir, il change, et il n'est publié nulle part. Les contrats des pharmacies avec les gestionnaires de régimes exigent couramment que la pharmacie remette au PBM son prix le plus bas, donc les pharmacies gardent le prix comptant affiché au-dessus de leurs tarifs négociés au lieu de se faire concurrence dessus. Environ 19 000 pharmacies indépendantes restent largement hors des sites de comparaison. Donc la seule façon fiable de connaître un prix comptant est de téléphoner au comptoir, et c'est la méthode de recherche établie : une étude de 2020 dans Psychiatric Services a téléphoné à 265 pharmacies en un mois et trouvé un approvisionnement de 30 jours d'un générique allant de 29,99 $ à 1 345,00 $ dans une seule région métropolitaine. Ces études ont pris des semaines à des équipes. C'est ce qu'un agent téléphonique devrait pouvoir faire en un après-midi.
Trois règles qui rendent le titre plus petit
Donnez à Sticker un médicament et un code postal. Il lit le registre fédéral NPI pour les pharmacies communautaires agréées près de ce code, filtré à la taxonomie de vente au détail sans rendez-vous pour que les pharmacies de vente par correspondance et spécialisées ne puissent pas corrompre l'échantillon en douce. Il appelle celles que vous autorisez et pose une question : le prix comptant, sans assurance, pour cette quantité. Il renvoie une carte de prix triée et joint chaque prix au NADAC du CMS, pour que chaque ligne montre aussi la moyenne nationale payée par les pharmacies pour le même flacon. La colonne de majoration est le point, et ce n'est pas notre arithmétique sur notre propre exactitude : un prix qu'un pharmacien a dit à voix haute, divisé par un chiffre que le CMS a publié cette semaine-là. Trois règles décident de ce qui compte. Un prix ne compte que si un montant en dollars a été dit à voix haute pour la quantité demandée ; une cotation pour un autre format de flacon est rapportée et jamais recalculée, parce que quatre-vingt-dix comprimés ne sont pas trois fois trente. Un refus reste au dénominateur, parce que la part des pharmacies qui refusent de donner un prix par téléphone est un constat sur l'opacité, pas un trou à effacer. Et un appel terminé n'est pas une question répondue, parce qu'une boîte vocale renvoie le statut terminé avec task_completed vrai, donc c'est la réponse structurée qui décide, jamais le statut.

Seize appels, zéro prix, zéro refus
Seize vrais appels à des pharmacies agréées dans un seul code postal de Manhattan, et pas un n'a produit de prix. Pas un n'a refusé non plus. Chaque conversation qui a atteint une personne s'est terminée en une quarantaine de secondes, en général juste après la question. Le premier appel a atteint une boîte vocale hors des heures d'ouverture et l'agent y a attendu trois minutes et demie, parce que rien dans l'API ne dit quoi faire devant un enregistrement. Ça, c'était corrigeable dans la consigne. Ce qui n'était pas corrigeable dans la consigne, c'est ce que j'ai trouvé ensuite. Le flux d'événements de CALL-E enregistre les événements de parole du bot et de l'interlocuteur avec horodatage, et leur lecture a montré l'agent ouvrant son tour pendant que le pharmacien était encore en train de saluer. Six événements de parole distincts de l'interlocuteur encadrent le moment où l'agent commence à parler. Une personne qui entend une machine parler par-dessus ses propres mots dit allô, et raccroche.

J'ai réécrit l'ouverture quatre fois, terminant par un seul mot, allô avec un point d'interrogation, suivi de silence jusqu'à ce que la ligne soit calme, et l'agent coupait encore. Il n'y a pas de paramètre de requête pour la prise de parole : l'appel de création a six champs et rejette les clés inconnues. L'application d'un autre contributeur a heurté le même mur indépendamment. Les chaînes de pharmacies ont été un second mur : un arbre téléphonique exigeait un numéro à dix chiffres pour vérifier l'identité, ne pouvait pas valider un appelant sans dossier patient, et acheminait directement vers la messagerie. Une vérification de prix ne peut pas passer ça par conception. Et le compte a une limite d'appels simultanés documentée nulle part ; je l'ai trouvée en la dépassant, HTTP 429 account_concurrency_exceeded. Celle-là est devenue une fonctionnalité, parce qu'un 429 veut dire que rien n'a été composé, donc c'est la seule erreur qu'on peut attendre et réessayer sans risque.

L'effet secondaire est un téléphone qui sonne à un comptoir en activité
La surface de sûreté est la partie qui m'a pris le plus de temps. La découverte ne compose jamais : elle écrit une liste de candidats qu'une personne édite en liste blanche, et une liste blanche vide n'autorise rien plutôt que tout. Les numéros sont validés en E.164 ASCII strict, parce que la classe de chiffres de Python accepte aussi les chiffres arabo-indiens et pleine largeur et composerait autre chose que ce que vous lisez. L'origine de l'API est analysée et mise en liste blanche avant que la clé ne soit attachée à un en-tête, et les redirections sont désactivées. Les clés d'idempotence sont dérivées du contenu de la requête, donc un plantage et un redémarrage réutilisent la clé au lieu de composer deux fois. Une requête rejetée est un fait, mais un délai d'attente n'en est pas un, donc une création ambiguë arrête l'exécution pour un humain plutôt que de réessayer. Le premier mot de l'agent est seulement allô, et il attend que la pharmacie finisse sa salutation avant de dire quoi que ce soit d'autre. Puis une phrase à la fois révèle qu'il est une IA et pose la question, la divulgation avant la question à chaque fois, y compris après un transfert. CALL-E ne s'annonce pas et n'offre aucun réglage pour ça, donc ça n'existe que dans la consigne de la tâche. C'est pourquoi la suite de tests l'affirme.

Fusionné en amont, après cinq passes qui ont trouvé de vraies choses
La contribution a été fusionnée en amont dans CALLE-AI/awesome-phone-call-agents après cinq passes de révision avec le mainteneur du dépôt, et trois d'entre elles ont trouvé quelque chose de réel dans le code et les affirmations : de fausses affirmations sur ce qu'une pharmacie a payé quand le barème est une moyenne nationale, des chronométrages d'appels réels glissés dans des docstrings comme justification technique, un coût par appel inventé, un compteur d'appels qui créditait des appels qu'une exécution arrêtée avait empêchés. Tout corrigé, et la suite est passée de 61 tests à 94 et de 47 secondes à moins de 2. Un fait appris lors d'un appel réel est un artefact d'appel réel même quand il est formulé comme la raison d'une décision de conception. Le mainteneur m'a surpris à réintroduire exactement la chose qu'on m'avait dit de retirer, deux fois, parce que je l'avais écrite comme justification plutôt que comme donnée. Le comportement qu'elle justifie peut aller dans le dépôt. L'observation qui l'a produite ne le peut pas.


Ce qui n'est pas revendiqué
Un seul prix comptant. Zéro est un résultat si vous dites comment vous l'avez obtenu. J'aurais pu livrer un tableau simulé avec des prix dessus et un paragraphe sur des tests en direct à venir. À la place, la page de résultats montre seize vrais appels sans rien dans la colonne des prix, la transcription du pourquoi, et un rapport de bogue sur lequel la plateforme agit. Tout le reste du projet fonctionnait : la consultation du registre, le barème fédéral, le schéma, le modèle de sûreté, la logique d'arrêt. Rien de tout cela n'a compté, parce que la conversation n'est jamais arrivée au point où un prix pouvait être dit. Tout le produit vit ou meurt dans environ deux secondes de prise de parole que je ne contrôle pas. Et une méthode d'enquête conçue pour des appelants humains ne se transfère pas à un appelant IA déclaré sans l'aide de la plateforme. C'est un constat sur l'outil, pas sur les pharmacies, et j'ai essayé de le dire ainsi partout. Le NADAC est un barème et non une facture : le multiple vous dit à quelle hauteur un prix se situe au-dessus de ce qu'un médicament coûte généralement à acheter, pas ce qu'une boutique donnée a payé à son grossiste, et le rapport le dit à chaque exécution.

Sticker: phones pharmacies for a prescription's cash price and prices it against the federal benchmark. Sixteen real calls, zero prices, and the measured reason why
Voir le projet