Como usar o Jev para decidir quem recebe um feature flag e controlar o rollout progressivo

Diagrama mostrando o Jev feature flag calculando elegibilidade de usuários para rollout progressivo
Resposta rápida

Jev é o primeiro modelo da categoria System One da TypeSafe AI: em vez de gerar texto, ele recebe um estado e devolve valores tipados com probabilidade calibrada. Usar o Jev como motor de feature flag significa trocar a lista fixa de segmentos por uma pergunta tipada sobre o usuário: um Noul devolve um valor entre 0 e 1 para elegibilidade, um Choice escolhe entre ligado, escondido ou variante conservadora. O rollout progressivo vira um limiar nesse valor, que você baixa em degraus conforme mede. Chamada única no endpoint POST https://api.typesafe.ai/v1/systemone, com as perguntas avaliadas em paralelo sobre o mesmo state.

Toda lista fixa de segmentos envelhece mal

Você começa com if (plano === 'pro'), aí entra a exceção do cliente grande, depois o beta group, depois aquele array de e-mails hardcoded que ninguém tem coragem de apagar

Seis meses depois o arquivo de flags virou um monstrinho que só uma pessoa do time entende

O Jev, que a TypeSafe AI apresenta como o primeiro modelo da categoria System One, propõe outra rota: em vez de gerar texto, ele recebe um estado e devolve valores tipados com probabilidade calibrada

Na prática, você para de escrever a regra de quem entra e passa a fazer uma PERGUNTA sobre o usuário, recebendo de volta um número entre 0 e 1 que você usa como corte

Bora ver como isso funciona? 🙂

O que você precisa antes de começar

Pouca coisa, beleza? A lista é curta:

  • Conta na TypeSafe: desde 21/09/2026 não existe mais waitlist, o cadastro é aberto no console.typesafe.ai e vem com US$ 5 de crédito gratuito. Se você está acostumado com lançamento de IA que te joga numa fila de espera para liberar acesso, esse ponto muda bastante o teste inicial
  • Chave de API, que vai no header Authorization: Bearer <chave>
  • Escolher o modelo: jev-latest (alias que aponta pro modelo principal da TypeSafe) ou fixar em jev-1.13, versão publicada em 18 de setembro de 2026
  • Noção da janela de contexto: Jev 1.13 trabalha com 32.000 tokens, e é dentro disso que o estado do usuário precisa caber
  • Ou um gateway, se você já tem um: a OpenRouter lista jev-latest e jev-1.13, e o Vercel AI Gateway expõe o modelo como typesafe-ai/jev

E um aviso que evita frustração logo no começo: Jev não gera texto

Ele não vai te escrever a copy do banner do feature novo, não vai explicar em prosa por que o usuário entrou

Ele devolve valor tipado com probabilidade, e ponto

Os três tipos de pergunta da System One:

A API tem exatamente três formatos, e escolher o certo é metade do trabalho:

Tipo O que devolve Limite Confidence
Choice distribuição de probabilidade entre as opções, somando 1 até 255 opções sim, derivado da distribuição
Score distribuição sobre uma régua ordenada de 2 a 10 níveis sim, derivado da distribuição
Noul um valor entre 0 e 1: a probabilidade da proposição ser verdadeira proposição sim/não não tem campo separado, a própria probabilidade é o sinal

Guarde essa última linha, porque é ela que sustenta o rollout progressivo

Passo a passo: da lista fixa de segmentos à decisão tipada

  1. Monte o state com o estado real do usuário

O campo state é o conteúdo a que todas as perguntas daquela requisição se referem

Ele aceita string simples ou dado estruturado (objeto ou array), tipo registros ou o estado atual da aplicação

{
  "plano": "pro",
  "dias_desde_signup": 214,
  "projetos_ativos": 7,
  "builds_ultimos_30d": 412,
  "tickets_suporte_90d": 1,
  "onboarding_concluido": true,
  "ja_usou_beta_anterior": true,
  "falhas_de_pagamento_12m": 0
}

O erro comum deste passo: mandar só {"plano": "pro"}

Se o state é pobre, a resposta vai ser pobre também, é a mesma lista fixa de segmentos com um custo de API em cima 😛

Coloque o que um humano olharia pra decidir: uso, histórico, maturidade da conta

  1. Escreva a pergunta Noul de elegibilidade

Noul avalia uma proposição sim/não e devolve um número entre 0 e 1

A proposição aqui é algo como "esta conta tem perfil pra receber o novo editor de pipelines sem risco de quebrar o fluxo atual dela"

O erro comum deste passo: escrever proposição vaga, do tipo "este usuário é bom"

Pergunta ambígua devolve probabilidade em cima de 0,5, que não serve de corte pra nada

  1. Escreva a pergunta Choice para a variante

