Pular para o conteúdo

Pilha empresarial do agente

Este documento mapeia a lacuna entre a atual implementação de referência da demonstração e o que uma implantação de produção exigiria. Ele serve a operadores que planejam adaptar a demonstração em uma implantação real, e a leitores que avaliam a consciência de produção da implementação de referência.

A arquitetura é apresentada em cinco camadas (Computação/Hospedagem, Armazenamento/Dados, IA/ML, Observabilidade, Segurança/Conformidade) usando diagramas Mermaid para clareza visual.

Isto cobre o agente conversacional de adesão à medicação conforme implantado no Google Cloud Run, o pipeline de CI/avaliação e uma arquitetura de referência de produção genérica. A demonstração roda em um host específico (Cloud Run); a referência de produção não prescreve um fornecedor de nuvem específico: ela identifica o que uma implantação real precisaria, não qual fornecedor usar.


A visão de mais alto nível: quem usa o sistema, de quais sistemas externos ele depende e quais dados fluem entre eles.

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

Limites-chave:

  • O agente é o único limite de confiança. Toda entrada do usuário entra através do FastAPI e passa pelo pipeline de salvaguardas antes de alcançar qualquer sistema externo.
  • Os provedores de LLM, o ElevenLabs e os sinks de observabilidade são dependências externas. O agente degrada graciosamente quando qualquer um deles está indisponível.
  • O Supabase armazena dados operacionais (chaves da demo, interações, sugestões de melhoria), mas o agente continua servindo turnos se ele estiver fora do ar.

Três contextos de implantação: a demonstração ao vivo, o pipeline de CI/avaliação e uma referência de produção.

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

Custo: perto de $0/mês em escala de demonstração. A hospedagem (a franquia sempre gratuita do Cloud Run sob uma única instância com escala a zero), a observabilidade (Langfuse Cloud Hobby, 50K obs/mês) e os dados operacionais (Supabase camada gratuita) permanecem dentro de camadas gratuitas em tráfego de demonstração (50-150 revisores, 5-10 turnos cada). Os completamentos de LLM rodam em provedores pagos (OpenAI primário, Anthropic de fallback), medidos pelo registro de custos “como se pago” e limitados por um disjuntor de orçamento diário, de modo que o gasto da demo é limitado. A primeira requisição após a instância escalar a zero paga um arranque a frio do contêiner. A mesma imagem também roda a custo genuinamente $0 no Hugging Face Spaces como alvo secundário.

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

Garantia de determinismo: O gate de CI passa sem chave por meio de um cliente LLM stub determinístico. Os scorers apoiados em juiz só são ativados quando uma chave do provedor juiz (Anthropic) está definida. A mesma imagem Docker que passa no CI é a imagem que é entregue ao Cloud Run.

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

Lacuna de produção: A demonstração roda em uma única instância com escala a zero e estado em memória. A produção precisa de escalonamento horizontal atrás de um balanceador de carga, persistência durável, segredos gerenciados, WAF, SIEM e provedores de LLM com SLA. A arquitetura é a mesma (StateGraph de seis nós do LangGraph) — apenas as camadas de infraestrutura mudam.


3. Diagrama de Componentes: internos do grafo do agente

Seção intitulada “3. Diagrama de Componentes: internos do grafo do agente”

O StateGraph de seis nós do LangGraph com o sétimo nó HITL opcional.

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

Fluxo de dados:

  1. intake — marca o início do turno, semeia o trace ID, aplica a redação de PII.
  2. guardrail_pre — executa o classificador de escopo. Mensagens dentro de escopo seguem para a recuperação RAG. Mensagens fora de domínio contornam a recuperação e recebem um fallback gracioso. Mensagens que disparam escalonamento curto-circuitam para o closing com um encaminhamento.
  3. retrieve_context — consulta o Chroma embedded por cartões de KB relevantes. Se nenhum cartão corresponder, o agente recusa em vez de alucinar.
  4. generate_response — chama o provedor de LLM configurado com o contexto recuperado e um prompt que impõe citação.
  5. guardrail_post — verifica que a resposta gerada não contém dosagem, diagnóstico ou outro conteúdo fora de escopo. Respostas sinalizadas são roteadas para a revisão HITL.
  6. closing — calcula a duração do turno, fecha o span OTel e retorna a resposta.
  7. review_response (opcional) — uma interrupção do LangGraph para revisão human-in-the-loop de turnos sinalizados. Desabilitado por padrão no modo de avaliação.

