01
O SLI de atendimento não é uptime, e essa é a parte difícil
Em um serviço de infraestrutura o indicador é direto: a requisição respondeu com sucesso dentro do prazo ou não. Em atendimento automatizado essa definição não cobre quase nada do que importa. O bot pode responder em duzentos milissegundos, com status 200, e ter dado uma resposta completamente errada. Do ponto de vista de disponibilidade, foi um sucesso. Do ponto de vista do cliente, foi uma falha pior do que uma indisponibilidade honesta, porque ele agiu com base numa informação incorreta.
Por isso o SLI precisa ser composto por sinais de qualidade, não só de resposta. Na prática funciona bem definir um evento bom como a conversa que teve primeira resposta dentro do prazo, não foi marcada como resposta errada pelo cliente, e não escalou para humano por falha do bot. Repare no qualificador na última condição: escalar porque o assunto exige um humano é o comportamento correto e não pode contar como falha, senão o sistema aprende a não escalar nunca, que é exatamente o oposto do desejado.
A segunda decisão difícil é o denominador. Toda conversa entra na conta? Não. A conversa que o cliente abandonou antes da primeira resposta não mede qualidade do bot, e incluí-la dilui o indicador com ruído. Mas cada exclusão precisa de justificativa escrita e revisão, porque a lista de exclusões é a porta dos fundos mais fácil para maquiar o número: basta ir marcando como não elegível tudo que ficou ruim.
// sli.js
// Um SLI de atendimento so vale se contar eventos elegiveis, nao todos.
// Conversa cancelada pelo cliente antes da primeira resposta nao e falha
// do bot: incluir isso no denominador dilui o sinal e esconde regressao.
// Motivos que tiram a conversa da conta. Cada exclusao precisa de
// justificativa escrita, senao vira porta dos fundos para maquiar o numero.
const NOT_ELIGIBLE = new Set([
'client_abandoned_before_first_reply', // saiu antes de o bot poder agir
'spam_or_test', // trafego sintetico
'out_of_business_hours_by_policy', // fora do escopo contratado
]);
export function isEligible(conversation) {
return !NOT_ELIGIBLE.has(conversation.exclusionReason);
}
// Bom evento: resolvida sem escalonamento indevido, dentro do prazo,
// e sem que o cliente tenha marcado a resposta como errada.
export function isGood(conversation, { maxFirstReplyMs = 30000 } = {}) {
if (conversation.firstReplyMs > maxFirstReplyMs) return false;
if (conversation.wrongAnswerReported) return false;
if (conversation.escalatedBecauseBotFailed) return false;
return true;
}
// SLI = bons eventos elegiveis / total de eventos elegiveis.
export function computeSli(conversations, options) {
const eligible = conversations.filter(isEligible);
if (eligible.length === 0) return null; // sem trafego nao ha sinal
const good = eligible.filter((c) => isGood(c, options)).length;
return { sli: good / eligible.length, eligible: eligible.length, good };
}Vale a pena começar com um SLI só. É tentador definir cinco indicadores no primeiro dia, mas cada um deles precisa de alvo, de alerta e de revisão periódica, e um time que não consegue manter um SLI honesto não vai manter cinco. Comece pelo que o cliente sente primeiro, tipicamente resposta correta dentro do prazo, e só adicione outro quando o primeiro estiver estável e confiável.