Skip to content

Stack empresarial del agente

Este documento mapea la brecha entre la implementación de referencia actual de la demo y lo que requeriría un despliegue de producción. Sirve a los operadores que planean adaptar la demo a un despliegue real, y a los lectores que evalúan la conciencia de producción de la implementación de referencia.

La arquitectura se presenta a lo largo de cinco capas (Cómputo/Hospedaje, Almacenamiento/Datos, IA/ML, Observabilidad, Seguridad/Cumplimiento) usando diagramas Mermaid para mayor claridad visual.

Esto cubre el agente conversacional de adherencia a la medicación tal como está desplegado en Google Cloud Run, la canalización de CI/evaluación y una arquitectura de referencia de producción genérica. La demo corre en un host específico (Cloud Run); la referencia de producción no prescribe un proveedor de nube específico: identifica lo que un despliegue real necesitaría, no qué proveedor usar.


La vista de más alto nivel: quién usa el sistema, de qué sistemas externos depende y qué datos fluyen entre ellos.

graph TB
    Patient[Patient / Caregiver<br/>Chat + Voice UI]
    Operator[Operator / Reviewer<br/>Demo Key Mgmt + HITL Review]
    Agent[Medication Adherence Agent<br/>FastAPI + LangGraph]

    LLM[LLM Providers<br/>OpenAI + Anthropic<br/>Groq judge fallback]
    TTS[ElevenLabs<br/>TTS + STT]
    KB[Knowledge Base<br/>Chroma Embedded<br/>38 Synthetic KB Cards]
    Obs[Observability<br/>OTel / Langfuse / Phoenix]
    Supabase[(Supabase<br/>Demo Operational Data)]

    Patient -->|Chat / Voice Input| Agent
    Operator -->|Key Mgmt + Review| Agent
    Agent -->|Generate + Judge| LLM
    Agent -->|TTS / STT| TTS
    Agent -->|Retrieve + Cite| KB
    Agent -->|Spans + Metrics| Obs
    Agent -->|Keys + Sessions + Interactions| Supabase
    Agent -->|Response| Patient

Límites clave:

  • El agente es el único límite de confianza. Todo el input del usuario entra a través de FastAPI y pasa por la canalización de barreras de seguridad antes de alcanzar cualquier sistema externo.
  • Los proveedores de LLM, ElevenLabs y los destinos de observabilidad son dependencias externas. El agente se degrada con elegancia cuando alguno de ellos no está disponible.
  • Supabase almacena datos operativos (claves de la demo, interacciones, sugerencias de mejora) pero el agente sigue sirviendo turnos si está caído.

Tres contextos de despliegue: la demo en vivo, la canalización de CI/evaluación y una referencia de producción.

graph TB
    subgraph CloudRun["Google Cloud Run<br/>Single Instance (max-instances 1)<br/>us-central1 / scale-to-zero"]
        FastAPI[FastAPI<br/>Single Uvicorn Worker]
        Graph[LangGraph StateGraph<br/>6 Nodes + Optional HITL]
        MemorySaver[MemorySaver<br/>In-Memory Checkpointer]
        Chroma[Chroma Embedded<br/>DuckDB + Parquet<br/>38 Synthetic Cards]
        Resilience[Resilience Layer<br/>Rate Limiter + Fallback + Cache]
        OTel[OTel Exporter]
    end

    subgraph External["External Services"]
        OpenAI[OpenAI<br/>gpt-4o-mini<br/>Primary Completions]
        Anthropic[Anthropic<br/>claude-haiku-4-5<br/>Fallback + Eval Judge]
        Langfuse[Langfuse Cloud Hobby<br/>50K obs/month]
        Supabase[(Supabase Free Tier<br/>500 MB Postgres)]
        ElevenLabs[ElevenLabs<br/>TTS + STT<br/>Entitlement-gated]
    end

    FastAPI --> Graph
    Graph --> MemorySaver
    Graph --> Chroma
    Graph --> Resilience
    Resilience --> OpenAI
    Resilience --> Anthropic
    FastAPI --> OTel
    OTel --> Langfuse
    FastAPI --> Supabase
    FastAPI --> ElevenLabs

