Como usar o Jev para escolher qual ação de remediação rodar quando um serviço cai?

O Jev é o modelo System One da TypeSafe AI: você manda um state e perguntas tipadas, ele devolve resposta tipada com probabilidades e confiança, sem gerar texto livre. Para remediação, cada runbook conhecido vira uma opção de um Choice (até 255 opções, mais uma de escape), e métricas, logs e estado do deploy entram como state em JSON. A resposta traz a opção escolhida, a distribuição de probabilidades e um confidence de 0 a 1. É esse confidence que separa o que roda sozinho do que para na aprovação humana, com piso sugerido de 0.6.
Fala aí, beleza? Três da manhã, o alerta dispara, o serviço tá fora e existem cinco runbooks possíveis na sua wiki
Restart do pod, rollback do último deploy, escalar réplicas, drenar a fila, ou simplesmente esperar porque é o provedor que tá com problema
Quem decide isso hoje é o plantonista, no olho, com sono, lendo três dashboards ao mesmo tempo 😅
O Jev entra exatamente aí, e ele NÃO é um chatbot que escreve um textão dizendo o que você deveria fazer
Ele é o modelo System One da TypeSafe AI: recebe um state mais perguntas tipadas e devolve respostas tipadas, com probabilidade de cada opção e um número de confiança
Ou seja: modelo de decisão tipada, não de geração de texto
Isso muda tudo pra automação de incidente, porque uma decisão tipada você consegue colocar dentro de um if sem parser, sem regex, sem rezar pro JSON vir bem formado
Bora montar isso na prática?
O que você precisa antes de começar
Antes do código, o de sempre: acesso, chave e ambiente
- Conta com chave de API da TypeSafe. Aqui tem um detalhe importante de estado atual: a TypeSafe abriu cadastro direto pra todo mundo em 20/09/2026, com US$ 5 de crédito, e pausou novos cadastros no
console.typesafe.aiem 22/09/2026. Quem já tem conta segue funcionando normal, e eles disseram que trabalham pra reabrir. Até hoje (24/09/2026) não saiu anúncio de reabertura, então se você não pegou a janela, fica de olho - Node 20 ou mais novo, se for pelo SDK JavaScript:
npm install @typesafe-ai/sdk. Ele lê a chave da variável de ambienteTYPESAFE_API_KEYe chamajev-latestpor padrão - Ou nada disso, e você bate direto no endpoint:
POST https://api.typesafe.ai/v1/systemone, com headerAuthorization: BearereContent-Type: application/json. É isso, é uma requisição HTTP comum
Curso de Jev: Sistemas Mais Inteligentes, Rápidos e Robustos
Desenvolva sistemas mais inteligentes, rápidos e robustos com Jev
Tem ainda a agent skill oficial, que empacota o contexto da API (as três primitivas, padrões e boas práticas) pro seu agente não chutar a forma do payload
No Claude Code:
claude plugin marketplace add typesafe-ai/skills
claude plugin install typesafe@typesafe-ai
Em outros agentes:
npx skills add typesafe-ai/skills --skill typesafe-ai
Repara que o identificador muda de um comando pro outro, e isso confunde geral: no Claude Code você instala o plugin typesafe vindo do marketplace typesafe-ai, nos outros agentes você pede a skill typesafe-ai de dentro do repo typesafe-ai/skills
É o mesmo conteúdo, só muda o nome que cada produto usa pra se referir a ele, então copie o comando do SEU produto e não tente adaptar o do outro
E se você precisa de rota alternativa: o typesafe/jev-1.13 e o jev-latest estão listados na OpenRouter, e lá dentro tem um provedor só servindo esses modelos, a própria TypeSafe
Fora da OpenRouter, o Jev também aparece no catálogo de modelos da Cloudflare AI, que é outra porta de entrada
Sobre custo, é curioso: o Jev cobra só por token de entrada, US$ 0,042 por 1 milhão de tokens de input, e output custa US$ 0,00
Faz sentido quando você lembra que a saída dele é uma opção e alguns floats, não um textão 🙂
Passo a passo: da lista de runbooks à decisão de remediação
A ideia central é simples: o seu runbook vira opção, o seu monitoring vira state
1. Transforme cada runbook conhecido em uma opção
A primitiva aqui é o Choice: escolhe uma opção de um conjunto
Um Choice aceita até 255 opções, o que é MUITO mais do que qualquer wiki de runbook saudável tem, então espaço não é o seu problema
O que importa é a descrição de cada opção ser específica e não pisar na descrição da vizinha
{
"restart_service": "Reiniciar as instâncias do serviço. Use quando o processo está vivo mas travado, sem relação com deploy recente",
"rollback_deploy": "Voltar para a versão anterior. Use quando a falha começou depois de um deploy nas últimas horas",
"scale_replicas": "Aumentar o número de réplicas. Use quando há saturação de CPU ou memória com tráfego acima do normal",
"drain_queue": "Drenar a fila de mensagens acumuladas. Use quando o backlog da fila é a causa da lentidão",
"upstream_wait": "Nenhuma ação local. Use quando a falha vem de dependência externa fora do seu controle",
"none_of_the_above": "Nenhuma das opções acima descreve a situação"
}
Repara nessa última: a doc recomenda incluir uma opção de escape tipo other ou none of the above sempre que a lista pode não cobrir todo input
Incidente é o exemplo perfeito de lista que não cobre tudo, porque sempre aparece um jeito novo de quebrar
O erro comum deste passo: descrições sobrepostas. Se "restart" e "rollback" ambos dizem "use quando o serviço não responde", você não deu ao modelo o que diferencia uma da outra, e a probabilidade vai se espalhar entre as duas. Se quiser ver a dinâmica de escolha entre opções em um cenário mais visual, tem esse post sobre a demo de navegação do Jev
2. Monte o state com métrica, log e estado do deploy
O state pode ser texto simples ou dado estruturado (objeto ou array), tipo o estado atual da sua aplicação
Pra incidente, estruturado é bem melhor, porque você consegue apontar a pergunta pra um pedaço específico depois
{
"service": "checkout-api",
"alert": {
"name": "HighErrorRate",
"fired_at": "2026-09-24T03:12:00Z"
},
"metrics": {
"error_rate_pct": 47.2,
"p99_latency_ms": 8300,
"cpu_pct": 31,
"memory_pct": 62,
"queue_backlog": 12
},
"deploy": {
"last_deploy_minutes_ago": 18,
"version": "2026.09.24-a1",
"changed_services": ["checkout-api"]
},
"logs": [
"ERROR payment_gateway: connection reset by peer",
"ERROR payment_gateway: connection reset by peer",
"WARN retry budget exhausted for payment_gateway"
]
}
Repara que eu já mandei error_rate_pct e queue_backlog calculados
Isso não é preguiça de formatar, é regra: a doc do jev-1.13 diz explicitamente que o modelo não conta de forma confiável e que o erro cresce com o tamanho do que se conta
Então a conta fica no seu código, e pro modelo vai o resultado
O erro comum deste passo: despejar 4 mil linhas de log cru achando que "mais contexto é melhor". A acurácia do jev-1.13 cai quando o state cresce com conteúdo irrelevante pra decisão, e ainda tem o orçamento de contexto: a doc fala em 64k cobrindo o state mais todas as perguntas somadas, e 32k pro state mais a pergunta mais longa. Mande a amostra que decide, não o arquivo inteiro
Curso RecomendadoDesenvolva sistemas mais inteligentes, rápidos e robustos com JevConhecer curso3. Escreva instructions e criteria sem contradição
Cada pergunta é um objeto com type, instructions e criteria
E aqui tem uma limitação documentada que muda a forma de escrever: o Jev lê a pergunta ao pé da letra. Escopo, negação e condição implícita são lidos literalmente
Então nada de "escolha a ação, exceto se não for o caso de não reiniciar" kkk
Frase direta, afirmativa, um objetivo só
A doc também orienta apontar a pergunta pra um valor específico do state usando caminho com pontos e índices entre crases, tipo metrics.error_rate_pct ou logs[0]
O erro comum deste passo: instruction dizendo uma coisa e criteria dizendo outra. Se a instruction fala "priorize a ação menos arriscada" e a descrição do rollback fala "use sempre que houver deploy recente", você criou um conflito, e critérios contraditórios confundem o modelo
4. Monte o body e dispare
O corpo tem três campos no topo: state, model e questions
curl -X POST https://api.typesafe.ai/v1/systemone \
-H "Authorization: Bearer $TYPESAFE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"state": { "service": "checkout-api", "metrics": { "error_rate_pct": 47.2 } },
"model": "jev-latest",
"questions": {
"runbook": {
"type": "choice",
"instructions": "Escolha a ação de remediação mais adequada para o incidente descrito em `state`, considerando `metrics`, `deploy` e `logs`",
"criteria": {
"restart_service": "Reiniciar as instâncias do serviço. Use quando o processo está vivo mas travado, sem relação com deploy recente",
"rollback_deploy": "Voltar para a versão anterior. Use quando a falha começou depois de um deploy nas últimas horas",
"scale_replicas": "Aumentar o número de réplicas. Use quando há saturação de CPU ou memória com tráfego acima do normal",
"drain_queue": "Drenar a fila de mensagens acumuladas. Use quando o backlog da fila é a causa da lentidão",
"upstream_wait": "Nenhuma ação local. Use quando a falha vem de dependência externa fora do seu controle",
"none_of_the_above": "Nenhuma das opções acima descreve a situação"
}
}
}
}'
O model aceita jev-latest (o padrão do SDK e dos exemplos da doc) ou IDs versionados tipo jev-1.13.0
Se você quer previsibilidade em produção, versionado é o caminho, porque aí o comportamento não muda debaixo de você numa madrugada de plantão
5. Leia a opção, a distribuição e o confidence
A resposta de um Choice traz três coisas: a opção escolhida, a probabilidade de cada opção (floats que somam 1) e um confidence entre 0 e 1 derivado dessa distribuição
E a resposta vem uma por pergunta, na mesma chave que você definiu lá no mapa questions
const res = await fetch("https://api.typesafe.ai/v1/systemone", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.TYPESAFE_API_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({ state, model: "jev-1.13.0", questions })
})
const resultado = await res.json()
const decisao = resultado["runbook"] // confira o formato exato da resposta na doc da API
console.log(decisao.confidence)
O detalhe que muita gente ignora: a distribuição é tão útil quanto a opção vencedora
Um caso em que rollback_deploy ganhou com margem folgada é muito diferente de um caso em que rollback e restart ficaram empatados tecnicamente
No segundo, a decisão é "o modelo não sabe", e é isso que o confidence vai te dizer
Como combinar várias perguntas numa requisição só
O campo questions é um mapa, e a doc mostra que dá pra fazer perguntas diferentes (inclusive de primitivas diferentes) numa única requisição
Pra remediação isso é ouro, porque "qual ação" sozinha não basta
1. Pergunte qual runbook (Choice)
É a pergunta que você já montou ali em cima, com as opções e a de escape
2. Pergunte a gravidade (Score)
O Score dá uma nota numa rubrica de níveis ordenados, com mínimo de 2 e máximo de 10 níveis
Quatro níveis costumam resolver bem a vida de um pipeline de incidente:
"severidade": {
"type": "score",
"instructions": "Classifique a gravidade do impacto no usuário final com base em `metrics` e `alert`",
"criteria": {
"baixa": "Degradação sem impacto perceptível para o usuário",
"media": "Parte das requisições falha, existe caminho alternativo",
"alta": "Funcionalidade principal indisponível para boa parte dos usuários",
"critica": "Serviço totalmente indisponível ou com risco de perda de dados"
}
}
3. Pergunte se a evidência basta (Noul)
O Noul é sim/não numa escala de 0 a 1
Perfeito pra uma pergunta de porteiro:
"evidencia_suficiente": {
"type": "noul",
"instructions": "A evidência em `logs` e `metrics` é suficiente para identificar a causa da falha?",
"criteria": {
"sim": "Os dados apontam uma causa provável de forma consistente",
"nao": "Os dados são insuficientes ou contraditórios"
}
}
4. Cruze as três antes de encostar em qualquer botão
A lógica de cruzamento fica no SEU código, não no prompt:
const acao = resultado["runbook"]
const sev = resultado["severidade"]
const evidencia = resultado["evidencia_suficiente"]
const podeAgirSozinho =
acao.confidence >= 0.8 &&
evidencia.confidence >= 0.8 &&
acoesAutomaticas.includes(acao.answer)
O erro comum deste bloco: empurrar o state inteiro pra todas as perguntas. A doc orienta dar a cada pergunta só o contexto de que ela precisa e manter junto o que precisa ser comparado. A pergunta de gravidade não precisa do histórico de deploy, por exemplo
Roteamento por confiança: quais ações rodam sozinhas e quais param na aprovação humana
Agora o ponto sensível, e é aqui que a maioria das automações de remediação se estrepa

