Governança de alertas (combate à fadiga)
A SauBit emite alertas clínicos determinísticos (clinical_alerts) além das interações
fármaco-fármaco. Em ambientes reais, o excesso de alertas leva à fadiga: o profissional
passa a ignorar avisos — inclusive os críticos. A governança de alertas permite que cada
organização ajuste o que é exibido sem nunca alterar a verdade clínica.
Princípios de segurança
- Supressão é apresentação, não diagnóstico. Um alerta suprimido da lista visível
continua contando para o
prescription_risk_level. A governança nunca rebaixa o risco da prescrição. - Risco crítico não pode ser ocultado. Alertas no nível
confirm_min_severityou acima (padrão:CONTRAINDICADO) são sempre exibidos e marcados comrequires_confirmation: true— nenhuma regra de política consegue suprimi-los. - Toda supressão é auditável. Cada item suprimido carrega o motivo (
suppression_reason) e, em overrides de alertas conhecidos, a justificativa textual registrada.
Campos na resposta
Cada item de clinical_alerts expõe:
| Campo | Descrição |
|---|---|
id | Identificador estável do alerta (independente da ordem dos fármacos). Use para suprimir/justificar alertas conhecidos. |
requires_confirmation | true quando o alerta exige confirmação explícita antes de prosseguir. |
E a resposta ganha o bloco alert_governance:
"alert_governance": {
"applied": true,
"policy_enabled": true,
"view": "pharmacist",
"unit": "icu",
"min_severity": "MODERADO",
"confirm_min_severity": "CONTRAINDICADO",
"requires_confirmation": true,
"confirmation_required_ids": ["drug_allergy-1a2b3c4d5e"],
"total_alerts": 4,
"visible_count": 2,
"suppressed_count": 2,
"suppressed": [
{
"type": "food_alcohol",
"severity": "LEVE",
"id": "food_alcohol-9f8e7d6c5b",
"suppression_reason": "below_min_severity",
"justification": ""
}
]
}
Motivos de supressão (suppression_reason):
| Motivo | Significado |
|---|---|
below_min_severity | Abaixo do nível mínimo de gravidade configurado. |
suppressed_type | Tipo de alerta suprimido pela política (global ou por unidade). |
policy_override | Alerta conhecido suprimido com justification registrada. |
out_of_view | Fora da visão do papel (ex.: drug_disease na visão de farmacêutico). |
Visões por papel (médico × farmacêutico)
Envie o header X-SauBit-Alert-View (ou o query param ?alert_view=) com medico ou
farmaceutico:
curl -X POST https://api.saubit.com.br/api/v1/interactions/check \
-H "X-API-Key: sm_live_..." \
-H "X-SauBit-Alert-View: farmaceutico" \
-H "Content-Type: application/json" \
-d '{ "medications": [ { "name": "ibuprofeno" } ], "patient_record": { "conditions": ["insuficiência renal"] } }'
medico— vê todos os tipos de alerta.farmaceutico— vê os alertas operacionais/de dispensação (alergia, duplicidade, dose máxima, compatibilidade IV, fármaco × lab, ajuste renal/hepático); alertas de raciocínio diagnóstico (ex.:drug_disease) saem da lista comout_of_view.
Alertas críticos são sempre exibidos, independentemente da visão.
Segurança do papel: quando a API key tem um papel vinculado (definido pelo admin —
physician/pharmacist), ele é autoritativo e o headerX-SauBit-Alert-Viewé ignorado (não pode escalar privilégio). O header só vale como preferência de apresentação quando a key não tem papel vinculado. A supressão é apenas de exibição e nunca rebaixa o risco — mas o papel autêntico deve vir da identidade, não de um header livre.
Unidade hospitalar
A unidade é inferida de patient_context.setting (ex.: "UTI", "Pediatria",
"Oncologia") e normalizada para um tag (icu, pediatrics, oncology, emergency,
obstetrics). Uma política pode definir regras específicas por unidade.
Política (por organização / API key)
A política é um objeto JSON configurado por organização (com override por API key). Campos:
| Campo | Tipo | Efeito |
|---|---|---|
enabled | bool | Quando false, vira pass-through (mantém apenas a confirmação crítica). |
min_severity | LEVE·MODERADO·GRAVE·CONTRAINDICADO | Suprime alertas abaixo do limiar. |
confirm_min_severity | idem | Gravidade a partir da qual exige confirmação (padrão CONTRAINDICADO). |
suppressed_types | lista | Tipos de alerta sempre suprimidos (ex.: ["food_alcohol"]). |
suppressed_signatures | lista | Overrides de alertas conhecidos: { "signature": "<id>", "justification": "...", "expires_at"?: "ISO 8601" }. Com expires_at, o override expira e o alerta volta a aparecer. |
unit_rules | objeto | Override por unidade: { "UTI": { "min_severity": "GRAVE" } }. |
role_types | objeto | Tipos visíveis por papel: { "pharmacist": ["drug_allergy", "max_dose"] }. |
Exemplo de política:
{
"enabled": true,
"min_severity": "MODERADO",
"confirm_min_severity": "CONTRAINDICADO",
"suppressed_types": ["food_alcohol"],
"unit_rules": {
"UTI": { "min_severity": "GRAVE" },
"Pediatria": { "suppressed_types": [] }
},
"suppressed_signatures": [
{ "signature": "duplicate_therapy-1a2b3c4d5e", "justification": "Protocolo institucional aprovado pela CCIH" }
]
}
Configuração (rotas administrativas)
A política é configurada por rotas administrativas (JWT de admin, sob /api/v1/admin/*),
com a política da API key tendo precedência sobre a da organização. Como são rotas de
administração, elas são documentadas no Swagger Admin (/docs/admin), separadas das rotas
de hospital — incluindo GET/PUT/DELETE …/organizations/{org_id}/alert-governance e
…/api-keys/{key_id}/alert-governance.
Entradas inválidas (gravidade fora do conjunto, tipo de alerta desconhecido, override sem
justification) retornam 422. Os valores são normalizados (ex.: min_severity em
maiúsculas, unidade convertida para tag).
Propagação: a autenticação por API key é cacheada por ~60s; alterações de política passam a valer em até 60 segundos (o override por key invalida o cache imediatamente).
Métrica: alertas que mudaram a conduta
O indicador-chave da governança não é "quantos alertas foram gerados", e sim quantos mudaram a conduta clínica. Para medir isso, o cliente registra a decisão tomada sobre cada alerta exibido.
Memória de decisões (a organização "ensina" o sistema, sem mudar a decisão clínica)
Cada decisão registrada alimenta uma memória por organização:
- No
check, o mesmo alerta (mesma assinaturaid) volta comdecision_history— quantas vezes foi reconhecido, sobreposto ou modificado, a taxa de sobreposição e a última justificativa. Isso ajuda o prescritor a ver a conduta local, sem rebaixar severidade, suprimir nada nem alterar oprescription_risk_level. - No chat (
/chat/messagecomanalysis_id) e no MCP, o histórico entra no contexto como um bloco explicitamente rotulado "memória institucional — não é evidência clínica". - Sugestões de governança: quando um alerta é sobreposto repetidamente com a mesma razão,
a plataforma gera sugestões de supressão por assinatura para o administrador aprovar.
Nada é aplicado automaticamente; alertas
CONTRAINDICADOnunca são candidatos. Rota administrativa (Swagger Admin):GET /admin/organizations/{org_id}/alert-governance/suggestions.
Por que não "aprender sozinho"? Um sistema de apoio à decisão que altera seu próprio comportamento com base em overrides aprenderia a silenciar alertas (fadiga de alerta) e deixaria de ser um algoritmo travado e auditável. A memória é contexto; a decisão continua determinística e versionada.
Auto-alimentação por organização
Cada decisão informativa (com justificativa, prescrição modificada ou conduta alterada) realimenta automaticamente a própria organização — e só ela:
- Base de conhecimento da organização (RAG do tenant). A decisão vira um documento curto, sem dados do paciente (justificativa passa por remoção de PII), indexado na base vetorial exclusiva da organização — a mesma que o chat dela consulta. Perguntas como "como costumamos lidar com AINE em nefropata?" passam a recuperar as decisões registradas pela própria instituição. Reconhecimentos sem justificativa não são indexados (ruído).
- Perfil de conduta. Um resumo agregado (volume, taxa de sobreposição, tipos de alerta mais sobrepostos e justificativa típica) entra no contexto de todo chat da organização, rotulado como memória institucional, não evidência.
- Datasets de treinamento versionados. Com o consentimento formal registrado, a plataforma gera snapshots imutáveis (JSONL anonimizado, contagem de linhas e SHA-256) — sob demanda e automaticamente toda semana — para ajuste offline dos modelos de texto (resumo e chat). Cada rodada de ajuste pode citar exatamente o dataset usado (rastreabilidade do dossiê).
Limites fixos: nada disso alcança o motor determinístico; o isolamento é por organização; a exportação/geração fica desativada por padrão e exige consentimento por organização. Rotas administrativas (Swagger Admin): consentimento, geração, listagem e download dos snapshots.
Registrar uma decisão
POST /api/v1/interactions/alerts/decision (autenticação por API key, escopo
interactions:check):
curl -X POST https://api.saubit.com.br/api/v1/interactions/alerts/decision \
-H "X-API-Key: sm_live_..." \
-H "Content-Type: application/json" \
-d '{
"analysis_id": "a1b2c3...",
"alert_id": "drug_disease-1a2b3c4d5e",
"decision": "modified",
"changed_conduct": true,
"justification": "Trocado por alternativa segura na gestação"
}'
| Campo | Descrição |
|---|---|
analysis_id | Id da análise (check/recheck) que gerou o alerta. |
alert_id | O id do alerta em clinical_alerts. |
decision | acknowledged (ciente, manteve), overridden (sobrepôs) ou modified (alterou a conduta). |
changed_conduct | true se o alerta efetivamente mudou a prescrição/conduta. |
justification | Obrigatória quando decision = "overridden". |
O servidor valida que a análise pertence à organização e preenche alert_type/severity a
partir da análise armazenada.
Consultar a métrica
A consulta agregada (changed_conduct_rate = fração de decisões em que o alerta mudou a
conduta, além de recortes por tipo/gravidade) é uma rota administrativa e está no
Swagger Admin (/docs/admin): GET …/organizations/{org_id}/alert-metrics. As decisões
registradas acima também alimentam o Dashboard/ROI administrativo.