Costo: cerca de $0/mes a escala de demo. El hospedaje (la franquicia siempre gratuita de Cloud Run bajo una única instancia con escala a cero), la observabilidad (Langfuse Cloud Hobby, 50K obs/mes) y los datos operativos (nivel gratuito de Supabase) se mantienen dentro de niveles gratuitos con tráfico de demo (50-150 revisores, 5-10 turnos cada uno). Las completaciones del LLM corren en proveedores de pago (OpenAI primario, Anthropic de respaldo), medidas por el registro de costos “como si se pagara” y acotadas por un cortacircuitos de presupuesto diario, de modo que el gasto de la demo está acotado. La primera solicitud tras que la instancia escala a cero paga un arranque en frío del contenedor. La misma imagen también corre a costo genuinamente $0 en Hugging Face Spaces como destino secundario.

graph TB
    subgraph GitHub["GitHub Actions<br/>ubuntu-latest"]
        Build[Docker Build<br/>Same Dockerfile]
        Pytest[pytest Runner<br/>Deterministic Core<br/>Coverage Gate]
    end

    subgraph Eval["Eval Pipeline"]
        Deterministic[Deterministic Scorers<br/>Citation + Refusal<br/>Escalation + Recall]
        Judge[LLM-as-Judge<br/>Anthropic claude-haiku-4-5<br/>Groundedness + Faithfulness]
        DeepEval[DeepEval<br/>Hallucination Metric]
        Promptfoo[Promptfoo Nightly<br/>OWASP LLM Top 10 subset]
    end

    subgraph TestInfra["Test Infrastructure"]
        StubLLM[StubLLMClient<br/>Deterministic, Key-Free]
        Phoenix[Phoenix Self-Hosted<br/>Docker Compose Profile]
        GoldenCorpus[Golden Corpus<br/>315 Cases / 3 Locales<br/>JSONL Format]
    end

    Build --> Pytest
    Pytest --> StubLLM
    Pytest --> Deterministic
    Pytest --> Judge
    Pytest --> DeepEval
    Pytest --> Phoenix
    Pytest --> GoldenCorpus
    Promptfoo --> GoldenCorpus

Garantía de determinismo: La puerta de CI pasa sin claves a través de un cliente LLM de prueba (stub) determinista. Los scorers respaldados por juez se activan únicamente cuando se configura una clave del proveedor juez (Anthropic). La misma imagen de Docker que pasa la CI es la imagen que se entrega a Cloud Run.

2.3 Contenedor de referencia de producción

Section titled “2.3 Contenedor de referencia de producción”
graph TB
    subgraph Cloud["Cloud Hosting<br/>e.g., AWS / GCP / Azure"]
        LB[Load Balancer<br/>TLS Termination]
        FastAPIProd[FastAPI<br/>Multiple Workers<br/>Behind Reverse Proxy]
        GraphProd[LangGraph StateGraph<br/>Same 6 Nodes]
        PostgresSaver[AsyncPostgresSaver<br/>Durable Checkpointer]
        ManagedVector[Managed Vector Store<br/>e.g., Qdrant Cloud / Pinecone]
        ResilienceProd[Resilience Layer<br/>Redis-backed Rate Limiting<br/>Circuit Breakers]
    end

    subgraph LLMProd["LLM Providers"]
        LLMPrimary[Primary LLM<br/>SLA-backed API]
        LLMFallback[Fallback LLM<br/>Different Vendor]
        LLMJudge[Judge Model<br/>Dedicated Instance]
    end

    subgraph SecurityProd["Security + Compliance"]
        WAF[Web Application Firewall]
        SIEM[SIEM Integration<br/>Audit Log Export]
        SecretsMgr[Secrets Manager<br/>Vault / Cloud Secret Manager]
        KMS[Key Management Service]
    end

    LB --> WAF
    WAF --> FastAPIProd
    FastAPIProd --> GraphProd
    GraphProd --> PostgresSaver
    GraphProd --> ManagedVector
    FastAPIProd --> ResilienceProd
    ResilienceProd --> LLMPrimary
    ResilienceProd --> LLMFallback
    FastAPIProd --> SIEM
    FastAPIProd --> SecretsMgr
    FastAPIProd --> KMS

