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
Sección titulada «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.).
| 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 dev/eval BAAI/bge-small-en-v1.5 en el extra embeddings-local (fuera de la imagen de producción) 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. 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, uso de turnos de demo, presupuesto global de demo y verificaciones de correo 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. |
Referencias
Sección titulada «Referencias» Parte del portafolio de Waldemar Szemat · szemat.pro
GitHub · LinkedIn