Como usar o Jev para um assistente de voz decidir se responde agora ou espera o usuário terminar?

O Jev num assistente de voz não escuta áudio, então ele não decide quando a pessoa parou de falar: quem faz isso é o seu STT em streaming, tipo o Deepgram Flux com eot_threshold. O papel do Jev é o outro, decidir o que fazer com o turno que acabou de chegar: responder agora, esperar, pedir esclarecimento ou escalar. Você manda um state (trecho transcrito, pausa, últimos turnos) e um lote de perguntas tipadas na mesma requisição, lê choice, probabilities e confidence, e roteia por limiar. Nos cookbooks da TypeSafe, lotes assim ficaram na casa de 111 a 114 ms de ida e volta
Assistente de voz que responde cedo demais atropela a pessoa
E assistente que espera demais soa travado, aquele silêncio esquisito onde o usuário já começou a repetir a frase achando que a ligação caiu
Esse é o problema de turn-taking, e ele não é um problema só de áudio: metade dele é decisão
O Jev é o primeiro modelo público da TypeSafe AI e inaugura o que eles chamam de System One models: em vez de gerar texto, ele avalia um state e devolve respostas tipadas com probabilidades
Isso encaixa MUITO bem num pipeline de voz, onde você não tem tempo de esperar um LLM escrever um parágrafo pra depois parsear
Mas já aviso antes de você se empolgar: o Jev não enxerga áudio
Ele decide sobre texto ou JSON, e quem diz "a pessoa parou de falar" continua sendo o seu STT
Bora separar isso direito?
O que o Jev faz (e o que ele não faz) numa conversa por voz
O Jev tem três tipos de pergunta, as primitivas: Choice, Score e Noul
Toda pergunta tem id, tipo e instructions
Choice e Score aceitam criteria (as opções ou os níveis), e o Noul aceita criteria como esclarecimento opcional do que é sim e do que é não
As respostas de Choice e Score carregam um confidence entre 0 e 1, derivado da distribuição de probabilidade da resposta
O Choice ainda devolve a opção escolhida em choice e a probabilidade de cada opção em probabilities, e um Choice aceita até 255 opções
O Noul devolve um valor numérico entre zero e um
A parte que salva sua latência: o state vai no campo state da requisição junto com o mapa questions, e todas as perguntas enxergam o MESMO state
O Jev ingere esse state uma vez e avalia as perguntas em paralelo, em vez de fazer cada resposta depender da anterior
Ou seja, você não precisa de quatro chamadas pra saber quatro coisas do mesmo turno
É a mesma mecânica de lote que aparece quando o Jev é usado pra detectar jailbreak antes do LLM responder, só que aqui o state é uma conversa por voz em andamento
Curso de Jev: Sistemas Mais Inteligentes, Rápidos e Robustos
Desenvolva sistemas mais inteligentes, rápidos e robustos com Jev
Duas camadas, não uma
Separa mentalmente assim:
- "A pessoa parou?" é camada de áudio, resolvida por endpointing (Deepgram Flux, Smart Turn e afins)
- "E agora, o que eu faço?" é camada de decisão, e é aí que o Jev entra
Se você tentar usar o Jev pra adivinhar fim de fala, vai dar ruim: ele não recebe forma de onda, não sabe que a pessoa respirou fundo pra continuar a frase
No projeto de referência que existe hoje pra isso, quem encerra o turno a partir do áudio é o Flux, e o Jev cuida só do ramo da conversa
O que você precisa antes de começar
Antes do código, o checklist:
- Conta ativa na TypeSafe, e aqui tem um detalhe chato: a empresa abriu o Jev pra todo mundo em 20 de setembro de 2026 e pausou novos cadastros em 22 de setembro de 2026 por excesso de demanda
- Contas já criadas seguem funcionando, e eles dizem que trabalham pra reabrir, sem data anunciada até agora
- Se você não tem conta, dá pra chegar no modelo por intermediários: existe página do provider Typesafe no OpenRouter e o Jev também está listado na documentação de modelos da Cloudflare
TYPESAFE_API_KEYna variável de ambiente, que é de onde o SDK lê a chave- SDK Python com
pip install typesafe-sdk(ouuv add typesafe-sdk), exigindo Python 3.10 ou superior, ou SDK JavaScript comnpm install @typesafe-ai/sdk, pedindo Node.js 20 ou mais novo - Um STT em streaming que emita evento de fim de turno, porque sem isso não existe gatilho pra chamar o Jev
- Um TTS pra falar a resposta escolhida
O endpoint de avaliação é POST https://api.typesafe.ai/v1/systemone, com Authorization: Bearer e corpo JSON
No campo model você usa o alias jev-latest ou um ID versionado, tipo jev-1.13.0
Se for pelo OpenRouter, dá pra apontar o SDK oficial pra lá ou chamar pela Decisions API, que não é o endpoint de chat completions (não adianta jogar um cliente de chat em cima)
Passo a passo: da fala do usuário à decisão de responder ou esperar
- Configure o detector de fim de turno no STT
No Deepgram Flux (endpoint /v2/listen), o parâmetro eot_threshold define a confiança necessária pra disparar o evento EndOfTurn
Ele aceita valores de 0.5 a 0.9 e o padrão é 0.7
Valor mais alto reduz falso positivo (menos atropelo) com um pouquinho mais de latência, e 1.0 suprime a detecção natural de fim de turno
# parâmetros do Flux (/v2/listen)
eot_threshold = 0.8 # faixa 0.5 a 0.9, padrão 0.7, 1.0 desliga a detecção natural
eager_eot_threshold = 0.5 # faixa 0.3 a 0.9, habilita EagerEndOfTurn e TurnResumed
O erro comum deste passo: tentar resolver endpointing com o Jev
Ele não ouve áudio, ponto
- Monte o state com o que é decisão, não com o dump da conversa
O state é o retrato do turno que acabou de fechar: trecho transcrito, quanto durou a pausa, qual evento do STT chegou, os últimos turnos e onde você está no roteiro
O orçamento de contexto é de 64k cobrindo state mais todas as perguntas somadas, e de 32k pra state mais a pergunta mais longa
Parece muito, mas histórico bruto de uma ligação de dez minutos come isso rapidinho
O erro comum deste passo: jogar a transcrição inteira da chamada dentro do state
Resuma o histórico e mande só os turnos recentes
- Escreva as perguntas em lote, na mesma requisição
Um Choice pro ramo da conversa, dois Nouls (a pessoa respondeu o que foi perguntado? ela quer falar com humano?) e um Score de clareza
Esse é exatamente o desenho do projeto de referência: uma única chamada ao Jev por turno com quatro perguntas
Curso RecomendadoDesenvolva sistemas mais inteligentes, rápidos e robustos com JevConhecer curso{
"model": "jev-latest",
"state": {
"ultimo_trecho": "quero mudar o endereco de entrega do meu pedido",
"pausa_ms": 480,
"evento_stt": "EndOfTurn",
"turnos_recentes": [
{"agente": "pode me confirmar o numero do pedido?"},
{"usuario": "e o 4821, mas antes"}
],
"passo_do_roteiro": "confirmar_pedido",
"transcricao_suspeita": true
},
"questions": {
"branch": {
"type": "choice",
"instructions": "o agente acabou de receber um fim de turno. escolha a proxima acao",
"criteria": {
"responder_agora": "o turno esta completo e ja da pra avancar o roteiro",
"esperar": "a frase parece cortada no meio, a pessoa provavelmente vai continuar",
"pedir_esclarecimento": "o trecho esta ambiguo ou a transcricao nao faz sentido",
"escalar_humano": null
}
},
"answered": {
"type": "noul",
"instructions": "o usuario respondeu a ultima pergunta do agente?"
},
"escalating": {
"type": "noul",
"instructions": "o usuario pediu para falar com um atendente humano?"
},
"clarity": {
"type": "score",
"instructions": "quao clara esta a intencao do usuario neste turno",
"criteria": {
"baixa": "transcricao truncada ou sem sentido",
"media": "da pra entender mas cabe mais de uma leitura",
"alta": "intencao explicita e sem ambiguidade"
}
}
}
}
O erro comum deste passo: quebrar isso em quatro requisições encadeadas, uma esperando a outra
As perguntas são independentes e rodam em paralelo sobre o mesmo state, encadear só multiplica round-trip
- Chame o Jev uma vez por turno
import os
import requests
resp = requests.post(
"https://api.typesafe.ai/v1/systemone",
headers={
"Authorization": f"Bearer {os.environ['TYPESAFE_API_KEY']}",
"Content-Type": "application/json",
},
json=payload,
timeout=2,
)
answers = resp.json()
Do Choice você lê três coisas: choice (a opção), probabilities (a probabilidade de cada opção) e confidence (0 a 1)
O formato completo da resposta está na doc da API, o que importa aqui é que esses três campos são o seu material de roteamento
- Aplique o portão de confiança e roteie
Nada de confiar cegamente no choice
A regra é: se a confiança não bater o limiar, você não executa o ramo, você cai numa fala de esclarecimento
No projeto de referência o limiar do ramo começa em 0.65 e sobe pra 0.75 quando a transcrição vem marcada como suspeita, ou seja, quando alguma palavra do Flux ficou abaixo de GATE_MIN_WORD_CONFIDENCE (0.6)
Quem faz esse acréscimo é o GATE_SUSPECT_PENALTY (0.1)
GATE = 0.65
GATE_SUSPECT_PENALTY = 0.1
GATE_MIN_WORD_CONFIDENCE = 0.6
def rotear(branch, palavras_do_stt):
limiar = GATE
if any(p["confidence"] < GATE_MIN_WORD_CONFIDENCE for p in palavras_do_stt):
limiar += GATE_SUSPECT_PENALTY # vira 0.75
if branch["confidence"] < limiar:
return "pedir_esclarecimento"
return branch["choice"]
O erro comum deste passo: tratar confidence como enfeite de log
Ele é o botão que decide se o agente age ou pergunta de novo
- Use os eventos do STT pra ganhar tempo e pra parar de falar
Definir eager_eot_threshold (valores válidos entre 0.3 e 0.9) habilita os eventos EagerEndOfTurn e TurnResumed
A orientação da Deepgram é rascunhar a resposta no EagerEndOfTurn e cancelar o rascunho quando chegar TurnResumed, que indica que a pessoa voltou a falar
E pra barge-in, o caminho recomendado é o StartOfTurn, porque todo StartOfTurn vem com transcrição não vazia
O erro comum deste passo: rascunhar e esquecer de cancelar
Aí o agente fala por cima da pessoa que só tinha dado uma pausa pra respirar 😅
Como transformar confiança em decisão: limiares que fazem sentido
Os números que dão chão pra isso vêm do jev-voice-agent, um agente de voz em tempo real publicado na conta dg-coreylweathers no GitHub, sem LLM no loop: o Flux encerra o turno, o Jev escolhe a resposta e todas as falas possíveis estão escritas por humano em src/script.ts
Lá, qualquer palavra devolvida pelo Flux com confiança abaixo de GATE_MIN_WORD_CONFIDENCE (0.6) marca a transcrição como suspeita
Transcrição suspeita eleva a barra de confiança do ramo em GATE_SUSPECT_PENALTY (0.1), saindo de 0.65 pra 0.75
Quando o portão não é atendido, o agente cai na fala de esclarecimento escrita no script
Sacou a lógica? Áudio ruim não vira decisão errada, vira pergunta
Por que limiar funciona aqui
O paper JEV-as-a-Judge descreve o Jev como calibrado: quando o modelo diz probabilidade 0.8, o rótulo de referência concorda em torno de 80% das vezes

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.O mesmo paper descreve uma cascata que aceita o veredito confiante e escala o incerto, mantendo 99% da acurácia do comparador com custo menor
É a mesma ideia de aceitar o confiante e escalar a dúvida que aparece quando o Jev é usado pra qualificar e priorizar leads, só que aqui a "escalada" é falar mais uma frase, não abrir um ticket
Três cenários concretos
- Alta confiança em "responder_agora":
confidence0.91, nenhuma palavra suspeita, limiar 0.65 - O agente executa o ramo e o TTS já dispara a fala do script
- Confiança baixa por transcrição ruim: o Flux entregou duas palavras com confiança 0.4, a transcrição vira suspeita e o limiar sobe pra 0.75
- O Choice veio com
confidence0.7, ou seja, passaria no portão normal e NÃO passa no portão penalizado - Resultado: fala de esclarecimento, e ninguém confirma um endereço errado
- Ramo de escalar pra humano: o Noul de "quer falar com atendente" veio alto e o Choice escolheu
escalar_humanocom confiança acima do limiar - Transferência, sem mais rodeios
Jev, Deepgram Flux e Smart Turn: quem resolve qual parte
Muita gente lê isso como concorrência, e não é
São camadas diferentes do mesmo pipeline
| Peça | O que observa | O que devolve | Onde roda | Custo |
|---|---|---|---|---|
| Deepgram Flux | áudio em streaming (/v2/listen) |
transcrição e eventos de turno (StartOfTurn, EagerEndOfTurn, TurnResumed, EndOfTurn), com eot_threshold de 0.5 a 0.9 |
serviço da Deepgram | cobrança do serviço de STT |
| Smart Turn v3 | forma de onda do áudio, não a transcrição | detecção semântica de fim de turno | local, inferência em CPU em cerca de 12 ms em processadores modernos | open source, pesos em pipecat-ai/smart-turn-v3 |
| Jev | state em texto ou JSON | respostas tipadas com choice, probabilities e confidence |
API da TypeSafe, OpenRouter ou Cloudflare | US$ 0,042 por 1 milhão de tokens de entrada, saída gratuita |
O Smart Turn é mantido no repositório pipecat-ai/smart-turn e usa Whisper Tiny como base com uma camada classificadora linear, com cerca de 8M de parâmetros quantizados em int8
Ele resolve a camada de áudio, não a de decisão
Sobre latência do Jev, os números que existem publicados são os dos cookbooks da própria TypeSafe: uma rodada com 14 perguntas Noul numa única chamada registrou 111 ms de média de ida e volta, e uma rodada com 8 perguntas Choice registrou 114 ms
A home da TypeSafe divulga ainda 193,6x mais rápido e 444,6x mais barato, derivados dos workflows que eles mesmos publicaram, e a própria empresa admite que esses resultados representam a ponta alta dos ganhos reais
Ou seja, trate como claim de fornecedor e meça no SEU pipeline 🙂
Problemas comuns nessa arquitetura e como evitar
Sintoma: o agente atropela a fala do usuário
Causa provável: eot_threshold baixo demais, o turno fecha antes da hora
Como prevenir: suba dentro da faixa 0.5 a 0.9, lembrando que o padrão é 0.7 e que valores mais altos reduzem falso positivo com um pouco mais de latência
Sintoma: o agente demora a responder e a conversa fica robótica
Causa provável: você só começa a trabalhar depois do EndOfTurn
Como prevenir: habilite eager_eot_threshold (0.3 a 0.9), rascunhe a resposta no EagerEndOfTurn e cancele quando vier TurnResumed
Sintoma: decisão errada quando o áudio tá ruim
Causa provável: o Jev recebeu uma transcrição corrompida e decidiu com confiança em cima de lixo
Como prevenir: portão de confiança por palavra, penalizando o limiar do ramo quando existe palavra suspeita, e fallback numa fala de esclarecimento
Sintoma: 429 Too Many Requests
Causa provável: os limites da API são medidos em tokens por segundo E em requisições por minuto, e estourar qualquer um dos dois devolve 429
Como prevenir: enxugue o state e agrupe as perguntas numa chamada só por turno, em vez de uma chamada por pergunta
Sintoma: erro de contexto no meio da ligação
Causa provável: state crescendo turno a turno com histórico bruto
Como prevenir: respeite os 64k de state mais todas as perguntas e os 32k de state mais a pergunta mais longa, cortando histórico antigo e mantendo só o resumo do roteiro
Próximo passo
A ideia central é essa separação: o áudio diz QUANDO o turno acabou, o Jev diz O QUE fazer com ele
Misturar as duas camadas é o caminho mais rápido pra um agente que fala por cima da pessoa ou que congela esperando um modelo escrever texto
Pra começar, o jev-voice-agent é um ponto de partida honesto, porque mostra o pipeline inteiro com as falas escritas por humano e o portão de confiança explícito no código
E se você usa Pipecat, vale acompanhar a integração oficial do TypeSafe no pull request #5792, aberto por jamsea no repositório pipecat-ai/pipecat, que segue em rascunho e ainda não foi mesclado
Minha sugestão de ordem: sobe primeiro um único Choice de ramo com limiar fixo, valida em ligações reais, e só depois adiciona os Nouls e o Score no mesmo lote
Começar com quatro perguntas e três limiares é a receita certa pra você não saber qual deles tá errado quando o agente fizer besteira 😀
até o próximo post!
Perguntas frequentes
O Jev substitui o Deepgram Flux num assistente de voz?
Não, os dois fazem coisas diferentes
O Flux decide que a pessoa parou de falar a partir do áudio, é o endpointing
O Jev entra depois disso, decide o ramo da conversa a partir de texto ou JSON, porque ele não enxerga forma de onda
Dá pra usar o Jev sem ter conta na TypeSafe?
Dá, via intermediário
Existe página do provider Typesafe no OpenRouter e o modelo também está listado na documentação de modelos da Cloudflare
Vale porque a TypeSafe pausou novos cadastros em 22 de setembro de 2026 por excesso de demanda, embora contas já criadas sigam funcionando normalmente
Quantas chamadas ao Jev eu preciso fazer por turno de conversa?
No projeto de referência jev-voice-agent, é uma única requisição por turno com quatro perguntas em lote: o Choice do ramo, um Noul de se a pessoa respondeu, um Noul de escalar pra humano e um Score de clareza
Isso funciona porque o Jev avalia todas as perguntas em paralelo sobre o mesmo state, então não precisa de quatro chamadas separadas
Qual o limite de contexto pra montar o state de um turno de voz?
São dois orçamentos: 64k cobrindo o state somado a todas as perguntas da requisição, e 32k cobrindo o state mais a pergunta mais longa sozinha
Por isso o state deve ser um resumo do turno (trecho, pausa, evento do STT, turnos recentes), não o dump inteiro da ligação
Quanto custa rodar o Jev num agente de voz em produção?
O Jev 1.13 cobra US$ 0,042 por 1 milhão de tokens de entrada, e a saída é gratuita, já que o modelo devolve resposta tipada e não texto gerado
Como cada turno costuma virar uma única requisição em lote, o custo por turno tende a ficar baixo mesmo em volume
O que acontece se o STT transcrever uma palavra com baixa confiança antes de chamar o Jev?
No projeto de referência, qualquer palavra do Flux abaixo de GATE_MIN_WORD_CONFIDENCE (0.6) marca a transcrição como suspeita
Isso eleva a barra de confiança do ramo escolhido pelo Jev via GATE_SUSPECT_PENALTY (0.1), subindo o limiar de 0.65 para 0.75
Se o portão não é atendido, o agente cai numa fala de esclarecimento já escrita no script, em vez de arriscar responder errado
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.