Brecha de producción: La demo se ejecuta en una única instancia con escala a cero y estado en memoria. Producción necesita escalado horizontal tras un balanceador de carga, persistencia durable, secretos gestionados, WAF, SIEM y proveedores de LLM respaldados por SLA. La arquitectura es la misma (StateGraph de LangGraph de seis nodos) — solo cambian las capas de infraestructura.


3. Diagrama de componentes: interioridades del grafo del agente

Section titled “3. Diagrama de componentes: interioridades del grafo del agente”

El StateGraph de LangGraph de seis nodos con el séptimo nodo opcional de HITL.

graph LR
    Intake[intake<br/>Mark turn start<br/>Seed trace_id<br/>PII redaction]
    GuardPre[guardrail_pre<br/>Scope classification<br/>Escalation detection<br/>Out-of-domain routing]
    Retrieve[retrieve_context<br/>RAG from Chroma<br/>Citation matching]
    Generate[generate_response<br/>LLM generation<br/>Citation enforcement]
    GuardPost[guardrail_post<br/>Output safety check<br/>Refusal verification]
    Closing[closing<br/>Duration calculation<br/>OTel span close]
    Review[review_response<br/>HITL pause<br/>Optional 7th node]

    Intake --> GuardPre
    GuardPre -->|in-scope| Retrieve
    GuardPre -->|out-of-domain| Generate
    GuardPre -->|escalation| Closing
    Retrieve --> Generate
    Generate --> GuardPost
    GuardPost -->|safe| Closing
    GuardPost -->|flagged| Review
    Review -->|approved| Closing
    Review -->|rejected| Generate

Flujo de datos:

  1. intake — marca el inicio del turno, siembra el ID de traza, aplica la redacción de PII.
  2. guardrail_pre — ejecuta el clasificador de alcance. Los mensajes dentro del alcance avanzan a la recuperación RAG. Los mensajes fuera de dominio omiten la recuperación y obtienen una alternativa elegante. Los mensajes que disparan escalamiento hacen cortocircuito hacia el cierre con una derivación.
  3. retrieve_context — consulta Chroma embebido en busca de tarjetas de KB relevantes. Si ninguna tarjeta coincide, el agente se rehúsa en lugar de alucinar.
  4. generate_response — llama al proveedor de LLM configurado con el contexto recuperado y un prompt que exige citación.
  5. guardrail_post — verifica que la respuesta generada no contenga contenido de dosificación, diagnóstico u otro contenido fuera de alcance. Las respuestas marcadas se enrutan a la revisión HITL.
  6. closing — calcula la duración del turno, cierra el span de OTel y devuelve la respuesta.
  7. review_response (opcional) — una interrupción de LangGraph para la revisión con humano en el ciclo de los turnos marcados. Desactivada por defecto en el modo de evaluación.

4. Comparación de cinco capas: demo vs producción