Aqui você define o QUE acontece, não SE acontece: ligado, escondido, variante conservadora

Choice aceita no máximo 255 opções, então três estados é folga total

E lembre que Choice devolve a distribuição de probabilidades entre as opções, somando 1, mais um confidence entre 0 e 1 derivado dessa distribuição

Distribuição concentrada gera confidence maior, distribuição achatada gera confidence menor

O erro comum deste passo: criar opções que se sobrepõem ("ligado", "ligado com aviso", "ligado parcial")

Opção parecida demais achata a distribuição e derruba o confidence

  1. Opcional: um Score de risco

Score usa uma régua ordenada de no mínimo 2 e no máximo 10 níveis

É útil quando você quer graduar (risco de impacto negativo de 1 a 5, por exemplo) em vez de responder sim/não

O erro comum deste passo: montar régua de 10 níveis sem saber diferenciar o nível 6 do 7

Régua grande sem critério claro achata a distribuição do mesmo jeito

  1. Mande tudo num único mapa questions

O campo questions é um mapa de nomes escolhidos por VOCÊ para objetos de pergunta tipada

Todas as perguntas do mapa são avaliadas em uma única ida e volta, e a TypeSafe afirma que o Jev processa em paralelo as perguntas feitas sobre o mesmo estado, em vez de cada resposta depender da anterior

A requisição exige três campos: model, state e questions

POST https://api.typesafe.ai/v1/systemone
Authorization: Bearer <sua-chave>
Content-Type: application/json

{
  "model": "jev-latest",
  "state": { "plano": "pro", "builds_ultimos_30d": 412, "onboarding_concluido": true },
  "questions": {
    "elegivel":  { "type": "noul",   "...": "proposição sim/não" },
    "variante":  { "type": "choice", "...": "ligado | escondido | conservadora" },
    "risco":     { "type": "score",  "...": "régua de 2 a 10 níveis" }
  }
}

O formato exato de cada objeto de pergunta (nomes dos campos internos, como você descreve a proposição e lista as opções) está na documentação da System One API, confere lá antes de colar isso no seu código

O erro comum deste passo: disparar três requisições separadas, uma por pergunta

O mapa existe justamente pra você pagar uma viagem só

  1. Leia o answers e aplique o corte

A resposta traz model, answers e usage

A resposta de um Noul tem a cara disso:

{ "type": "noul", "noul": 0.95 }

E no seu código:

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(payload)
})

const { answers } = await res.json()
const p = answers.elegivel.noul   // valor entre 0 e 1

if (p >= LIMIAR_ATUAL) {
  return 'ligado'
}

O erro comum deste passo: procurar um campo de confidence dentro do Noul

Não existe, e essa é a diferença dele pro Choice e pro Score: a própria probabilidade é o sinal que a aplicação usa

Como usar a probabilidade como corte do rollout progressivo

Agora a parte boa

O rollout percentual clássico sorteia: uma fatia da base hoje, uma fatia maior depois, e o sorteio não sabe NADA sobre quem foi sorteado

Com o valor do Noul em mãos, você inverte a lógica: libera primeiro pra quem tem a maior probabilidade de dar certo, e vai descendo o limiar conforme a coisa se comporta

  1. Comece com o limiar alto

Algo como p >= 0.9

Isso é o seu grupo mais seguro, e no começo você quer erro perto de zero pra conseguir ler os gráficos

  1. Meça antes de mexer

Taxa de erro, tickets, tempo de resposta, conversão dentro do recurso

O limiar só desce quando a faixa atual está estável

  1. Desça em degraus

0.9, depois 0.8, depois 0.65, por aí vai

Cada degrau amplia o alcance sem você escrever regra nova nenhuma no código

  1. Use a variante conservadora na faixa intermediária

É aqui que o Choice brilha

Em vez de um corte seco entre ligado e desligado, a faixa do meio cai numa versão com menos superfície de risco: limites menores, menos concorrência, sem o botão destrutivo

function decidir(answers) {
  const p = answers.elegivel.noul

  if (p >= 0.9) return 'ligado'
  if (p >= 0.65) return 'conservadora'
  return 'escondido'
}

Por que dá pra confiar nesse limiar?

A TypeSafe treina os modelos System One com um método chamado RLCD (Reinforcement Learning for Calibrated Decisions)

A propriedade pretendida é que as probabilidades representem incerteza de verdade: grupos de previsões com probabilidade maior acertam com mais frequência que grupos com probabilidade menor

Sem isso, limiar não significa nada

Com isso, o número 0.9 vira uma alavanca com sentido: mover ela pra baixo aumenta alcance e aumenta erro, de forma previsível

