Guardian validator — anti-inversão de argumentos¶
LLMs às vezes trocam os argumentos ao chamar a tool. Exemplo real:
PARTICULAR é convênio, US ABDOME TOTAL é procedimento. O modelo
inverteu. O Clinfeto tem um guardião que detecta e corrige.
Implementação (Clinfeto)¶
# agendamento.py:294-367 (CLINFETO)
_PROCEDURE_KEYWORDS = [
"US ", "USG", "OBSTETRICA", "TIREOIDE", "JOELHO", "DOPPLER",
"TRANSVAGINAL", "ENDOVAGINAL", "MORFOLOGICA", "MAMARIA", "PROSTATA",
"ABDOME", "MAMA", "TIREOIDE",
]
_CONVENIO_NAMES = {_normalize(v) for v in CONVENIOS.values()}
def guardian_validate(nome_convenio: str, nome_procedimento: str) -> tuple[str, str]:
"""Se LLM inverteu convenio/procedimento, corrige.
Returns: (nome_convenio_corrigido, nome_procedimento_corrigido)
"""
conv_norm = _normalize(nome_convenio)
proc_norm = _normalize(nome_procedimento)
conv_parece_proc = any(kw in conv_norm for kw in _PROCEDURE_KEYWORDS)
proc_parece_conv = proc_norm in _CONVENIO_NAMES
if conv_parece_proc and proc_parece_conv:
logger.info("Guardian: invertendo convenio<->procedimento")
return nome_procedimento, nome_convenio
return nome_convenio, nome_procedimento
Heurística¶
Dois sinais simultâneos precisam acender:
- O campo
nome_conveniocontém palavra típica de procedimento (ex:"US "). - O campo
nome_procedimentoé exatamente um dos nomes de convênio conhecidos.
Só aí o guardião inverte. Uma condição sozinha não é suficiente — risco de falso positivo é alto.
Onde plugar¶
No início de toda função pública exposta ao agente:
def consultar_horarios_workflow(payload: dict) -> str:
nome_medico = payload.get("nome_medico", "")
nome_procedimento = payload.get("nome_procedimento", "")
nome_convenio = payload.get("nome_convenio", "")
nome_convenio, nome_procedimento = guardian_validate(nome_convenio, nome_procedimento)
# ... resto do fluxo
Quando adicionar um guardian¶
Só quando você observar o problema em produção. Não crie guardiões preventivos — eles mascaram bugs reais do prompt e criam magia.
Se o LLM ficar invertendo:
- Primeiro tente corrigir no prompt (descrição da tool + exemplos).
- Se persistir, adicione guardian com logs que deixem claro quando dispara.
Outros guardiões possíveis¶
Nenhum outro foi implementado hoje, mas padrões observáveis:
- Data vs hora invertidos: cliente pede
data="14:30",hora="2026-04-15". Detecção: regex ISO vs regex hora. - CPF no lugar do telefone: ambos são números, mas CPF tem 11 dígitos e telefone internacional 12-13.
- Nome do médico com "DR" / "DRA" no início: normalização simples removendo prefixos já resolve.
Log é obrigatório¶
Quando guardian dispara, logue com nível INFO (não ERROR — é um
comportamento esperado e tratado):
logger.info("Guardian: invertendo convenio<->procedimento (%r <-> %r)",
nome_convenio, nome_procedimento)
Ajuda a monitorar se o prompt está ficando ruim / se o modelo novo regrediu.