Section titled “4. Comparación de cinco capas: demo vs producción”
CapaDemo (actual)Referencia de producción
Cómputo/HospedajeGoogle Cloud Run; una única instancia de contenedor (--max-instances 1); región us-central1; escala a cero cuando está inactivo; despliegue sin llaves gatillado por etiqueta desde la misma imagen que CIHospedaje en la nube (cualquier proveedor); múltiples instancias tras un balanceador de carga; autoescalado; despliegues sin tiempo de inactividad; disponibilidad respaldada por SLA
Almacenamiento/DatosChroma embebido (DuckDB+Parquet) para RAG; MemorySaver en memoria para el estado de la conversación; nivel gratuito de Supabase (500 MB) para los datos operativos de la demoAlmacén de vectores gestionado (Qdrant Cloud / Pinecone) para RAG; AsyncPostgresSaver para el estado durable de la conversación; Postgres gestionado (RDS / Cloud SQL) con respaldos para los datos operativos; cifrado de datos en reposo
IA/MLOpenAI gpt-4o-mini (primario) con Anthropic claude-haiku-4-5 (respaldo) para las completaciones; juez de evaluación Anthropic claude-haiku-4-5 (Groq como respaldo del juez); embeddings gestionados de Voyage voyage-3.5 (primario) con un fallback local integrado BAAI/bge-small-en-v1.5; cliente LLM de prueba (stub) determinista para CI; tarjetas de KB sintéticasAPI de LLM respaldada por SLA con throughput dedicado; una instancia de juez dedicada; servicio de embeddings gestionado; base de conocimiento expandida con revisión clínica; evaluación continua con detección de deriva
ObservabilidadSpans de OTel con convenciones de OpenInference; Langfuse Cloud Hobby (50K obs/mes); Phoenix autohospedado en Docker para las corridas de evaluación; Arize AX como tablero secundario; exportación OTLPStack completo de OTel con colector, muestreo y políticas de retención; backend de observabilidad dedicado (Datadog / Grafana / Honeycomb); alertas sobre latencia, tasa de error y anomalías de costo; exportación de registros de auditoría a SIEM
Seguridad/CumplimientoSin secretos en el repo (gitleaks en CI); lockfile anclado; Dependabot habilitado; sin PHI / sin EHR real; encuadre de General Wellness de la FDA; redacción de PII en el ingreso y el egreso; borde de Cloudflare (Turnstile, origin-lock)Protección WAF / DDoS; secretos gestionados (Vault / Cloud Secret Manager); BAA con todos los proveedores de LLM; cumplimiento de la HIPAA Security Rule; SOC 2 Type II; pruebas de penetración; plan de respuesta a incidentes

La comparación de cinco capas nombra qué cambia entre la demo y un despliegue de producción; esta banda esboza cuándo, como fases cualitativas en lugar de fechas comprometidas. Cada fase está condicionada a la anterior, y el código del agente (el grafo de seis nodos y sus barreras de seguridad) atraviesa las cuatro sin cambios: el trabajo está en las capas de infraestructura y gobernanza.

graph LR
    A[Demo today<br/>Cloud Run single instance<br/>synthetic data, near $0] --> B[Hardening<br/>durable state + shared store<br/>managed vector store]
    B --> C[Pilot<br/>clinical KB review<br/>BAA + compliance controls]
    C --> D[Production<br/>multi-instance autoscale<br/>SLA + alerting + SIEM]

La demo ya entrega la parte difícil determinante -el comportamiento del agente medido y controlado por puertas-, así que el cronograma está dominado por el trabajo de infraestructura y cumplimiento, no por reconstruir el agente.

La demo corre cerca de $0 / mes: hosting scale-to-zero, observabilidad y datos operativos en niveles gratuitos, y completions de LLM medidos por el libro de costos as-if-paid bajo un cortacircuitos diario duro. El costo de producción no es ese número escalado linealmente: tiene dos partes que escalan distinto.

  • El costo variable es la inferencia del LLM: tokens por turno por la tarifa del proveedor. Escala más o menos linealmente con el tráfico y es la línea dominante a volumen. El libro as-if-paid ya lo mide por turno, así que una cotización real parte de una base medida y no de una suposición.
  • El costo fijo es el piso de infraestructura: una instancia caliente, un vector store gestionado, un Postgres gestionado y un backend de observabilidad con retención. Aparece como un escalón al salir de los niveles gratuitos y se mantiene bastante plano a lo ancho de una amplia banda de tráfico.

La forma, como bandas ilustrativas de orden de magnitud -las cifras reales dependen del contrato del proveedor, el modelo, el tamaño de recuperación y el uso de voz:

Turnos mensualesQué dominaForma del costo
Demo (cientos)niveles gratuitos + LLM medidocerca de $0, acotado por el cortacircuitos diario
Miles bajostokens de LLM por turnogasto variable pequeño; infra aún casi-gratis
Decenas de milestokens de LLM + instancia caliente + stores gestionadosaparece un piso de infra fijo; domina el costo variable de LLM
Cientos de miles+throughput de LLM + retenciónterritorio de contrato con el proveedor: negocia throughput y tarifas