O erro comum aqui: tratar a probabilidade como score arbitrário, tipo "0.7 é um sete de dez", e ir mudando o limiar no feeling porque a semana estava tranquila

Se você não mede a faixa antes de liberar a próxima, você não tem rollout progressivo, você tem um chute com JSON bonito

Outro ponto pra ser honesto: a documentação da TypeSafe não descreve usar a probabilidade do Noul como percentual de rollout

Isso é decisão de arquitetura de quem implementa, e você deve tratá-la como tal

Casos de uso: onde esse tipo de flag faz diferença

  • Recurso pesado só pra conta com uso compatível: aquele export gigante, o modo colaborativo em tempo real, a build paralela. Em vez de amarrar no plano, o state carrega volume real de uso e o Noul responde se a conta aguenta
  • Esconder feature nova de quem está em onboarding: usuário de três dias que ainda não achou o menu principal não precisa de mais uma novidade na tela. O onboarding_concluido e o tempo de conta entram no state e a decisão sai pronta
  • Cair na variante conservadora quando o histórico pede cautela: conta com falha de pagamento recente, com pico de tickets, com integração instável. O Choice manda pra versão reduzida em vez de mandar pro tudo ou nada
  • Rollout por coorte sem escrever regra nova a cada exceção: esse é o alívio principal. A exceção entra no state, não num if novo
  • Kill switch com critério: em vez de derrubar pra 100% da base quando o alerta toca, você sobe o limiar de volta pra 0.95 e mantém ligado só onde está seguro

E repare que é exatamente o mesmo formato de raciocínio de quem usa decisão tipada para priorizar leads: muda o state e muda a pergunta, a mecânica é idêntica

Custo, latência e cache: o que pensar antes de colocar em produção

  1. Chame no lugar certo

Login, início de sessão, abertura do workspace

NÃO a cada render de componente, não dentro de um loop de lista

  1. Cacheie a decisão

Guarde o resultado por usuário com um TTL que faça sentido pro seu produto, e só recalcule quando o state mudar de verdade (upgrade de plano, mudança grande de uso)

  1. Tenha um valor padrão quando a chamada não volta

Se a decisão não chegou, o app precisa saber o que fazer sem ela

O comportamento oficial de fallback e a política de retry da API não estão documentados publicamente, então trate isso como responsabilidade sua do lado do cliente

  1. Olhe os números de referência antes de estimar

O preço listado do Jev 1.13 é US$ 0,042 por milhão de tokens de entrada e US$ 0,00 por milhão de tokens de saída

A TypeSafe estima que uma decisão média custa cerca de US$ 0,0004 nos benchmarks dela

E os números de lançamento apontam latência ponta a ponta de 70 a 500 milissegundos

Mesmo na ponta boa dessa faixa, 500 ms dentro de um render é tempo suficiente pra estragar a percepção de velocidade do seu app

O erro comum deste passo: pendurar a chamada na requisição HTTP que pinta a tela

Resolve tudo, funciona no dev com um usuário, e derrete quando cem pessoas abrem o dashboard ao mesmo tempo 😀

Problemas comuns e como resolver

Probabilidade sempre travada no meio da escala

Sintoma: praticamente todo usuário volta com valor entre 0,45 e 0,55

Causa: state pobre ou proposição ambígua. O modelo não tem como separar quem é quem

Solução: enriqueça o state com sinais que realmente diferenciam (uso, histórico, maturidade) e reescreva a proposição pra ser verificável, com critério explícito

Como prevenir: antes de codar, pergunte se um colega do suporte conseguiria responder sim/não olhando só pro JSON que você está mandando. Se ele não consegue, o Jev também não vai

Confidence baixo no Choice

Sintoma: a distribuição fica espalhada entre as opções e o confidence vem lá embaixo

Causa: opções parecidas demais entre si. Distribuição achatada gera confidence menor, é assim que o número é derivado

Solução: reduza o número de variantes e deixe cada uma com um comportamento claramente distinto

Como prevenir: trate o limite de 255 opções como teto técnico, não como convite. Três variantes bem separadas decidem melhor que oito quase iguais

State grande demais

Sintoma: você resolve mandar o histórico completo da conta e a requisição não cabe

Causa: a janela do Jev 1.13 é de 32.000 tokens, e log bruto come isso rapidinho

Solução: mande agregados em vez de eventos crus. builds_ultimos_30d: 412 diz mais em menos espaço que 412 objetos de build

Como prevenir: monte uma função de resumo do usuário e use ela sempre, em vez de serializar o objeto inteiro que veio do banco. Já vi gente jogar SELECT * num state e se perguntar por que ficou caro

Decisão instável entre chamadas

