Registros de decisiones de arquitectura
Esta sección contiene los registros de decisiones de arquitectura (ADR) de
la implementación de referencia ai-agent-eval-harness-healthtech. Cada ADR
captura una decisión arquitectónicamente significativa que es difícil o
costosa de revertir y explica por qué se tomó.
Convenciones
Section titled “Convenciones”- Formato: MADR 4.0.0. Copia la estructura de un ADR existente para cualquier decisión nueva; no inventes estructuras ad-hoc.
- Estado:
Proposed->Accepted. Cada registro plantea una decisión en tiempo presente; las alternativas que se sopesaron y se descartaron se conservan en la sección “Opciones consideradas” de ese mismo registro. - Nomenclatura de archivos:
ADR-NNNN-kebab-title, secuencia de cuatro dígitos rellenada con ceros, título en kebab y minúsculas. - Alcance de un ADR: una decisión por archivo.
- Tono: inglés técnico, sin texto de marketing, sin emojis, sin guiones largos. Toda afirmación sobre un framework, proveedor o versión cita una fuente primaria (notas de versión, documentación oficial, registro de la FDA, etc.).
Índice
Section titled “Índice”| ID | Título | Estado | Resumen en una línea |
|---|---|---|---|
| ADR-0001 | Framework de orquestación | Accepted | LangGraph 1.x por encima de CrewAI, Microsoft Agent Framework, Claude Agent SDK, Pydantic AI, AutoGen. Grafo de seis nodos con un nodo HITL review_response opcional basado en interrupt() y una fábrica de checkpointer MemorySaver / AsyncPostgresSaver. |
| ADR-0002 | Abstracción de proveedor de LLM | Accepted | Un Protocol LLMClient delgado sobre adaptadores de LangChain más una ruta Groq directa vía un cliente REST compatible con OpenAI, conmutado por una variable de entorno LLM_PROVIDER. |
| ADR-0003 | Arnés de evaluación | Accepted | Núcleo pytest hecho a mano más DeepEval y Promptfoo, con un LLM-como-juez Anthropic Claude Haiku para las dimensiones puntuadas por rúbrica y Phoenix para la inspección opcional de trazas. |
| ADR-0004 | Stack de RAG | Accepted | Almacén vectorial primario Chroma embebido; Voyage voyage-3.5 como embedder primario con un fallback local integrado BAAI/bge-small-en-v1.5 usando recuperación asimétrica consciente de instrucciones; Qdrant Cloud documentado como la alternativa de base de datos vectorial gestionada. |
| ADR-0005 | Barreras de seguridad y postura regulatoria | Accepted | Clasificador de alcance, plantillas de rechazo y un enrutador de escalamiento determinista de alto recall como módulos de primera clase; contrato de diseño = línea de la guía FDA 2026 General Wellness / CDS Software. |
| ADR-0006 | Stack de observabilidad | Accepted | Formato de transmisión OpenTelemetry + OpenInference; Langfuse Cloud para la demo en vivo, Phoenix autoalojado para las corridas de evaluación, Pydantic Logfire documentado como alternativa. |
| ADR-0007 | Objetivo de despliegue | Accepted | Google Cloud Run (imagen de contenedor, instancia única) como objetivo de producción, con Hugging Face Spaces conservado como objetivo secundario y local. Capa de resiliencia de despliegue: limitador de tasa por sesión, fallback de proveedor OpenAI -> Anthropic, caché de respuestas de TTL corto. |
| ADR-0008 | Licencia del código | Accepted | El código tiene licencia Apache 2.0. |
| ADR-0009 | Transmisión del grafo de ejecución del agente a la interfaz | Accepted | El grafo de ejecución del agente transmite eventos por nodo a la SPA mediante server-sent events, activable por negociación de contenido vía cabecera Accept; el contrato JSON de /chat no cambia. |
| ADR-0010 | Capa de datos (Supabase para los datos operativos de la demo) | Accepted | Postgres gestionado de Supabase para las claves de la demo, interacciones, sugerencias de mejora, solicitudes de claves de demo, consentimientos de claves de demo, sesiones de demo y uso de turnos de demo. El RAG sigue siendo Chroma (ADR-0004). |
| ADR-0011 | Detección de fuera de dominio en formato libre | Accepted | El clasificador de alcance determinista (regex + palabra clave) gana detección de fuera de dominio consciente del tema: admite los turnos dentro del dominio, rechaza los de fuera de alcance con alta confianza, y da a la entrada benigna fuera de tema un empujón amable en lugar de un rechazo duro. Sin llamada a LLM (un clasificador basado en LLM se descartó por costo). |
| ADR-0012 | Estrategia de expansión del corpus | Accepted | Estrategia de añadir sobre lo existente: los dominios nuevos se agregan encima del corpus base en lugar de reemplazarlo. Las tarjetas de KB y los turnos de evaluación nuevos amplían la cobertura a través de los dominios de adherencia a la medicación; se mantiene la paridad de locale entre en / es-419 / pt-BR. |
| ADR-0013 | Extensión de voz (ElevenLabs TTS + STT) | Accepted | ElevenLabs eleven_multilingual_v2 para TTS bajo demanda con mapeo de voz por locale y ElevenLabs Scribe para STT, entregado como una superficie con consentimiento previo y limitada por derechos en lugar de un control universal. |
| ADR-0014 | Fallback en cascada de proveedor de LLM | Accepted | Cascada tipada de errores transitorios OpenAI -> Anthropic. Los 4xx que no son 429 no se reintentan (preservación de cuota). El proveedor que responde se etiqueta en metadata para una atribución honesta de costos. |
| ADR-0015 | Almacenamiento de la capa de mejora continua | Accepted | Los registros de interacciones y las sugerencias de mejora están diseñados para ubicarse juntos en el mismo proyecto Postgres gestionado (ADR-0010), con PII redactada en el ingreso, curados por el operador y nunca aplicados de forma automática. |
| ADR-0016 | Capa de resiliencia de despliegue del nivel gratuito | Accepted | Limitador de tasa de ventana deslizante en proceso (IP consciente de proxy) + caché de respuestas con TTL, ambos acotados y residentes en memoria. Sin Redis, sin servicio externo. Diseño de un solo worker; el escalado a múltiples workers requiere estado externo. |
| ADR-0017 | Voz desactivada por defecto - política de seguridad | Accepted | La voz está desactivada por defecto y condicionada por un consentimiento explícito registrado en el servidor antes de cualquier turno de audio; el estado del consentimiento es del lado del servidor, no solo del cliente. Paridad de locale entre en / es-419 / pt-BR. |
| ADR-0018 | Invariante de datos solo sintéticos + lista de exclusión | Accepted | Corpus de evaluación 100% sintético a partir de fuentes de dominio público (MedlinePlus, DailyMed, WHO EML, etiquetas de la FDA). Lista de exclusión explícita: MIMIC, ChatDoctor, MedDialog, n2c2/i2b2. Carga de la prueba en el PR para cualquier dataset nuevo (licencia + procedencia + compatibilidad). |
| ADR-0019 | Respuesta estructurada del agente (esquema Pydantic + modo JSON del LLM) | Accepted | El agente emite una respuesta estructurada validada por Pydantic mediante el modo JSON del LLM en lugar de prosa libre, de modo que los evaluadores de rechazo / escalamiento leen campos explícitos en vez de inferir la intención a partir del texto. |
| ADR-0020 | Recuperación de documento padre (fragmentación en sub-tarjetas, citación a nivel de tarjeta) | Accepted | Las tarjetas de KB se fragmentan en pasajes de sub-tarjeta para el embedding/recuperación, y luego se de-duplican de vuelta a la tarjeta padre para la citación, mejorando el recall mientras las citaciones se mantienen a nivel de tarjeta. |
| ADR-0021 | Transmisión de tokens (stream personalizado de LangGraph + cliente de streaming) | Accepted | Los deltas del LLM por token se transmiten a la SPA sobre la superficie SSE existente (ADR-0009) para que el mensaje del asistente se renderice mientras se genera en lugar de después de un búfer de respuesta completa. |
| ADR-0022 | Recuperación híbrida (BM25 + denso + RRF + reordenamiento con cross-encoder) | Accepted | La recuperación solo densa se reemplaza por una canalización de tres etapas activable por bandera - generadores léxicos (BM25) + densos en paralelo, fusión por rango recíproco y luego reordenamiento con cross-encoder - degradándose con elegancia a la ruta densa previa. |
| ADR-0023 | Medición de recall de recuperación (recall@k / hit@k / nDCG@k) | Accepted | La calidad de la recuperación se mide directamente con recall@k / hit@k / nDCG@k contra las tarjetas relevantes etiquetadas, desacoplando la puntuación de recuperación de métricas acopladas a la generación como la cobertura de citaciones. |
| ADR-0024 | Enriquecimiento de citaciones del lado del servidor | Accepted | El modelo Citation gana los campos opcionales source_url, source_license y retrieved_score, enriquecidos del lado del servidor en el nodo de cierre, para que el popover de citaciones de la SPA se renderice sin un segundo viaje de ida y vuelta a la KB. |
| ADR-0025 | Proveedor de reordenamiento gestionado y determinismo de evaluación | Accepted | El reordenamiento se traslada a un reordenador gestionado fuera de la caja resuelto por turno (gestionado cuando hay una clave de Voyage, si no local), degradándose a solo-fusión ante cualquier corte; la compuerta de evaluación offline permanece sin store, determinista y gratuita. |
| ADR-0026 | Bloqueo de diseño de la calibración del juez | Accepted | La compuerta de concordancia humano-vs-juez congela su encuadre, bins, umbral y corpus antes de etiquetar cualquier caso, mide un kappa de Cohen ponderado linealmente por dimensión (compuerta agrupada, diagnósticos por locale) y solo permite reequilibrar el corpus - nunca ajustar el umbral - ante una paradoja de kappa. |
| ADR-0027 | Reequilibrio del corpus de calibración | Accepted | El corpus de calibración se compone para discriminar - ponderado hacia lo límite, paralelo entre locales y diverso en defectos - tras que un panel experto hallara que un corpus saturado en los polos arroja un kappa casi circular y no informativo; aplica la única palanca abierta del bloqueo de diseño con cada constante de integridad congelada. |
| ADR-0028 | Corrección del constructo de fidelidad | Accepted | La fidelidad se re-especifica como un constructo de solo contradicción - desligado de la fundamentación, que se queda con las adiciones no respaldadas - y se recalibra con un panel a ciegas y las constantes congeladas intactas, para que humano y juez midan lo mismo. |
| ADR-0029 | Puntuador de fidelidad por rúbrica | Accepted | El puntuador de fidelidad de producción se reemplaza por un puntuador por rúbrica del juez que lee la tarjeta citada completa y puntúa la contradicción o violación de sus reglas de comportamiento explícitas, para que ambos lados de la calibración midan el mismo constructo; el juez no cambia. |
| ADR-0030 | Compuerta de calibración consultiva por defecto | Accepted | La compuerta de calibración cableada se entrega consultiva por defecto - una ruta de corpus no establecida se omite en verde (registrada), la aplicación es una adhesión explícita del operador que dispara y pasa como está probado - para que una dimensión honestamente en el límite nunca se vuelva un CI permanentemente en rojo, con el umbral y los bins congelados nunca como palanca. |
| ADR-0031 | Calibración con compuerta de escalamiento y autolesión | Accepted | Escalamiento y autolesión se suman a la compuerta humano-vs-juez como bloqueadores duros del lanzamiento - una compuerta de revalidación que falla ante una concordancia de seguridad ausente, obsoleta para la cadena activa, de una sola clase o por debajo del umbral - mientras las dimensiones de calidad conservan la omisión consultiva; ninguna constante congelada se mueve y el juez queda intacto. |
| ADR-0032 | Corrección del constructo de la rúbrica de autolesión | Accepted | La rúbrica de autolesión se re-especifica con compuerta de presencia - primero pregunta si el turno porta una señal de autolesión (interpretada ampliamente) y no confiere crédito en un turno benigno ni en una emergencia que no es de autolesión - reflejando el ancla-ausente de escalamiento y revalidada sobre un conjunto reservado, con las etiquetas humanas y las constantes congeladas sin cambios. |
| ADR-0033 | Compuerta del carril de lanzamiento acotada a las dimensiones requeridas | Accepted | En el carril de aplicación del lanzamiento la compuerta falla en duro solo sobre las dimensiones de seguridad requeridas; las dimensiones no de seguridad quedan consultivas-y-reportadas ahí, y la compuerta general no cambia - para que el veredicto de lanzamiento gire sobre la señal de seguridad, sin mover ningún umbral ni debilitar ningún control de seguridad. |
| ADR-0034 | Piso de escalamiento ciego a la negación, ratificado | Accepted | El piso de emergencia determinista y siempre activo es intencionalmente ciego a la negación - una señal de alarma negada o hipotética igual escala (recall por sobre precisión) - y cualquier cambio a él debe re-pasar una compuerta de paridad de recall y una prueba de piso sin juez, para que un caso nunca pueda descartarse en silencio. |
| ADR-0035 | Inversión fail-safe del juez de escalamiento | Accepted | El juez semántico de escalamiento es la única barrera que falla hacia la escalamiento - cada tiempo de espera, error, fuera-de-esquema o desenlace malformado escala - corriendo detrás del piso determinista (combinado por conjunción, sin estrecharlo nunca) con un prior sesgado hacia el recall, un tiempo de espera duro acotado sin reintentos en línea, y la calibración empírica diferida. |
| ADR-0036 | Política acotada de redacción de nombres | Accepted | El redactor determinista de PII cubre solo identificadores estructurados (correo, teléfono, IDs nacionales incluidos RUT/CPF/DNI, tarjeta, MRN, fecha de nacimiento, dirección, con dígito verificador) y excluye intencionalmente los nombres de personas por tasa de falsos positivos y por datos solo sintéticos; una pasada activa de nombres condicionada por configuración es la mejora nombrada y diferida para un despliegue con datos reales. |