Dos palancas mueven la línea variable sin tocar el agente: un modelo de generación más pequeño o más barato, y una recuperación que mantenga el prompt ajustado (menos tokens por turno). Ambas son configuración, no una reconstrucción.


Estado actual. La demo se ejecuta en Google Cloud Run como una única instancia de contenedor (--max-instances 1, región us-central1), escalando a cero cuando está inactiva. Los despliegues son sin llaves (Workload Identity Federation) y están condicionados a una matriz de CI en verde para la etiqueta de versión; el mismo Dockerfile se construye en CI, en el desarrollo local y en Cloud Run. El techo de una sola instancia es deliberado: el limitador de tasa, la caché de respuestas y el checkpointer de HITL son en proceso.

Brecha de producción. Un despliegue de producción necesita múltiples instancias tras un balanceador de carga, autoescalado para manejar los picos de tráfico, despliegues sin tiempo de inactividad y disponibilidad respaldada por SLA (típicamente 99,9% o más). Los arranques en frío deben eliminarse con un conteo mínimo de instancias calientes. El código del agente en sí es portable — FastAPI con uvicorn funciona tras cualquier proxy inverso — pero la capa de infraestructura necesita una inversión significativa.

Ruta de migración. La misma imagen de Docker puede desplegarse en cualquier host con capacidad de Docker; Hugging Face Spaces está documentado como destino secundario (consulta despliegue). Escalar hacia afuera en Cloud Run significa elevar el techo de instancias, agregar una instancia mínima caliente y mover el limitador de tasa, la caché y el checkpointer en proceso a un almacén compartido (Redis, Postgres) para que se comporten de forma consistente entre instancias.

Estado actual. La recuperación RAG usa Chroma embebido (DuckDB+Parquet), que es de cero red y se ejecuta enteramente dentro de la memoria de la instancia. El estado de la conversación usa MemorySaver en memoria por defecto; se pierde al reiniciar la instancia. Los datos operativos de la demo (claves, sesiones, interacciones) se almacenan en el nivel gratuito de Supabase (500 MB de Postgres gestionado). La base de conocimiento contiene tarjetas de KB sintéticas en formato JSONL.

Brecha de producción. Un despliegue de producción necesita estado de conversación durable (AsyncPostgresSaver mediante una cadena de conexión de Postgres). La recuperación RAG debería usar un almacén de vectores gestionado (Qdrant Cloud, Pinecone o pgvector en el Postgres operativo) para la persistencia, el soporte de corpus más grandes y el desempeño de consultas a escala. Los datos operativos necesitan un Postgres gestionado con respaldos automatizados, recuperación a un punto en el tiempo y cifrado en reposo.

Ruta de migración. El agente ya provisiona una fábrica de checkpointer de Postgres durable mediante una cadena de conexión. Cambiar de Chroma embebido a un almacén de vectores gestionado requiere actualizar la configuración del recuperador pero no el grafo del agente en sí. El formato JSONL versionado ya es compatible con la carga masiva en cualquier almacén de vectores.

Estado actual. Las completaciones del LLM corren una cascada de dos proveedores: OpenAI gpt-4o-mini como primario, con respaldo en Anthropic claude-haiku-4-5 ante una falla transitoria del upstream. El juez de evaluación es Anthropic claude-haiku-4-5, con Groq llama-3.3-70b-versatile como nivel de respaldo del juez. Los embeddings usan por defecto el embedder gestionado de Voyage cuando hay una clave de Voyage presente y recaen en BAAI/bge-small-en-v1.5 localmente (sin llamada a API). El arnés de evaluación es un núcleo de pytest hecho a mano más DeepEval (métrica de Alucinación), un LLM-como-juez de Anthropic y Promptfoo (red-team), ejecutado contra casos golden sintéticos a lo largo de tres locales (en, es-419, pt-BR). La base de conocimiento cubre varios dominios de adherencia a la medicación con 38 tarjetas sintéticas.

