Metodologia de Confidence
Toda decisão de roteamento que a Floopy toma carrega um campo confidence — a crença auto-reportada do roteador de que sua escolha principal é a correta para o tráfego desta organização agora. Esta página explica exatamente como esse número é calculado, o que cada confidence_reason significa e por que null às vezes é a resposta honesta.
O que confiança é e o que não é
Seção intitulada “O que confiança é e o que não é”Confiança é uma heurística, não uma probabilidade. Uma confiança de 0.78 não significa “78% de chance de o roteador estar correto” — significa “os inputs que o roteador tem sobre este candidato (gap para o vice, contagem de amostras, variância de outcome) são mais fortes que os inputs na maioria das decisões recentes desta org”.
Expomos confiança para que clientes possam construir filas de revisão, alertas e a constraint confidence_threshold em cima de um sinal explícito — não para que ela seja tratada como uma probabilidade de correção.
A confiança é calculada inteiramente a partir dos inputs da própria organização requisitante (seus candidatos, suas contagens de amostras, sua variância). Ela não vaza informação cross-tenant.
Fórmula
Seção intitulada “Fórmula”gap_norm = clamp(gap_top2 / GAP_REF, 0.0, 1.0) GAP_REF = 0.20n_norm = clamp(log1p(n_samples) / log1p(N_REF), 0.0, 1.0) N_REF = 30var_norm = 1.0 - clamp(variance / VAR_REF, 0.0, 1.0) VAR_REF = 0.25
raw = W_GAP*gap_norm + W_N*n_norm + W_VAR*var_norm W_GAP = 0.45, W_N = 0.35, W_VAR = 0.20
if phase == Day0: return min(raw, CAP_DAY0) // 0.6if used_shared_pool_prior == true: return min(raw, CAP_SHARED) // 0.8return raw| Input | Source | Meaning |
|---|---|---|
gap_top2 | score_top1 − score_top2 em RoutingAudit.candidates | Quão à frente está o vencedor. |
n_samples | janela rolante sobre o log de requisições para o vencedor | Quanto tráfego real respalda a escolha. |
variance | variância rolante de outcome do vencedor (qualidade composta) | Quão estáveis têm sido os outcomes observados. |
phase | Fase do Feedback-Driven: Day0, Auto, Nps | Maturidade dos dados da org. |
used_shared_pool_prior | boolean na auditoria | Se priors cross-tenant influenciaram o score. |
Por que esses pesos?
Seção intitulada “Por que esses pesos?”W_GAP = 0.45— uma separação clara entre os dois principais candidatos é a evidência mais direta de que a decisão de roteamento não é cara ou coroa.W_N = 0.35— a contagem de amostras importa, mas com forte retorno decrescente (note olog1p). Ir de 5 para 50 amostras te diz muito; ir de 500 para 5000 te diz menos.W_VAR = 0.20— estabilidade de outcome é um sinal confirmatório, não um sinal principal. Variância baixa com gap empatado ainda é confiança baixa.
Esses pesos são estáticos e não configuráveis pelo cliente na v1.
Os dois caps
Seção intitulada “Os dois caps”CAP_DAY0 = 0.6 — o cap de Day-0
Seção intitulada “CAP_DAY0 = 0.6 — o cap de Day-0”Quando a organização está na fase Day0 do Feedback-Driven (ainda sem feedback de NPS, apenas sinais automatizados), a fórmula pode calcular qualquer valor raw, mas a confiança retornada é capada em 0.6.
Por quê: em Day-0, por definição, não há sinal validado por usuário final. O roteador pode rankear candidatos bem, mas até que o feedback de uso real esteja no loop, “alta confiança” seria enganoso. O cap é uma forcing function: um cliente que quiser ver confiança acima de 0.6 precisa completar a rampa de cold-start.
CAP_SHARED = 0.8 — o cap de prior do pool compartilhado
Seção intitulada “CAP_SHARED = 0.8 — o cap de prior do pool compartilhado”Quando a decisão de roteamento utilizou priors cross-tenant (used_shared_pool_prior == true), a confiança retornada é capada em 0.8.
Por quê: priors cross-tenant são por definição menos confiáveis que outcomes do próprio tenant. Capar em 0.8 reflete isso honestamente. O cap foi revisado e aceito na revisão de segurança (SEC-020 na Credibility & Auditability Initiative) — o boolean cross-tenant em si é exposto na auditoria, mas os priors subjacentes nunca são expostos.
Você pode identificar decisões influenciadas pelo pool compartilhado por:
- O campo
used_shared_pool_prior: truena auditoria, e - O header HTTP
Floopy-Aggregation-Notice: contains-shared-pool-influenced-decisionsemGET /v1/export/decisions, e - O
aggregation_signal_present: truedo trailer.
Enum confidence_reason
Seção intitulada “Enum confidence_reason”Toda decisão carrega um confidence_reason para que o cap ou caso de borda seja explícito, não implícito.
| Value | Meaning |
|---|---|
ok | A fórmula retornou raw e nenhum cap foi aplicado. |
cap_day0 | Retornou raw, depois clampeou para CAP_DAY0 = 0.6. A org está na fase Day-0. |
cap_shared | Retornou raw, depois clampeou para CAP_SHARED = 0.8. A decisão usou um prior do pool compartilhado. |
no_router_invoked | Nenhum roteador rodou para esta requisição — confidence é null. Cache hit, caminho de legacy-model, ou outro short-circuit. |
insufficient_samples | n_samples < N_MIN (default 3) e a org está além do Day-0. O score é raw * 0.5 para amortecer uma fórmula apressada com poucos dados. |
single_candidate | Apenas um candidato foi considerado — gap_top2 é indefinido, então a confiança é null. |
Quando confidence é null
Seção intitulada “Quando confidence é null”null é um valor de primeira classe e válido. Significa “nenhum roteador foi invocado para esta requisição” — por exemplo:
- A resposta foi servida do cache (
outcome.cache_hit == true). - O caminho de parsing de legacy-model assumiu porque nenhuma regra de roteamento se aplicou.
- Uma regra de roteamento de candidato único fez short-circuit do scoring de candidatos.
Trate confiança null como “não audite esta linha buscando uma decisão de qualidade de roteamento — não houve uma”. Se você filtrar min_confidence > 0 em GET /v1/decisions, linhas null são excluídas por design.
Exemplos calculados
Seção intitulada “Exemplos calculados”| Cenário | gap_top2 | n_samples | variance | phase | shared | confidence | confidence_reason |
|---|---|---|---|---|---|---|---|
| Alta confiança, maduro | 0.18 | 100 | 0.05 | Nps | false | 0.917 | ok |
| Baixa confiança, empatado | 0.01 | 100 | 0.05 | Nps | false | 0.532 | ok |
| Day-0, prior perfeito | 0.20 | 0 | nenhuma | Day0 | false | 0.45 | ok |
| Day-0, raw máximo | 0.20 | 30 | 0.0 | Day0 | false | 0.6 | cap_day0 |
| Amostras insuficientes | 0.18 | 1 | nenhuma | Auto | false | 0.27 | insufficient_samples |
| Cache hit | n/a | n/a | n/a | n/a | n/a | null | no_router_invoked |
| Candidato único | n/a | 50 | 0.05 | Nps | false | null | single_candidate |
| Prior compartilhado | 0.18 | 30 | 0.05 | Auto | true | 0.8 | cap_shared |
Estes casos são exercitados pela suíte de testes de confiança do gateway — eles são o contrato.
Forward-only — sem backfill
Seção intitulada “Forward-only — sem backfill”confidence e confidence_reason são populados em toda decisão da data de deploy em diante. Linhas anteriores à data de deploy têm confidence == null e confidence_reason == null. Escolhemos isso em vez de um backfill porque reconstruir n_samples, variance e phase para decisões históricas estaria errado mais frequentemente do que ajudaria — e um número errado de confiança é pior que nenhum número.
Como usar
Seção intitulada “Como usar”- Como fila de revisão:
GET /v1/decisions?max_confidence=0.5retorna as decisões de roteamento que você deve revisar primeiro. - Como alerta: acompanhe a fração de decisões na sua janela com
confidence < 0.6. Um salto geralmente significa que o formato do tráfego da org mudou, não que a Floopy piorou. - Como constraint de roteamento:
PUT /v1/constraintscomconfidence_threshold: 0.7faz o roteador cair para a baseline sempre que a confiança cair abaixo do threshold. Candidatos filtrados carregamreason: "constraint_confidence_below_threshold".
Evidence — o que o router sabia, exposto
Seção intitulada “Evidence — o que o router sabia, exposto”No v2 toda decisao que passa pelo router Feedback-Driven ou Smart-Cost carrega um bloco evidence ao lado de confidence e confidence_reason. Evidence e o pequeno conjunto de entradas que produziu o numero de confianca, exposto para que voce possa auditar o raciocinio, nao apenas o veredito.
Os cinco campos
Seção intitulada “Os cinco campos”| Campo | Tipo | Significado |
|---|---|---|
samples | integer | A contagem rolante de amostras n_samples sobre o vencedor. Mesmo numero que alimenta o termo n_norm na formula. |
top2_score_gap | number | O gap de score entre o vencedor e o segundo colocado (gap_top2). Mesmo numero que alimenta gap_norm. |
outcome_variance | number | A variancia rolante de resultados sobre o vencedor, na escala de qualidade composta. Mesmo numero que alimenta var_norm. |
recent_regressions | tagged union | Contagem bucketizada de alertas de regressao sobre o (provider, model) do vencedor nos ultimos 7 dias. Veja abaixo. |
last_regression_at | ISO8601 | null | Timestamp da regressao mais recente na janela de 7 dias, arredondado para o multiplo de 5 minutos mais proximo. null quando nao ha regressao na janela. |
Quando nenhum router foi invocado (cache hit, candidato unico, amostras insuficientes para a estrategia), o campo evidence e ausente — null e um valor de primeira classe, igual a confidence.
recent_regressions e bucketizado, nao uma contagem bruta
Seção intitulada “recent_regressions e bucketizado, nao uma contagem bruta”O campo recent_regressions e uma tagged union com dois formatos:
{ "kind": "exact", "exact": 3 }{ "kind": "at_least", "at_least": 10 }{ "kind": "at_least", "at_least": 50 }Os limites dos buckets estao fixados no gateway:
| Contagem bruta | Bucket emitido |
|---|---|
0..=9 | Exact { exact: n } |
10..=49 | AtLeast { at_least: 10 } |
>= 50 | AtLeast { at_least: 50 } |
Os buckets comprimem um sinal de evento de regressao em escala de frota em uma forma de 3 buckets. Eles preservam “tem algo errado com meu modelo?” — qualquer contagem exata diferente de zero ou qualquer AtLeast dispara o ramo “regression_detected” no endpoint de verificacao — sem vazar volumes precisos que poderiam ser correlacionados entre tenants.
last_regression_at arredondado em 5 minutos
Seção intitulada “last_regression_at arredondado em 5 minutos”O timestamp da regressao mais recente e arredondado para baixo no multiplo de 5 minutos mais proximo antes de sair do gateway. Uma regressao disparada em 2026-05-07T14:32:18Z e reportada como 2026-05-07T14:30:00Z. O arredondamento existe pelo mesmo motivo do bucketing: sinal suficiente para investigar, resolucao insuficiente para usar como side-channel.
A janela de 7 dias
Seção intitulada “A janela de 7 dias”recent_regressions e last_regression_at sao calculados sobre uma janela rolante de 7 dias. A janela e fixa e nao e configuravel pelo cliente no v2.
A consulta e org-scoped: o gateway busca alertas de regressao cujo organization_id corresponde a organizacao chamadora, com join no (provider, model) do vencedor. Nao ha agregacao cross-tenant nesse caminho.
Semantica null-safe
Seção intitulada “Semantica null-safe”Cada campo de evidence segue regras null-safe:
evidenceem si e ausente (naonull) em linhas onde nenhum router foi invocado.last_regression_atenullquando a janela de 7 dias nao tem regressoes, mesmo com o restante deevidencepopulado.- Um lookup de regressao falho (timeout no PostgREST, erro transitorio) renderiza
recent_regressions: { "kind": "exact", "exact": 0 }elast_regression_at: null— fail-safe para “nenhuma regressao observada”, com uma metrica incrementada no lado do gateway para sabermos com que frequencia isso acontece. A decisao nao e bloqueada por um lookup de regressao.
A consulta da janela de 7 dias tem timeout duro de 150 ms e cache Redis positivo-e-negativo (TTL 60 s). A latencia da decisao fica limitada; o sinal de regressao fica atualizado.
Evidence na auditoria, nao no score
Seção intitulada “Evidence na auditoria, nao no score”Evidence e explicativo, nao load-bearing. O numero confidence e calculado das mesmas entradas (gap, samples, variance) mais os caps de phase e used_shared_pool_prior; recent_regressions nao alimenta confidence diretamente. Expomos evidence para que um revisor possa ler a linha de auditoria e ver com o que o router estava trabalhando — do mesmo jeito que o texto de explicacao recita os mesmos numeros em prosa simples.
Veja também
Seção intitulada “Veja também”GET /v1/decisions/{request_id}— decisão única, incluindoconfidenceeconfidence_reason.- GET /v1/decisions — listagem com filtros
min_confidence/max_confidence. - PUT /v1/constraints — defina
confidence_threshold. - POST /v1/routing/explain — pré-visualize a confiança que uma requisição candidata carregaria.