Registros de Decisão de Arquitetura
Esta seção reúne os Registros de Decisão de Arquitetura (ADRs) da
implementação de referência ai-agent-eval-harness-healthtech. Cada ADR
captura uma decisão arquiteturalmente significativa que é difícil ou
cara de reverter e explica por que ela foi tomada.
Convenções
Seção intitulada “Convenções”- Formato: MADR 4.0.0. Copie a estrutura de um ADR existente para qualquer nova decisão; não invente estruturas ad-hoc.
- Status:
Proposed->Accepted. Cada registro declara uma decisão no tempo presente; as alternativas que foram ponderadas e deixadas de lado são mantidas na seção “Opções consideradas” do próprio registro. - Nomenclatura de arquivos:
ADR-NNNN-kebab-title, sequência de quatro dígitos preenchida com zeros à esquerda, título em kebab minúsculo. - Escopo de um ADR: uma decisão por arquivo.
- Tom: inglês técnico, sem texto de marketing, sem emojis, sem travessões. Toda afirmação sobre framework / fornecedor / versão cita uma fonte primária (notas de versão, documentação oficial, registro da FDA, etc.).
| ID | Título | Status | Resumo em uma linha |
|---|---|---|---|
| ADR-0001 | Framework de orquestração | Accepted | LangGraph 1.x em vez de CrewAI, Microsoft Agent Framework, Claude Agent SDK, Pydantic AI, AutoGen. Grafo de seis nós com um nó HITL review_response opcional via interrupt() e uma fábrica de checkpointer MemorySaver / AsyncPostgresSaver. |
| ADR-0002 | Abstração de fornecedor de LLM | Accepted | Um Protocol LLMClient fino sobre adaptadores LangChain mais um caminho Groq direto via um cliente REST compatível com OpenAI, alternado por uma variável de ambiente LLM_PROVIDER. |
| ADR-0003 | Harness de avaliação | Accepted | Núcleo artesanal em pytest mais DeepEval e Promptfoo, com um LLM-como-juiz Anthropic Claude Haiku para as dimensões pontuadas por rubrica e Phoenix para inspeção opcional de traces. |
| ADR-0004 | Stack de RAG | Accepted | Armazenamento vetorial primário Chroma embarcado; Voyage voyage-3.5 como embedder primário com um fallback local embutido BAAI/bge-small-en-v1.5 usando recuperação assimétrica consciente de instruções; Qdrant Cloud documentado como a alternativa de banco de dados vetorial gerenciado. |
| ADR-0005 | Guardrails e postura regulatória | Accepted | Classificador de escopo, templates de recusa e um roteador de escalonamento determinístico de alto recall como módulos de primeira classe; contrato de design = linha de orientação FDA 2026 General Wellness / CDS Software. |
| ADR-0006 | Stack de observabilidade | Accepted | Formato de transmissão OpenTelemetry + OpenInference; Langfuse Cloud para a demo ao vivo, Phoenix auto-hospedado para execuções de avaliação, Pydantic Logfire documentado como alternativa. |
| ADR-0007 | Alvo de implantação | Accepted | Google Cloud Run (imagem de contêiner, instância única) como alvo de produção, com Hugging Face Spaces mantido como alvo secundário e local. Camada de resiliência de implantação: rate limiter por sessão, fallback de provedor OpenAI -> Anthropic, cache de resposta com TTL curto. |
| ADR-0008 | Licença de código | Accepted | O código tem licença Apache 2.0. |
| ADR-0009 | Streaming do grafo de execução do agente para a UI | Accepted | O Agent Execution Graph transmite eventos por nó para a SPA via server-sent events, com adesão opcional por negociação de conteúdo via cabeçalho Accept; o contrato JSON /chat permanece inalterado. |
| ADR-0010 | Camada de dados (Supabase para dados operacionais da demo) | Accepted | Postgres gerenciado do Supabase para chaves da demo, interações, sugestões de melhoria, solicitações de chaves da demo, consentimentos de chaves da demo, sessões da demo e uso de turnos da demo. O RAG continua sendo Chroma (ADR-0004). |
| ADR-0011 | Detecção de fora de domínio em texto livre | Accepted | O classificador de escopo determinístico (regex + palavra-chave) ganha detecção de fora de domínio ciente do tópico: admite turnos dentro de domínio, recusa fora de escopo de alta confiança, e dá à entrada benigna fora de tópico um empurrão gentil em vez de uma recusa dura. Sem chamada de LLM (um classificador baseado em LLM foi descartado por custo). |
| ADR-0012 | Estratégia de expansão do corpus | Accepted | Estratégia de acréscimo ao existente: novos domínios adicionados sobre o corpus base em vez de substituí-lo. Novos cartões de KB e turnos de avaliação ampliam a cobertura pelos domínios de adesão a medicamentos; paridade de localidade mantida entre en / es-419 / pt-BR. |
| ADR-0013 | Extensão de voz (ElevenLabs TTS + STT) | Accepted | ElevenLabs eleven_multilingual_v2 para TTS sob demanda com mapeamento de voz por localidade e ElevenLabs Scribe para STT, entregue como uma superfície com consentimento prévio e limitada por direitos em vez de um controle universal. |
| ADR-0014 | Fallback em cascata de provedor de LLM | Accepted | Cascata tipada de erros transitórios OpenAI -> Anthropic. Um 4xx que não seja 429 não é repetido (preservação de cota). O provedor que respondeu é etiquetado em metadata para atribuição honesta de custo. |
| ADR-0015 | Armazenamento da Camada de Melhoria Contínua | Accepted | Logs de interação e sugestões de melhoria são projetados para coalocar no mesmo projeto Postgres gerenciado (ADR-0010), com PII redigida na entrada, curados pelo operador e nunca aplicados automaticamente. |
| ADR-0016 | Camada de resiliência de implantação no nível gratuito | Accepted | Rate limiter de janela deslizante em processo (IP consciente de proxy) + cache de resposta com TTL, ambos limitados e residentes em memória. Sem Redis, sem serviço externo. Design de worker único; escalonamento multi-worker exige estado externo. |
| ADR-0017 | Voz desligada por padrão - política de segurança | Accepted | A voz vem desligada por padrão e é condicionada por consentimento explícito registrado no servidor antes de qualquer turno de áudio; o estado do consentimento é do lado do servidor, não apenas do cliente. Paridade de localidade entre en / es-419 / pt-BR. |
| ADR-0018 | Invariante de dados exclusivamente sintéticos + lista de exclusão | Accepted | Corpus de avaliação 100% sintético a partir de fontes de domínio público (MedlinePlus, DailyMed, WHO EML, rótulos da FDA). Lista de exclusão explícita: MIMIC, ChatDoctor, MedDialog, n2c2/i2b2. Ônus da prova no PR para qualquer novo conjunto de dados (licença + procedência + compatibilidade). |
| ADR-0019 | Resposta estruturada do agente (esquema Pydantic + modo JSON do LLM) | Accepted | O agente emite uma resposta estruturada validada por Pydantic via modo JSON do LLM em vez de prosa livre, de modo que os avaliadores de recusa / escalonamento leiam campos explícitos em vez de inferir intenção a partir do texto. |
| ADR-0020 | Recuperação de documento pai (chunking de subcartão, citação em nível de cartão) | Accepted | Os cartões de KB são divididos em passagens de subcartão para embedding/recuperação e, em seguida, deduplicados de volta para o cartão pai para citação, melhorando o recall enquanto mantém as citações em nível de cartão. |
| ADR-0021 | Streaming de tokens (stream customizado do LangGraph + cliente de streaming) | Accepted | Deltas de LLM por token são transmitidos para a SPA pela superfície SSE existente (ADR-0009), de modo que a mensagem do assistente seja renderizada enquanto é gerada, em vez de após um buffer de resposta completa. |
| ADR-0022 | Recuperação híbrida (BM25 + densa + RRF + rerank com cross-encoder) | Accepted | A recuperação somente densa é substituída por um pipeline de três estágios condicionado por flag - geradores léxico (BM25) + denso em paralelo, fusão por reciprocal-rank e, em seguida, rerank com cross-encoder - degradando graciosamente para o caminho denso anterior. |
| ADR-0023 | Medição de recall de recuperação (recall@k / hit@k / nDCG@k) | Accepted | A qualidade da recuperação é medida diretamente com recall@k / hit@k / nDCG@k contra cartões relevantes rotulados, desacoplando a pontuação de recuperação de métricas acopladas à geração, como cobertura de citação. |
| ADR-0024 | Enriquecimento de citação no lado do servidor | Accepted | O modelo Citation ganha source_url, source_license e retrieved_score opcionais, enriquecidos no lado do servidor no nó de encerramento, de modo que o popover de citação da SPA renderize sem um segundo ida e volta à KB. |
| ADR-0025 | Provedor de reranking gerenciado e determinismo de avaliação | Accepted | O reranking é transferido para um reranker gerenciado fora da caixa resolvido por turno (gerenciado quando há uma chave da Voyage, senão local), degradando para apenas-fusão em qualquer queda; o portão de avaliação offline permanece sem store, determinístico e gratuito. |
| ADR-0026 | Trava de design da calibração do juiz | Accepted | O portão de concordância humano-vs-juiz congela seu enquadramento, bins, limiar e corpus antes de rotular qualquer caso, mede um kappa de Cohen com ponderação linear por dimensão (portão agrupado, diagnósticos por locale) e só permite reequilibrar o corpus - nunca ajustar o limiar - ante um paradoxo de kappa. |
| ADR-0027 | Reequilíbrio do corpus de calibração | Accepted | O corpus de calibração é composto para discriminar - ponderado ao limítrofe, paralelo entre locales e diverso em defeitos - após um painel especialista constatar que um corpus saturado nos polos rende um kappa quase circular e não informativo; aplica a única alavanca aberta da trava de design com cada constante de integridade congelada. |
| ADR-0028 | Correção do construto de fidelidade | Accepted | A fidelidade é re-especificada como um construto de somente contradição - desvinculado da fundamentação, que fica com as adições não apoiadas - e recalibrada por um painel às cegas com as constantes congeladas intactas, para que humano e juiz meçam a mesma coisa. |
| ADR-0029 | Pontuador de fidelidade por rubrica | Accepted | O pontuador de fidelidade de produção é substituído por um pontuador por rubrica do juiz que lê o cartão citado completo e pontua a contradição ou violação de suas regras de comportamento explícitas, para que os dois lados da calibração meçam o mesmo construto; o juiz não muda. |
| ADR-0030 | Portão de calibração consultivo por padrão | Accepted | O portão de calibração cabeado é entregue consultivo por padrão - um caminho de corpus não definido pula em verde (registrado), a aplicação é uma adesão explícita do operador que dispara e passa como está provado - para que uma dimensão honestamente no limite nunca se torne um CI permanentemente vermelho, com o limiar e os bins congelados nunca como alavanca. |
| ADR-0031 | Calibração com portão de escalonamento e autolesão | Accepted | Escalonamento e autolesão se somam ao portão humano-vs-juiz como bloqueadores duros do lançamento - um portão de revalidação que falha ante uma concordância de segurança ausente, obsoleta para a cadeia ativa, de uma única classe ou abaixo do limiar - enquanto as dimensões de qualidade conservam o pulo consultivo; nenhuma constante congelada se move e o juiz fica intacto. |
| ADR-0032 | Correção do construto da rubrica de autolesão | Accepted | A rubrica de autolesão é re-especificada com portão de presença - primeiro pergunta se o turno carrega um sinal de autolesão (interpretado amplamente) e não confere crédito em um turno benigno nem em uma emergência que não é de autolesão - refletindo a âncora-ausente de escalonamento e revalidada sobre um conjunto reservado, com os rótulos humanos e as constantes congeladas sem alteração. |
| ADR-0033 | Portão da faixa de lançamento restrito às dimensões exigidas | Accepted | Na faixa de aplicação do lançamento o portão falha em duro só sobre as dimensões de segurança exigidas; as dimensões não de segurança ficam consultivas-e-reportadas ali, e o portão geral não muda - para que o veredito de lançamento gire sobre o sinal de segurança, sem mover nenhum limiar nem enfraquecer nenhum controle de segurança. |
| ADR-0034 | Piso de escalonamento cego à negação, ratificado | Accepted | O piso de emergência determinístico e sempre ativo é intencionalmente cego à negação - um sinal de alarme negado ou hipotético mesmo assim escala (recall acima de precisão) - e qualquer mudança nele deve re-passar um portão de paridade de recall e uma prova de piso sem juiz, para que um caso nunca possa ser descartado em silêncio. |
| ADR-0035 | Inversão fail-safe do juiz de escalonamento | Accepted | O juiz semântico de escalonamento é a única barreira que falha em direção ao escalonamento - cada tempo limite, erro, fora-do-esquema ou desfecho malformado escala - rodando atrás do piso determinístico (combinado por conjunção, sem nunca estreitá-lo) com um prior enviesado ao recall, um tempo limite duro limitado sem retentativas em linha, e a calibração empírica diferida. |
| ADR-0036 | Política limitada de redação de nomes | Accepted | O redator determinístico de PII cobre só identificadores estruturados (e-mail, telefone, IDs nacionais incluídos RUT/CPF/DNI, cartão, MRN, data de nascimento, endereço, com dígito verificador) e exclui intencionalmente os nomes de pessoas por taxa de falsos positivos e por dados somente sintéticos; uma passagem ativa de nomes condicionada por configuração é a melhoria nomeada e diferida para uma implantação com dados reais. |