Sintoma: o mesmo usuário vê o recurso hoje e não vê amanhã

Causa: state mutável. Se você inclui coisa que muda a cada minuto, a decisão muda junto

Solução: separe o que é estrutural (plano, maturidade, uso agregado no mês) do que é volátil, e alimente a flag só com o estrutural. Some a isso o cache por usuário, que é o que realmente segura a estabilidade

Como prevenir: persista a decisão tomada junto com o timestamp e o limiar vigente. Assim você consegue auditar depois por que fulano entrou no rollout, e a experiência dele não oscila enquanto a faixa não muda

Tome cuidado com um detalhe: a documentação não confirma se o Jev é determinístico nem se existe parâmetro de seed ou cache oficial

Ou seja, a estabilidade por usuário é você quem garante, guardando a decisão do seu lado

Vídeo: contexto sobre a onda atual de modelos

Pra quem quer entender o momento em que essa categoria de modelo apareceu, este vídeo do canal coloca os modelos grandes de hoje lado a lado e mostra como eles se comportam em comparação direta

Bom ponto de partida antes de mergulhar em API

Conclusão e próximo passo

O ganho aqui não é usar IA em feature flag porque é bonito no slide

É parar de manter uma lista fixa de segmentos que cresce a cada exceção, e passar a fazer uma pergunta tipada sobre o usuário, com um número entre 0 e 1 servindo de corte que você desce em degraus

Menos if aninhado, mais critério explícito

O próximo passo prático é bem pequeno: cria a conta no console, pega a chave, monta o state de UM usuário real da sua base e roda uma pergunta Noul

Compara o que voltou com o que a sua regra atual decidiria pra esse mesmo usuário

Se as duas concordam, ótimo sinal

Se discordam, você acabou de achar o caso que a sua lista fixa não sabia tratar 🙂

E só DEPOIS dessa comparação você mexe no rollout de verdade

até o próximo post!

Perguntas frequentes

Quanto custa rodar uma decisão de feature flag com o Jev?

O Jev 1.13 cobra US$ 0,042 por milhão de tokens de entrada e US$ 0,00 por milhão de tokens de saída. A própria TypeSafe estima, nos benchmarks dela, que uma decisão média sai em torno de US$ 0,0004. Como o state e as perguntas cabem na janela de 32.000 tokens, o custo por avaliação de rollout tende a ficar bem baixo.

O Jev consegue escrever o texto do banner ou aviso do feature novo?

Não. O Jev é um modelo de decisão tipada, não um gerador de texto: ele recebe um state e devolve valores tipados com probabilidade calibrada. Pra copy do banner, você precisa de outro modelo, o Jev entra só na hora de decidir quem vê o quê.

Dá pra combinar Noul, Choice e Score na mesma chamada de rollout?

Sim. O campo questions é um mapa de nomes escolhidos por você, e todas as perguntas daquele mapa são avaliadas em uma única ida e volta. A TypeSafe afirma que o Jev processa essas perguntas em paralelo sobre o mesmo state, então dá pra pedir elegibilidade (Noul), variante (Choice) e risco (Score) de uma vez.

Qual a latência esperada do Jev pra não travar o carregamento da feature?

Os números de lançamento da TypeSafe apontam latência ponta a ponta entre 70 e 500 milissegundos. É essa faixa que dá pra usar como referência ao decidir se a chamada roda antes de renderizar a tela ou em paralelo com outra coisa.

É possível usar o Jev fora da API própria da TypeSafe?

Sim, o modelo também está em gateways. A OpenRouter lista jev-latest e jev-1.13, e o Vercel AI Gateway expõe o modelo como typesafe-ai/jev, então dá pra encaixar num projeto que já usa um desses gateways.

Ainda existe lista de espera pra testar o Jev antes de colocar no rollout?

Não. A TypeSafe removeu a waitlist do Jev em 21 de setembro de 2026, e o cadastro agora é aberto direto no console.typesafe.ai, com US$ 5 de crédito gratuito pra você testar as perguntas antes de plugar no seu sistema de flags.




Escrito por | Matheus Battisti

Matheus Battisti
Fundador da Hora de Codar

Programador apaixonado pelo mundo das tecnologias, sempre buscando em aprender e se aprofundar em linguagens, frameworks e o que mais for necessário para executar um bom trabalho. Agora tem uma nova missão que é de passar seu conhecimento adiante para formar novos programadores e especializar mais os que já são.

Subscribe
Notify of
guest

0 Comentários
Oldest
Newest Most Voted

Formações

Formação Claude Code

Formação Claude Code

Domine Claude Code do absoluto zero até o avançado

  • 120 aulas
  • 4 projetos
  • 9h 48min

Blog | Mais populares