4. Comparação em cinco camadas: demonstração vs produção

Seção intitulada “4. Comparação em cinco camadas: demonstração vs produção”
CamadaDemonstração (atual)Referência de produção
Computação/HospedagemGoogle Cloud Run; única instância de contêiner (--max-instances 1); região us-central1; escala a zero quando ocioso; implantação sem chaves disparada por tag a partir da mesma imagem da CIHospedagem em nuvem (qualquer fornecedor); múltiplas instâncias atrás de balanceador de carga; auto-escalonamento; implantações sem tempo de inatividade; uptime com SLA
Armazenamento/DadosChroma embedded (DuckDB+Parquet) para RAG; MemorySaver em memória para o estado da conversa; Supabase camada gratuita (500 MB) para dados operacionais da demoArmazenamento vetorial gerenciado (Qdrant Cloud / Pinecone) para RAG; AsyncPostgresSaver para estado durável da conversa; Postgres gerenciado (RDS / Cloud SQL) com backups para dados operacionais; criptografia de dados em repouso
IA/MLOpenAI gpt-4o-mini (primário) com Anthropic claude-haiku-4-5 (fallback) para os completamentos; juiz de avaliação Anthropic claude-haiku-4-5 (Groq como fallback do juiz); embeddings gerenciados da Voyage voyage-3.5 (primário) com um fallback local embutido BAAI/bge-small-en-v1.5; cliente LLM stub determinístico para CI; cartões de KB sintéticosAPI de LLM com SLA e throughput dedicado; uma instância de juiz dedicada; serviço de embedding gerenciado; base de conhecimento expandida com revisão clínica; avaliação contínua com detecção de drift
ObservabilidadeSpans OTel com convenções OpenInference; Langfuse Cloud Hobby (50K obs/mês); Phoenix auto-hospedado em Docker para execuções de avaliação; Arize AX como painel secundário; exportação OTLPPilha OTel completa com collector, amostragem e políticas de retenção; backend de observabilidade dedicado (Datadog / Grafana / Honeycomb); alertas sobre latência, taxa de erro e anomalias de custo; exportação de log de auditoria para SIEM
Segurança/ConformidadeSem segredos no repositório (gitleaks no CI); lockfile fixado; Dependabot habilitado; sem PHI / sem EHR real; enquadramento de General Wellness da FDA; redação de PII na entrada e na saída; borda Cloudflare (Turnstile, origin-lock)WAF / proteção contra DDoS; segredos gerenciados (Vault / Cloud Secret Manager); BAA com todos os provedores de LLM; conformidade com a HIPAA Security Rule; SOC 2 Type II; testes de penetração; plano de resposta a incidentes

A comparação em cinco camadas nomeia o que muda entre a demonstração e uma implantação de produção; esta faixa esboça quando, como fases qualitativas em vez de datas comprometidas. Cada fase é condicionada à anterior, e o código do agente (o grafo de seis nós e suas salvaguardas) atravessa as quatro sem alteração: o trabalho está nas camadas de infraestrutura e governança.

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]

A demonstração já entrega a parte difícil determinante -o comportamento do agente medido e controlado por gates-, então o cronograma é dominado pelo trabalho de infraestrutura e conformidade, não por reconstruir o agente.

A demo roda perto de $0 / mês: hospedagem scale-to-zero, observabilidade e dados operacionais em camadas gratuitas, e completions de LLM medidos pelo livro de custos as-if-paid sob um disjuntor diário rígido. O custo de produção não é esse número escalado linearmente: ele tem duas partes que escalam de formas diferentes.

  • O custo variável é a inferência do LLM: tokens por turno vezes a taxa do provedor. Escala aproximadamente linear com o tráfego e é a linha dominante em volume. O livro as-if-paid já mede isso por turno, então uma cotação real parte de uma base medida em vez de um palpite.
  • O custo fixo é o piso de infraestrutura: uma instância quente, um vector store gerenciado, um Postgres gerenciado e um backend de observabilidade com retenção. Ele aparece como um degrau ao sair das camadas gratuitas e permanece bastante plano ao longo de uma ampla faixa de tráfego.