Brecha de producción. Las API de los proveedores tienen límites de tasa e infraestructura compartida. Un despliegue de producción necesita proveedores de LLM respaldados por SLA con throughput y latencia garantizados. El juez de evaluación debería ejecutarse en una instancia dedicada para la consistencia. La base de conocimiento necesitaría revisión clínica y expansión más allá de los datos sintéticos. La evaluación continua con detección de deriva es esencial para la seguridad de producción.

Ruta de migración. El Protocol del cliente hace que cambiar de proveedor sea un cambio de configuración. Agregar un nuevo proveedor requiere implementar el Protocol (a lo sumo un puñado de métodos) y configurar la cascada de generación mediante configuración. El arnés de evaluación ya puntúa contra umbrales configurables y está controlado por CI.

Estado actual. Los spans de OpenTelemetry con convenciones semánticas de OpenInference envuelven cada nodo, llamada al LLM, recuperación y decisión de barrera de seguridad. Destinos: Langfuse Cloud Hobby para la demo en vivo (50K observaciones/mes, retención de 30 días), Phoenix autohospedado vía Docker Compose para las corridas de evaluación, y Arize AX como tablero secundario. No hay alertas configuradas.

Brecha de producción. Un despliegue de producción necesita un stack completo de OTel: un colector con muestreo configurable, un backend dedicado con retención larga (90+ días), alertas sobre percentiles de latencia, tasas de error y anomalías de costo, y exportación de registros de auditoría a SIEM para el cumplimiento. Los spans actuales ya portan los atributos correctos; la brecha está en la infraestructura del backend, no en la instrumentación.

Ruta de migración. La instrumentación de OTel es neutral respecto del proveedor. Cambiar de backend es un cambio de configuración del exportador OTLP. Los atributos de span existentes (interaction.*, llm.*, retrieval.*) son compatibles con cualquier backend compatible con OTel.

Estado actual. Sin secretos en el repositorio (impuesto por gitleaks en CI). Las dependencias están ancladas mediante el lockfile con monitoreo de Dependabot. Sin PHI, sin datos reales de EHR, sin información identificatoria de pacientes (datos 100% sintéticos). El agente opera bajo el encuadre de General Wellness / CDS de la FDA 2026 (consulta la postura regulatoria). La redacción de PII se aplica tanto en el ingreso como en el egreso. Un borde de Cloudflare (verificación de bots con Turnstile, origin-lock) protege el servicio. La huella digital de las claves de la demo usa una huella sha256 seudonimizada (re-identificable), no anonimización.

Brecha de producción. Un despliegue de producción que maneje datos reales de pacientes necesitaría: Web Application Firewall y protección DDoS, secretos gestionados (Vault, Cloud Secret Manager), Acuerdos de Asociado de Negocio con todos los proveedores de LLM, cumplimiento de la HIPAA Security Rule (evaluación de riesgos, notificación de brechas, acceso mínimo necesario), certificación SOC 2 Type II, pruebas de penetración regulares y un plan de respuesta a incidentes. La postura regulatoria pasaría de General Wellness a un marco de cumplimiento completo.

Ruta de migración. La arquitectura de barreras de seguridad está diseñada para producción: la clasificación de alcance determinista, las plantillas de rechazo auditables y el escalamiento basado en reglas son todos patrones de grado de producción. La brecha de seguridad está principalmente en la infraestructura (WAF, gestión de secretos, cifrado) y en el proceso (evaluaciones de riesgos, calendarios de auditoría), no en el código de la aplicación.


TemaADR
Marco de orquestación (StateGraph de seis nodos)ADR-0001
Abstracción de proveedor de LLM (Protocol + adaptadores)ADR-0002
Arnés de evaluación (pytest + DeepEval + juez Anthropic + Promptfoo)ADR-0003
Stack de RAG (Chroma embebido)ADR-0004
Barreras de seguridad (alcance + rechazo + escalamiento)ADR-0005
Observabilidad (OTel + OpenInference)ADR-0006
Despliegue (Google Cloud Run)ADR-0007
Capa de datos (nivel gratuito de Supabase)ADR-0010
Extensión de voz (ElevenLabs TTS/STT)ADR-0013
Arquitectura de streaming (eventos SSE)ADR-0009