Crie sistemas com IA para vender
Prompts, modelos e checklists para criar e publicar seu sistema com IA e preparar a oferta para o primeiro cliente.
Quero o e-book gratuito Receba o livro e os bônus no seu e-mail.A TypeSafe documenta esse padrão de forma bem seca: a resposta diz o quê, a confiança diz se pode agir sozinho
Caso incerto vai pra uma pessoa ou pra um modelo de raciocínio mais caro
O exemplo da própria doc é literalmente isso:
if (answer.confidence < 0.8) {
await enviarParaPlantonista(answer)
} else {
await handlerAutomatico(answer)
}
E tem duas orientações que valem mais que o snippet
A primeira é o piso: a doc sugere 0.6 como piso pra pegar o que o modelo está genuinamente incerto
Abaixo disso, nem discute, é humano
A segunda é que acima do piso, cada tipo de ação tem seu próprio limiar, conforme a consequência de errar
E é MUITO diferente errar um restart e errar um rollback de banco, né?
| Ação | Reversível? | Custo de errar | Quem decide |
|---|---|---|---|
| Restart do serviço | sim, em segundos | baixo | pode ser automática |
| Escalar réplicas | sim | baixo, custa dinheiro | pode ser automática |
| Drenar fila | parcialmente | médio | automática com limiar alto |
| Rollback de deploy | sim, mas mexe em tráfego real | médio a alto | confirmação humana |
| Rollback de banco | não | altíssimo | sempre humano, sem exceção |
Repara na última linha: ação destrutiva e irreversível não entra na régua de confiança
Não existe confidence alto o bastante pra restaurar um banco sozinho às 3 da manhã, e isso não é medo da IA, é a mesma regra que você já aplica pros rm -rf da vida
A sua lista de ações automáticas é uma allowlist explícita no código, nunca "tudo que o modelo escolher"
O erro comum aqui: usar um único limiar global pra tudo. Se você põe 0.8 e aplica pra restart e pra rollback, ou você está frouxo demais no rollback ou rígido demais no restart
O segundo erro comum: nunca validar o limiar. A doc recomenda testar plotando confiança contra acurácia nos seus próprios dados, e é isso que transforma o número de chute em decisão de engenharia
Cenários de incidente em que esse padrão se encaixa bem
A TypeSafe lista, como caso de uso do modelo, priorizar alertas por risco, relevância e qualidade da evidência, e mandar caso ambíguo pra revisão humana
Traduzindo pro seu dia a dia:
- Rajada de alerta: caem 40 alertas em dois minutos e metade é consequência do outro. Um Score de risco por alerta ordena a fila antes do humano abrir o dashboard
- Qual serviço olhar primeiro: Choice entre os serviços envolvidos, com a descrição de cada um explicando quando ele é causa e quando é vítima
- Rollback ou escalar réplicas: a clássica. Saturação com tráfego acima do normal puxa pra réplica, falha começando 18 minutos depois do deploy puxa pra rollback
- Roteamento do caso ambíguo: quando a distribuição fica espalhada, o caso vai direto pro plantonista com a distribuição anexada, que já é um resumo do que o modelo considerou
E a latência ajuda: a TypeSafe reporta 70 ms a 500 ms ponta a ponta
Isso cabe dentro de um pipeline de alerta sem ninguém notar, o que não aconteceria se você mandasse tudo pra um modelo de raciocínio gerar um relatório
Se você ainda tá avaliando onde esse tipo de modelo encaixa melhor no seu produto, dá uma olhada nos casos de uso de automação com o Jev
Erros que derrubam a qualidade da decisão (e como prevenir)
A TypeSafe publica uma página de limitações conhecidas do jev-1.13, e quase todas mordem justamente em contexto de incidente
Contagem: o sintoma é a resposta que muda sozinha
Sintoma: você pergunta "quantos erros apareceram nos últimos 5 minutos" e o número vem errado, e o erro piora quanto mais linha tem
Causa: o modelo não conta de forma confiável, e o erro cresce com o tamanho do que se conta
Ajuste: aritmética no código. Conta você, e manda o resultado pronto no state, como error_count_5m: 143
Data: o sintoma é a ordem cronológica bagunçada
Sintoma: ele não percebe que o deploy veio ANTES do alerta
Causa: o Jev lê data como texto, não como quantidade ordenada
Ajuste: pré-calcule a relação no seu código e mande explícito, tipo last_deploy_minutes_ago: 18 em vez de dois timestamps pro modelo comparar
State inflado: o sintoma é a acurácia caindo conforme você "melhora" o contexto
Sintoma: você adiciona mais log pra ajudar e a decisão piora
Causa: a acurácia cai quando o state cresce com conteúdo irrelevante pra decisão
Ajuste: state enxuto e filtrado. Só o que participa da decisão entra, o resto fica no seu sistema de log mesmo
Negação e condição: o sintoma é o modelo fazendo o oposto do combinado
Sintoma: você escreveu uma regra com "exceto" e ele ignorou o exceto
Causa: escopo, negação e condição implícita são lidos literalmente
Ajuste: perguntas estreitas e afirmativas. Se precisa de condição, quebre em duas perguntas na mesma requisição, que é de graça em termos de round trip
Log hostil: o sintoma é a decisão estranha vinda de um input específico
Sintoma: um log com texto esquisito empurra a escolha pra um lado inesperado
Causa: o state é tratado como dado, não como hostil, então conteúdo adversarial pode mover a resposta
Ajuste: sanitize o que você coloca no state, principalmente log que carrega input de usuário. Trate log como entrada não confiável, do mesmo jeito que você trataria num parser
Critérios em conflito: o sintoma é a distribuição sempre espalhada
Sintoma: nenhuma opção ganha com folga, em nenhum incidente
Causa: instruções e critérios contraditórios confundem o modelo
Ajuste: releia a instruction junto de cada criteria, em voz alta. Se duas descrições servem pro mesmo cenário, funde ou diferencia
Próximo passo: comece com uma decisão só, em modo sombra
O caminho que eu sugeriria pra quem quer levar isso pra produção não é ligar automação no dia um
É rodar em modo sombra: a cada incidente, o Jev responde em paralelo, ninguém age em cima disso, e você guarda a opção escolhida, a distribuição e o confidence junto do que o plantonista realmente fez
Depois de um punhado de incidentes, você tem o dado pra fazer exatamente o que a doc recomenda: plotar confiança contra acurácia e descobrir onde fica o seu limiar de verdade
Aí sim você libera um runbook automático, o mais reversível da lista, geralmente o restart
Depois o segundo, e por aí vai
Rollback destrutivo continua com humano no meio, sempre, mesmo com confidence de 0.99
Sobre acesso: lembrando que os novos cadastros no console da TypeSafe estão pausados desde 22/09/2026, e as contas existentes seguem ativas
Se você já tem chave, a doc da API e a agent skill oficial são a melhor continuação, porque elas carregam os padrões atualizados direto pro seu agente
E se você montar esse fluxo aí no seu on-call, me conta como foi… tenho curiosidade de saber qual runbook você liberaria primeiro 😀
até o próximo post!
Perguntas frequentes
Qual limiar de confiança usar antes de rodar a remediação automática?
São dois números com papéis diferentes, e vale não misturar. O 0.6 é o piso que a doc sugere pra pegar o que o modelo está genuinamente incerto: abaixo disso, vai pra humano sem discussão. Acima do piso, cada tipo de ação tem seu próprio limiar conforme a consequência de errar, e o exemplo da própria doc usa 0.8 como corte (se answer.confidence < 0.8, manda pra revisão humana, senão chama o handler automático). Na prática: use 0.8 como ponto de partida do limiar da sua remediação automática, nunca desça abaixo do piso de 0.6, e valide o número plotando confiança contra acurácia nos seus próprios dados de incidente.
O Jev consegue contar quantos erros aconteceram no log pra decidir a ação?
Não é recomendado. A doc de limitações do jev-1.13 é clara: ele não conta de forma confiável e o erro cresce com o tamanho do que se conta. Por isso o certo é calcular error_rate_pct, queue_backlog e afins no seu código, e mandar só o resultado pronto no state.
Dá pra misturar Choice com Score na mesma chamada de remediação?
Dá sim. O campo questions é um mapa de ids pra objetos de pergunta, e as três primitivas (Choice, Score e Noul) podem dividir a mesma request. Então você pode pedir o Choice da ação de remediação e um Score de severidade no mesmo POST pro endpoint.
Quanto custa rodar o Jev em cada disparo de alerta?
O Jev cobra só por token de entrada, US$ 0,042 por 1 milhão de tokens de input, e o output sai a US$ 0,00. Como um payload de incidente típico (métricas, alguns logs e as opções do Choice) é pequeno perto de 1 milhão de tokens, o custo por decisão fica bem baixo.
O que fazer se eu não peguei a janela de cadastro aberto da TypeSafe?
A TypeSafe abriu cadastro direto no console.typesafe.ai em 20/09/2026 com US$ 5 de crédito e pausou novos cadastros em 22/09/2026. Contas já criadas continuam funcionando normalmente, mas não há anúncio de reabertura até 24/09/2026. Uma alternativa nesse meio tempo é acessar o modelo pela OpenRouter, onde o typesafe/jev-1.13 e o jev-latest estão listados.
Quantos runbooks (opções) eu posso colocar num Choice de remediação?
Uma pergunta Choice aceita até 255 opções, o que cobre folgado qualquer lista de runbooks real. O ponto de atenção não é quantidade, é a doc recomendando sempre incluir uma opção de escape tipo other ou none of the above pra quando o incidente não bater com nenhum runbook conhecido.
Formações
Formação Claude Code
Domine Claude Code do absoluto zero até o avançado
- 120 aulas
- 4 projetos
- 9h 48min
Blog | Mais populares

Como montar um workflow de automação combinando decisões do Jev em código
Aprenda a montar um workflow com Jev: decisões tipadas encadeadas em código, alta confiança agindo sozinha e casos incertos escalando para revisão.

Jev decide, LLM escreve: como dividir os papéis dentro de um agente de IA
Jev é o modelo que decide, não escreve: entenda como dividir papéis entre Jev e LLM dentro de um agente de IA e quando usar cada um.

Para quem o Jev serve (e para quem não serve)?
Jev serve pra roteamento, scoring e guardrails em IA, não pra texto ou código. Veja pra quem o Jev serve e quando evitar.
