Dados sensíveis no state do Jev: o que anonimizar antes de enviar?

O state do Jev é o campo que carrega o contexto da requisição para o System One, ao lado das questions. O problema é que muita gente joga ali o registro inteiro do banco, com CPF, e-mail e endereço que a pergunta nem usa. A doc da TypeSafe é direta: filtre em código antes e mande só os campos que a pergunta precisa, porque detalhe irrelevante vira distrator e derruba a acurácia. Como a cobrança é só por token de entrada (US$ 0,042 por milhão, saída US$ 0), cortar campo corta ruído e conta junto.
Mandar o registro inteiro do cliente pra uma API de decisão é o tipo de atalho que ninguém revisa até o dia em que alguém pergunta "peraí, o CPF tava nesse payload?"
O state é o campo que carrega o conteúdo que você quer que o System One avalie, enviado na requisição ao lado das questions
E como ele aceita tanto texto simples quanto dado estruturado, o caminho mais curto é sempre o mesmo: pega o registro do banco, joga inteiro, deixa o modelo se virar
Aí vai junto e-mail, endereço, telefone, número de documento e mais um monte de coisa que a pergunta não usa pra nada
Esse post é um checklist de engenharia pra cortar isso antes do POST, sem quebrar a decisão 🙂
O que você precisa antes de montar o state
Acesso ao Jev, primeiro de tudo
O acesso direto pela TypeSafe está em early access com lista de espera no console.typesafe.ai, mas Vercel AI Gateway, OpenRouter e Cloudflare Workers AI servem o modelo sem waitlist
Depois, a noção do formato da chamada: um POST em https://api.typesafe.ai/v1/systemone, com header Authorization: Bearer <API_KEY>, Content-Type: application/json e um corpo com state, questions e model (por exemplo "jev-latest")
Terceiro ponto, e esse é o que interessa aqui: o state aceita string de texto simples, objeto ou array JSON, e a documentação recomenda objeto estruturado para requisições não triviais