A forma, como faixas ilustrativas de ordem de grandeza -os números reais dependem do contrato do provedor, do modelo, do tamanho da recuperação e do uso de voz:

Turnos mensaisO que dominaForma do custo
Demo (centenas)camadas gratuitas + LLM medidoperto de $0, limitado pelo disjuntor diário
Milhares baixostokens de LLM por turnogasto variável pequeno; infra ainda quase-grátis
Dezenas de milharestokens de LLM + instância quente + stores gerenciadosaparece um piso de infra fixo; domina o custo variável de LLM
Centenas de milhares+throughput de LLM + retençãoterritório de contrato com o provedor: negocie throughput e taxas

Duas alavancas movem a linha variável sem tocar o agente: um modelo de geração menor ou mais barato, e uma recuperação que mantenha o prompt enxuto (menos tokens por turno). Ambas são configuração, não uma reconstrução.


Estado atual. A demonstração roda no Google Cloud Run como uma única instância de contêiner (--max-instances 1, região us-central1), escalando a zero quando ociosa. As implantações são sem chaves (Workload Identity Federation) e condicionadas a uma matriz de CI verde para a tag de release; o mesmo Dockerfile compila no CI, no desenvolvimento local e no Cloud Run. O teto de instância única é deliberado: o limitador de taxa, o cache de respostas e o checkpointer de HITL são em processo.

Lacuna de produção. Uma implantação de produção precisa de múltiplas instâncias atrás de um balanceador de carga, auto-escalonamento para lidar com picos de tráfego, implantações sem tempo de inatividade e uptime com SLA (tipicamente 99,9% ou mais). Os arranques a frio devem ser eliminados com uma contagem mínima de instâncias quentes. O próprio código do agente é portável — FastAPI com uvicorn funciona atrás de qualquer proxy reverso — mas a camada de infraestrutura precisa de investimento significativo.

Caminho de migração. A mesma imagem Docker pode implantar em qualquer host com capacidade Docker; o Hugging Face Spaces está documentado como alvo secundário (veja deploy). Escalar para fora no Cloud Run significa elevar o teto de instâncias, adicionar uma instância mínima quente e mover o limitador de taxa, o cache e o checkpointer em processo para um armazenamento compartilhado (Redis, Postgres) para que se comportem de forma consistente entre instâncias.

Estado atual. A recuperação RAG usa o Chroma embedded (DuckDB+Parquet), que é sem rede e roda inteiramente dentro da memória da instância. O estado da conversa usa o MemorySaver em memória por padrão; ele é perdido no reinício da instância. Os dados operacionais da demo (chaves, sessões, interações) são armazenados no Supabase camada gratuita (500 MB de Postgres gerenciado). A base de conhecimento contém cartões de KB sintéticos em formato JSONL.

Lacuna de produção. Uma implantação de produção precisa de estado durável da conversa (AsyncPostgresSaver via uma string de conexão do Postgres). A recuperação RAG deveria usar um armazenamento vetorial gerenciado (Qdrant Cloud, Pinecone ou pgvector no Postgres operacional) para persistência, suporte a corpus maior e desempenho de consulta em escala. Os dados operacionais precisam de um Postgres gerenciado com backups automatizados, recuperação a um ponto no tempo e criptografia em repouso.

Caminho de migração. O agente já provisiona uma fábrica de checkpointer durável do Postgres via uma string de conexão. Trocar do Chroma embedded por um armazenamento vetorial gerenciado exige atualizar a configuração do recuperador, mas não o próprio grafo do agente. O formato JSONL versionado já é compatível com o carregamento em massa em qualquer armazenamento vetorial.

Estado atual. Os completamentos de LLM rodam uma cascata de dois provedores: OpenAI gpt-4o-mini como primário, com fallback em Anthropic claude-haiku-4-5 diante de uma falha transitória do upstream. O juiz de avaliação é Anthropic claude-haiku-4-5, com Groq llama-3.3-70b-versatile como nível de fallback do juiz. Os embeddings usam por padrão o embedder gerenciado da Voyage quando há uma chave da Voyage presente e recaem no BAAI/bge-small-en-v1.5 localmente (sem chamada de API). O arcabouço de avaliação é um núcleo de pytest feito à mão mais DeepEval (métrica de Alucinação), um LLM-como-juiz da Anthropic e Promptfoo (red-team), executado contra casos golden sintéticos em três locales (en, es-419, pt-BR). A base de conhecimento cobre vários domínios de adesão à medicação com 38 cartões sintéticos.