Domine o Jev e coloque decisões de IA dentro do seu sistema
Você vai aprender a usar o Jev, o System One Model da TypeSafe AI, pra automatizar decisões com resposta tipada e confiança medida, sem depender de chat nem de alguém revisando cada passo. Entre na lista de espera para garantir a condição de lançamento!
Objeto estruturado é bom pra você também, porque campo nomeado é campo que dá pra auditar, remover e substituir em código
E tem a parte jurídica, que muita gente pula
No DPA da TypeSafe o cliente é o controlador dos dados pessoais e a TypeSafe é a operadora, com uso restrito às instruções documentadas
Traduzindo: decidir o que sai do seu banco é responsabilidade sua, não do provedor
Passo a passo: anonimizar o state antes de enviar
A ordem aqui importa, porque a maioria das pessoas monta o state primeiro e tenta limpar depois
Inverte isso
E encara como rotina de revisão, do mesmo jeito que você faria pra revisar antes de mandar pro cliente qualquer entregável
- Escreva as questions antes do state
Os tipos de pergunta do System One são Choice, Score e Noul (sim/não com probabilidade)
Escreve as perguntas primeiro e olha pra elas: cada pergunta te diz exatamente quais campos a decisão consome
Se nenhuma pergunta usa endereço, endereço não entra. Simples assim
O erro comum deste passo: montar o state "por garantia", achando que o modelo pode precisar de algo depois. Não precisa, e esse "depois" é justamente o que vira distrator
- Filtre e recorte em código, nunca no prompt
A doc da TypeSafe é bem literal nisso: busque e filtre em código primeiro, e mande só os campos que a pergunta precisa
// errado: manda o registro inteiro do banco
const state = await db.customer.findUnique({ where: { id } })
// certo: seleciona só o que as questions consomem
const row = await db.customer.findUnique({
where: { id },
select: {
createdAt: true,
plan: true,
chargebackCount: true,
failedPaymentCount: true
}
})
O erro comum deste passo: pedir no texto do state pro modelo "ignorar os campos pessoais". Instrução não é filtro, o dado já saiu da sua infra nesse ponto
- Troque identificador direto por token interno
Quando a decisão precisa referenciar uma entidade (pra correlacionar logs, por exemplo), você não precisa do valor real
Substitui por um token do seu lado e guarda o mapa na sua base
const state = {
customer_ref: tokenize(row.id), // "cus_9f21"
account_age_days: daysSince(row.createdAt),
plan: row.plan
}
O mapa cus_9f21 -> id real fica com você, e o provedor recebe uma referência que não diz nada fora do seu contexto
É a mesma lógica de manter dados sensíveis fora da memória de uma ferramenta de IA: se o dado não precisa atravessar, ele não atravessa
O erro comum deste passo: gerar o token a partir do valor real com hash simples e previsível. Se o token é reversível por força bruta em cima de um domínio pequeno (tipo CPF), tu não anonimizou nada
- Mascare o que precisa continuar legível
Tem caso em que a pergunta usa o formato do dado, não o dado
Aí máscara resolve, mantendo prefixo e sufixo e escondendo o miolo
Existe um CLI comunitário no GitHub, o jev-pii-checker, que usa o próprio Jev pra achar PII em texto e já aplica máscara padrão nos valores detectados, no formato primeiros2…último1
Dá pra usar como passo de verificação em cima do payload antes de enviar, ou só como referência do formato de máscara
O erro comum deste passo: mascarar o campo óbvio e esquecer o texto livre. Campo notes, description e histórico de conversa é onde o e-mail e o telefone aparecem escritos na mão
- Converta dado bruto em sinal derivado
Esse é o passo que mais reduz risco e ruído ao mesmo tempo
A pergunta quase nunca quer a data de nascimento, ela quer uma faixa. Não quer o histórico inteiro, quer uma contagem
| Campo bruto (sai) | Sinal derivado (fica) |
|---|---|
cpf, email, phone |
customer_ref tokenizado |
birth_date |
age_range: "25-34" |
full_address |
region: "SE" |
transactions[] completo |
tx_count_30d, avg_ticket_band |
notes em texto livre |
has_open_complaint: true |
Repara que o lado direito responde as mesmas perguntas e não identifica ninguém
O erro comum deste passo: derivar sinal tão agregado que a pergunta perde o que precisava. Se a acurácia cair, o culpado costuma ser um sinal derivado cedo demais, não o corte de PII
- Meça o state contra os orçamentos
O OpenRouter lista a janela de contexto do Jev 1.13 como 32.000 tokens
Já a documentação da TypeSafe descreve dois orçamentos: 64k cobrindo o state mais todas as questions somadas, e 32k valendo pro state mais a pergunta mais longa. Limites maiores existem em planos custom e enterprise
Os dois números não batem entre si e nenhuma das duas páginas explica por quê, então o caminho sem susto é tratar o menor como teto: 32k pro state mais a pergunta mais longa
Mede isso no CI, não na hora do incidente
O erro comum deste passo: medir só o state e esquecer que as questions entram na conta junto
- Ligue as proteções do provedor na chamada
No Vercel AI Gateway, Zero Data Retention e bloqueio de treino são habilitados por requisição, via providerOptions.gateway (os filtros combinam como AND)
providerOptions: {
gateway: {
zeroDataRetention: true,
disallowPromptTraining: true
}
}
No Workers AI da Cloudflare, a chamada vai pelo binding AI, passando state e questions:
const res = await env.AI.run('typesafe/jev', {
state: '...',
questions: {
// Choice, Score ou Noul, conforme a doc
}
})
E o formato direto na API da TypeSafe:
curl -X POST https://api.typesafe.ai/v1/systemone \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "jev-latest",
"state": { "customer_ref": "cus_9f21", "account_age_days": 412 },
"questions": { }
}'
O erro comum deste passo: tratar flag de provedor como substituto da anonimização. Flag protege o que acontece lá; anonimizar protege o que sai daqui. São camadas diferentes
Três exemplos de state antes e depois da anonimização
Cadastro de cliente
Antes, o clássico "joguei o SELECT *":
{
"id": 48211,
"name": "Maria de Souza Lima",
"cpf": "123.456.789-00",
"email": "[email protected]",
"phone": "+55 11 99999-0000",
"address": "Rua das Acácias, 120, apto 51, São Paulo/SP",
"birth_date": "1991-03-08",
"created_at": "2023-02-14",
"plan": "pro",
"failed_payments": 2
}
Depois, só o que a pergunta "esse cadastro deve ir pra revisão manual?" realmente usa:
{
"customer_ref": "cus_9f21",
"account_age_days": 950,
"plan": "pro",
"failed_payments": 2,
"email_domain_type": "public"
}
Mesma decisão, sem um único identificador direto
Ticket de suporte
O texto livre é o campeão de vazamento, porque o cliente escreve o próprio telefone no corpo da mensagem
{
"ticket": {
"subject": "Não consigo acessar",
"body": "Oi, sou a Maria ([email protected]), meu tel é 11 99999-0000...",
"customer_email": "[email protected]"
}
}
Depois, com máscara no texto e sinais do que a triagem usa:
{
"ticket_ref": "tkt_7c03",
"subject": "Não consigo acessar",
"body_masked": "Oi, sou a Ma…a (ma…m), meu tel é 11…0...",
"reopened_count": 3,
"sla_breached": true,
"plan": "pro"
}
Análise de transação
Aqui o ganho é trocar o array inteiro de transações por contagem e faixa
{
"tx_ref": "tx_11ab",
"amount_band": "1k-5k",
"device_new": true,
"tx_count_24h": 7,
"chargeback_count_90d": 1,
"country_match": false
}
E tem um detalhe que faz esse corte valer mais do que parece: o Jev ingere o state uma vez e avalia todas as questions contra ele em paralelo
Ou seja, é uma passada de state pra N perguntas
Cada campo que tu corta se paga em todas as decisões daquela requisição, não em uma só 😀
Por que menos dado melhora a decisão (e não só o custo)
Aqui vem a parte contraintuitiva pra quem vem de LLM de chat, onde "mais contexto" costuma ser conselho padrão
A documentação da TypeSafe diz o oposto: a acurácia cai conforme o state se enche de conteúdo não relacionado à decisão, porque o detalhe irrelevante funciona como distrator
Faz sentido se tu pensar no que o modelo tá fazendo: ele não tá escrevendo texto, tá avaliando o state contra perguntas fechadas
Cada campo que não serve pra nenhuma pergunta é ruído competindo por atenção
E tem o efeito colateral que dói na manutenção: state grande e cheio de detalhe irrelevante dificulta descobrir qual parte da entrada gerou a resposta errada
Quando a resposta vem estranha com 40 campos no payload, boa sorte no bisect
Com 6 campos, tu olha e sabe
A conta fecha do mesmo lado
A cobrança do Jev é só por token de entrada, porque o modelo não gera texto: US$ 0,042 por milhão de tokens de entrada e US$ 0 por milhão de tokens de saída no Jev 1.13
Saída zero muda o incentivo por completo
Não existe "resposta mais longa saiu mais cara": todo o custo tá no que você mandou
Campo cortado é ruído e dinheiro cortados na mesma linha de código
O que o provedor garante e o que continua sendo seu problema
Do lado do provedor, o que está publicado:
- A política de privacidade da TypeSafe diz que a empresa não treina nem faz fine-tune de modelos com o Input do cliente, e não divulga o Input a terceiros além de seus provedores de serviço
- O DPA coloca o cliente como controlador e a TypeSafe como operadora, com transferências cobertas por SCCs da UE ou UK Addendum
- A lista de subprocessadores fica em
trust.typesafe.ai/subprocessors, com aviso prévio antes de nomear novos e janela de objeção de até 15 dias pro cliente - No Vercel AI Gateway, ZDR e No Training são habilitados por requisição e as chamadas aparecem nos logs do gateway
- A Cloudflare afirma que não usa o Customer Content (incluindo prompts e saídas) pra treinar modelos do Workers AI nem pra melhorar serviços, salvo consentimento explícito
Agora o contrapeso honesto, porque compliance sem contrapeso é marketing
O Jev não tem pesos públicos nem opção suportada de self-host: o acesso é pela API hospedada da TypeSafe e por gateways de terceiros
Não existe rodar isso dentro do teu perímetro e pronto
O dado sai da tua infra de qualquer jeito
Por isso a anonimização na origem é a única camada que tu controla de verdade. Política é promessa contratual, e promessa contratual é ótima, mas ela não desfaz um payload que já saiu com CPF dentro
Material de apoio: contexto certo antes de codar
Pra começar do zero com a ideia de alimentar IA com o contexto certo (e só o contexto certo) dentro do fluxo de código, este vídeo do canal mostra o Context7 plugado no Claude Code, fazendo ele ler a documentação antes de escrever qualquer linha
Checklist final antes do primeiro POST
Rodada rápida do que NÃO deve estar no payload quando tu apertar enter:
- Nome completo, CPF, e-mail, telefone e endereço em campo próprio
- Os mesmos dados escondidos dentro de texto livre (
notes,body, histórico) - ID de banco cru no lugar de token interno
- Data de nascimento onde faixa etária resolve
- Array completo de histórico onde contagem ou faixa resolve
- Qualquer campo que nenhuma das suas questions consulta
O próximo passo prático é bem direto: monta o payload mínimo, roda contra as tuas questions reais e compara a resposta com a do state completo
Se a decisão não mudou, tu acabou de tirar PII, ruído e custo de uma vez
Se mudou, olha qual sinal tu agregou demais no passo 5 e devolve só aquele
E sobre o caminho de acesso: direto pela TypeSafe é early access com waitlist no console.typesafe.ai, enquanto Vercel AI Gateway, OpenRouter e Cloudflare Workers AI servem o Jev sem lista de espera
Escolhe o provedor, liga as flags que ele oferecer e manda o state magrinho
até o próximo post! =)
Perguntas frequentes
A TypeSafe treina modelos com os dados que eu mando no state do Jev?
Não. A política de privacidade da TypeSafe afirma que a empresa não treina nem faz fine-tune de modelos com o Input do cliente, e esse Input também não é divulgado a terceiros fora dos provedores de serviço envolvidos na operação.
Dá pra ativar Zero Data Retention no state do Jev?
Sim, mas depende do canal de acesso. No Vercel AI Gateway, Zero Data Retention e bloqueio de treino são configurados por requisição em providerOptions.gateway, com zeroDataRetention e disallowPromptTraining, e os dois filtros funcionam como AND.
O Jev cobra pelo texto de resposta das questions, igual um modelo generativo?
Não, porque o Jev não gera texto de saída. A cobrança é só por token de entrada, US$ 0,042 por milhão de tokens no Jev 1.13, e o token de saída custa US$ 0.
Dá pra rodar o Jev on-premise pra não mandar o state pra fora da minha infra?
Não existe essa opção hoje. O Jev não tem pesos públicos nem self-host suportado, o acesso é só via API hospedada da TypeSafe ou por gateways de terceiros como Vercel AI Gateway, OpenRouter e Cloudflare Workers AI.
Como eu sei se um novo subprocessador vai ter acesso ao state que eu envio?
A TypeSafe publica a lista atual de subprocessadores em trust.typesafe.ai/subprocessors e avisa antes de nomear um novo. Existe uma janela de até 15 dias pra o cliente se opor antes da mudança valer.
O Workers AI da Cloudflare usa o conteúdo do state do Jev pra treinar modelo?
Não por padrão. A Cloudflare afirma que não usa Customer Content, o que inclui prompts e saídas, pra treinar modelos do Workers AI nem pra melhorar serviços, exceto com consentimento explícito do cliente.
Formações
Formação Claude Code
Domine Claude Code do absoluto zero até o avançado
- 120 aulas
- 4 projetos
- 9h 45min
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.