Lacuna de produção. As APIs dos provedores têm limites de taxa e infraestrutura compartilhada. Uma implantação de produção precisa de provedores de LLM com SLA, com throughput e latência garantidos. O juiz de avaliação deveria rodar em uma instância dedicada para consistência. A base de conhecimento precisaria de revisão clínica e expansão para além dos dados sintéticos. A avaliação contínua com detecção de drift é essencial para a segurança em produção.

Caminho de migração. O Protocol de cliente torna a troca de provedor uma mudança de configuração. Adicionar um novo provedor exige implementar o Protocol (no máximo um punhado de métodos) e definir a cascata de geração por configuração. O arcabouço de avaliação já avalia contra limiares configuráveis e é controlado por CI.

Estado atual. Spans OpenTelemetry com convenções semânticas OpenInference envolvem cada nó, chamada de LLM, recuperação e decisão de salvaguarda. Sinks: Langfuse Cloud Hobby para a demonstração ao vivo (50K observações/mês, retenção de 30 dias), Phoenix auto-hospedado via Docker Compose para execuções de avaliação, e Arize AX como painel secundário. Nenhum alerta está configurado.

Lacuna de produção. Uma implantação de produção precisa de uma pilha OTel completa: collector com amostragem configurável, um backend dedicado com retenção longa (90+ dias), alertas sobre percentis de latência, taxas de erro e anomalias de custo, e exportação de log de auditoria para SIEM para conformidade. Os spans atuais já carregam os atributos certos; a lacuna está na infraestrutura de backend, não na instrumentação.

Caminho de migração. A instrumentação OTel é neutra em relação ao fornecedor. Trocar de backend é uma mudança de configuração do exportador OTLP. Os atributos de span existentes (interaction.*, llm.*, retrieval.*) são compatíveis com qualquer backend compatível com OTel.

Estado atual. Sem segredos no repositório (imposto pelo gitleaks no CI). As dependências são fixadas via o lockfile com monitoramento do Dependabot. Sem PHI, sem dados reais de EHR, sem informação identificável de paciente (dados 100% sintéticos). O agente opera sob o enquadramento de General Wellness / CDS de 2026 da FDA (veja postura regulatória). A redação de PII é aplicada tanto na entrada quanto na saída. Uma borda Cloudflare (verificação de bots com Turnstile, origin-lock) protege o serviço. O fingerprinting das chaves da demo usa uma impressão sha256 pseudonimizada (reidentificável), não anonimização.

Lacuna de produção. Uma implantação de produção que manipule dados reais de pacientes precisaria de: Web Application Firewall e proteção contra DDoS, segredos gerenciados (Vault, Cloud Secret Manager), Business Associate Agreements com todos os provedores de LLM, conformidade com a HIPAA Security Rule (avaliação de risco, notificação de violação, acesso mínimo necessário), certificação SOC 2 Type II, testes de penetração regulares e um plano de resposta a incidentes. A postura regulatória mudaria de General Wellness para um arcabouço de conformidade completo.

Caminho de migração. A arquitetura de salvaguardas é projetada para produção: classificação de escopo determinística, modelos de recusa auditáveis e escalonamento baseado em regras são todos padrões de nível de produção. A lacuna de segurança está principalmente na infraestrutura (WAF, gestão de segredos, criptografia) e no processo (avaliações de risco, cronogramas de auditoria), não no código da aplicação.


TópicoADR
Arcabouço de orquestração (StateGraph de seis nós)ADR-0001
Abstração de fornecedor de LLM (Protocol + adaptadores)ADR-0002
Arcabouço de avaliação (pytest + DeepEval + juiz Anthropic + Promptfoo)ADR-0003
Pilha RAG (Chroma embedded)ADR-0004
Salvaguardas (escopo + recusa + escalonamento)ADR-0005
Observabilidade (OTel + OpenInference)ADR-0006
Implantação (Google Cloud Run)ADR-0007
Camada de dados (Supabase camada gratuita)ADR-0010
Extensão de voz (ElevenLabs TTS/STT)ADR-0013
Arquitetura de streaming (eventos SSE)ADR-0009