YouMind
Entrar

Construindo um Harness Personalizado com Pi e Jev

@omarsar0
INGLÊS23 de set. de 2026
102K
1.1K
115
41
2.2K

TL;DR

Este tutorial orienta os desenvolvedores na construção de um harness de agente de IA personalizado usando o SDK Pi e o Jev, um modelo especializado em tomada de decisão. Demonstra a implementação de portões de segurança, roteamento dinâmico de modelos e verificação de respostas para otimizar desempenho e custo.

Um agente de IA é um modelo de linguagem que trabalha em loop. Ele lê a tarefa, usa uma ferramenta como "leia este arquivo" ou "delete aquele arquivo", analisa o resultado e continua até terminar o trabalho. Cada vez que o modelo pede para usar uma ferramenta, essa solicitação é chamada de tool call (chamada de ferramenta).

O código que executa esse loop é chamado de harness. O modelo decide o que quer fazer. O harness executa a ação e também define o que o modelo tem permissão para fazer.

Um bom harness toma várias pequenas decisões ao longo do caminho. Qual modelo deve lidar com esta requisição? É seguro executar esta tool call? Esta resposta está boa o suficiente para ser entregue? A maioria dos harnesses responde a essas perguntas consultando um modelo de chat e lendo a resposta. Isso custa uma chamada completa de modelo a cada vez, então, na prática, a maioria das verificações acaba sendo ignorada.

Jev, da TypeSafe AI, é um modelo pequeno criado exclusivamente para essas decisões. Você descreve a situação, faz algumas perguntas e ele responde a cada uma delas com um número. Ele nunca gera texto.

Isso faz mais diferença quando você cria um harness personalizado, ou seja, seu próprio loop de agente em vez de usar uma solução pronta de mercado. Um harness personalizado permite escolher quais modelos serão executados, o que o agente pode acessar e o que conta como "trabalho concluído". O Jev torna as verificações por trás dessas escolhas baratas o suficiente para rodar em cada etapa.

Neste tutorial, você vai construir um harness com o Pi SDK, um kit de ferramentas em TypeScript para criar agentes, e usar o Jev em três pontos diferentes. No final, você vai rodar o harness pronto em um sandbox ao vivo e alterar as configurações por conta própria.

Acesse o tutorial interativo completo e o playground aqui:

https://academy.dair.ai/resources/jev-decisions-in-a-pi-sdk-harness

Este guia foi inspirado no artigo Building a Harness with Jev, de Sydney Runkle, publicado no blog da LangChain, que mostra o roteamento de modelos e o controle de ferramentas como middlewares prontos para uso na LangChain. Aqui, você mesmo vai implementar esses mesmos conceitos no Pi SDK e depois adicionar mais dois padrões: um para lidar com falhas e outro para validar respostas.

O que você vai construir

O harness tem três partes. Cada uma faz uma pergunta diferente ao Jev em um momento específico, e o restante deste guia se refere a elas por estes nomes.

elvis - inline image

O exemplo usado ao longo do texto é um agente trabalhando em uma pasta com anotações de levantamento de trilhas, sendo um arquivo por saída. Ele pode ler, escrever e realmente deletar essas anotações — e é exatamente por isso que o gate (controle de acesso) é tão importante.

O que é o Jev

A TypeSafe chama o Jev de modelo System One (Sistema 1). O nome vem do psicólogo Daniel Kahneman, que descreveu dois modos de pensar. O Sistema 1 é rápido e automático, como saber instintivamente que uma panela está quente. O Sistema 2 é lento e deliberado, como fazer uma divisão longa no papel.

Neste harness, um modelo de linguagem comum faz o trabalho pesado de ler arquivos e escrever respostas. O Jev fica responsável pelos julgamentos rápidos ao redor disso. Ele é barato e rápido o suficiente para ser consultado em cada tool call, não apenas naquelas que você já esperava serem arriscadas.

elvis - inline image

Cada número é uma probabilidade entre 0 e 1. Um 0,83 significa que o Jev tem bastante certeza de que a resposta é sim. Um 0,03 significa que ele tem bastante certeza de que a resposta é não.

Três tipos de perguntas

Toda requisição ao Jev tem duas partes. O state (estado) é a situação que você quer avaliar, como uma tool call ou o pedido de um usuário. As questions (perguntas) são o que você quer descobrir sobre essa situação. O Jev responde todas as perguntas em uma única chamada, ao mesmo tempo, então fazer três perguntas leva praticamente o mesmo tempo que fazer uma.

O Jev suporta três tipos de perguntas. A primeira, que ele chama de noul, é uma pergunta de sim ou não.

elvis - inline image

O Jev só sabe o que você diz a ele, então descreva cada opção e cada nível em linguagem clara. Essas descrições formam o prompt.

Configuração

O Jev está disponível pelo OpenRouter, um serviço que oferece acesso a vários modelos de IA usando uma única chave de API. Essa mesma chave serve tanto para o modelo de linguagem quanto para o Jev. Instale os dois pacotes do Pi e configure sua chave.

bash
1npm install @earendil-works/pi-agent-core @earendil-works/pi-ai
bash
1OPENROUTER_API_KEY=...

O Jev tem seu próprio endereço web, separado do endpoint padrão de chat. Sempre especifique uma versão exata, como typesafe/jev-1.13. O cliente inteiro do Jev cabe em uma única chamada fetch.

javascript
1const JEV = "typesafe/jev-1.13";
2
3async function ask(state: unknown, questions: unknown) {
4 const response = await fetch("https://openrouter.ai/api/alpha/decisions", {
5 method: "POST",
6 headers: {
7 "Content-Type": "application/json",
8 Authorization: `Bearer ${process.env.OPENROUTER_API_KEY}`,
9 },
10 body: JSON.stringify({ model: JEV, state, questions }),
11 signal: AbortSignal.timeout(2_000),
12 });
13 if (!response.ok) throw new Error(await response.text());
14 return response.json();
15}

O agente fica esperando enquanto o Jev responde, então a chamada é cancelada após dois segundos. Uma resposta normal leva de 200 a 400 milissegundos.

Onde o Jev entra

A classe Agent do Pi executa o loop para você. Ela permite que seu próprio código rode em momentos específicos desse ciclo. Esses pontos são chamados de hooks. O harness usa um hook para cada uma de suas três partes.

elvis - inline image

Um primeiro gate

Vamos começar com a versão mais simples e útil do gate. Antes de cada tool call, faça uma pergunta de sim ou não ao Jev e bloqueie a chamada se a resposta indicar "sim".

javascript
1import { Agent } from "@earendil-works/pi-agent-core";
2
3const agent = new Agent({
4 initialState: { systemPrompt, model, tools },
5 streamFn: models.streamSimple.bind(models),
6
7 beforeToolCall: async ({ toolCall, args }) => {
8 const { answers } = await ask(
9 { tool: toolCall.name, arguments: args },
10 {
11 destructive: {
12 type: "noul",
13 instructions: "Esta chamada de ferramenta destrói ou sobrescreve dados que não foram criados nesta execução.",
14 criteria: {
15 true: "Deleta arquivos, trunca ou sobrescreve conteúdo existente, descarta dados ou faz force-push sobre o histórico.",
16 false: "Lê, lista, cria um novo arquivo ou adiciona conteúdo a um arquivo que esta execução já criou.",
17 },
18 },
19 },
20 );
21
22 if (answers.destructive.noul >= 0.65) {
23 return { block: true, reason: "Bloqueado: isso parece destrutivo.", terminate: true };
24 }
25 },
26});

O valor 0,65 é um threshold (limiar), o ponto de corte onde o harness deixa de confiar na chamada. Qualquer coisa que o Jev pontue nesse valor ou acima é bloqueada.

Agora, um agente que tente deletar suas anotações será interrompido antes que a exclusão aconteça. Deletar uma anotação pontua cerca de 0,83, enquanto ler uma pontua 0,01. Mas o gate é meio bruto. Criar um arquivo totalmente novo pontua cerca de 0,70, então isso também acaba sendo bloqueado.

Fazer a consulta custa muito pouco. O Jev cobra US$ 0,042 por milhão de tokens de entrada, menos de um terço do preço de entrada do GLM 5.3 Flash, que é o mais barato dos dois modelos usados neste harness.

Do primeiro gate ao harness completo

O primeiro gate funciona, mas deixa quatro lacunas.

  1. O threshold fica escondido dentro do hook, o que dificulta ajustes e testes.
  2. Toda requisição roda no mesmo modelo, seja ela fácil ou difícil.
  3. Não há nenhuma regra dizendo o que acontece se o Jev ficar inacessível.
  4. Nada verifica se a resposta final é realmente boa.

Cada seção numerada abaixo resolve uma dessas lacunas.

1. Mantenha os thresholds em um só lugar

Esta seção aprimora o gate.

Os thresholds definem o que o agente pode fazer, e você vai ajustá-los com frequência assim que começar a ver resultados reais. Por isso, tire-os do hook e coloque-os em uma função simples, decideGate(). Ela recebe os números do Jev e devolve um verdict (veredito): a decisão final do harness sobre aquela chamada. Manter essas regras centralizadas é o que chamamos de policy (política).

A policy também adiciona uma opção intermediária. Um único threshold só permite dizer "liberar" ou "bloquear". Com dois thresholds, você tem três vereditos.

  • Em blockAt ou acima, a chamada é bloqueada.
  • Abaixo de askAt, a chamada é executada.
  • Entre os dois, a chamada aguarda a aprovação de uma pessoa.

Essa faixa intermediária captura as chamadas sobre as quais o Jev não tem certeza e que um limite único acabaria classificando errado para um lado ou para o outro.

elvis - inline image
javascript
1export function decideGate(signals: GateSignals, policy = DEFAULT_GATE_POLICY): GateVerdict {
2 const worst = Math.max(
3 signals.destructive.noul,
4 signals.irreversible.noul,
5 signals.outsideWorkspace.noul,
6 );
7 if (worst >= policy.blockAt) return { action: "block", ... };
8 if (worst >= policy.askAt) return { action: "ask", ... };
9 return { action: "allow", ... };
10}

Como é uma função simples, você pode testá-la passando números como os do exemplo acima, sem precisar envolver nenhum modelo real.

2. Escolha um modelo por requisição

Esta seção adiciona o router (roteador).

Algumas requisições são fáceis, como ler um único arquivo. Outras são difíceis, como investigar por que algo quebrou. Rodar tudo no modelo mais poderoso é jogar dinheiro fora, e rodar tudo em um modelo barato gera respostas fracas para as requisições complexas. O router associa cada requisição ao tier (nível) certo, ou seja, ao modelo rápido e barato ou ao modelo potente e caro.

Antes de uma requisição começar, o router faz duas perguntas ao Jev em uma única chamada. Uma choice (escolha) seleciona o tier, e um score (pontuação) avalia a complexidade da requisição.

elvis - inline image
javascript
1const ROUTER_QUESTIONS = {
2 tier: choice("Qual nível de modelo deve lidar com esta requisição?", {
3 fast: "Ler um arquivo, extrair uma informação dele ou fazer uma pequena edição em um único ponto.",
4 powerful: "Trabalho que envolve vários arquivos ou uma falha sem causa óbvia.",
5 }),
6 complexity: score("Quanto raciocínio esta requisição exige?", [
7 "Mecânico. Uma etapa, sem necessidade de julgamento.",
8 "Localizado. Algumas etapas dentro de uma mesma área.",
9 "Arquitetural. Muitas peças móveis ou uma causa raiz desconhecida.",
10 ]),
11};

A policy do router usa as duas respostas da seguinte forma.

  • Se a pontuação de complexidade for alta, use o modelo poderoso, mesmo que o Jev tenha escolhido o rápido.
  • Se o Jev não estiver confiante na escolha, use o modelo poderoso por segurança.
  • Caso contrário, use o modelo que o Jev escolheu.
javascript
1if (complexity.score >= policy.escalateAtComplexity) return powerful;
2if (tierAnswer.confidence < policy.minConfidence) return policy.fallbackTier;
3return tierAnswer.choice;

Esse é apenas um exemplo de policy. A sua pode dar pesos diferentes às respostas para se adequar ao seu contexto — por exemplo, priorizando o modelo barato em um job em lote de alto volume ou sempre escalando qualquer coisa que toque o ambiente de produção. O Jev só fornece as respostas; o seu código decide o que fazer com elas.

Por que escolher apenas uma vez

O router escolhe o modelo uma única vez, quando a requisição começa, e mantém essa escolha até o fim. O motivo é o prompt caching (cache de prompt).

Cada vez que o agente dá um passo, o modelo relê toda a conversa até aquele ponto. Os provedores de IA armazenam conversas lidas recentemente para que essa releitura saia barato. Mas cada modelo tem seu próprio armazenamento. Se você trocar de modelo no meio do caminho, o novo modelo terá que ler tudo de novo, pagando o preço cheio.

O criador do Jev detalha esses cálculos em um documento de design sobre agentes de programação. Em uma sessão longa, alternar do Claude Opus para o Sonnet (mais barato) e voltar custou cerca de 50% a mais do que simplesmente permanecer no Opus o tempo todo. Portanto, escolha o modelo logo no início, enquanto a conversa ainda é curta, e mantenha-o.

3. Prepare-se para o Jev ficar fora do ar

Esta seção altera tanto o gate quanto o router.

A partir do momento em que o harness consulta o Jev para cada tool call, o agente passa a depender dele. Como qualquer serviço online, o Jev pode ficar lento ou sair do ar. Defina antecipadamente o que cada parte fará quando não obtiver resposta. E a escolha certa varia para cada uma delas.

O gate bloqueia a chamada. Se o gate não consegue consultar o Jev, ele não tem como saber se a chamada é segura. Deixá-la passar poderia apagar arquivos, então o gate recusa. Engenheiros chamam isso de failing closed (falhar fechado), como uma porta que tranca automaticamente quando falta energia.

O router usa o modelo poderoso. Se o router não consegue consultar o Jev, ele não sabe qual é a dificuldade da requisição. O modelo poderoso dá conta de qualquer coisa, então a requisição ainda recebe uma boa resposta, e você paga um pouco mais por isso. Isso é failing open (falhar aberto), deixando o trabalho seguir em frente.

elvis - inline image

4. Valide a resposta

Esta seção adiciona o verifier (validador). Em harnesses de agentes, o verifier é a etapa que checa o trabalho do agente antes de considerá-lo concluído.

Um agente pode terminar entregando uma resposta incompleta ou afirmando coisas que ele nunca verificou de fato nos arquivos. Quem lê muitas vezes não percebe. Checar a resposta antes de devolvê-la pega esses erros enquanto o agente ainda pode tentar de novo.

O verifier envia ao Jev a resposta finalizada junto com os arquivos e resultados de ferramentas que serviram de base. O Jev pontua a qualidade da resposta e diz se as afirmações são grounded (fundamentadas), ou seja, respaldadas pelo que o agente realmente leu.

elvis - inline image
javascript
1const VERIFY_QUESTIONS = {
2 quality: score("Quão bem a resposta atende à requisição?", [
3 "Não responde à requisição.",
4 "Responde parcialmente, com uma lacuna que o leitor notaria.",
5 "Responde totalmente à requisição.",
6 ]),
7 grounded: noul("Toda afirmação factual é respaldada pelos arquivos ou resultados de ferramentas presentes no histórico."),
8};

Duas regras impedem que o agente fique tentando para sempre. Ele tem, no máximo, duas tentativas no total. E quando o Jev não está confiante na própria nota que deu, o harness aceita a resposta em vez de pagar por outra tentativa.

Segurança e logs

O Jev te dá uma probabilidade, e probabilidades podem estar erradas. Por isso, tudo o que o código puro consegue verificar com certeza deve ser validado direto no código. Neste harness, toda ferramenta de arquivo rejeita qualquer caminho fora da pasta do projeto, independentemente do que o Jev diga. Deixe o Jev para os julgamentos que o código não consegue fazer.

O gate analisa apenas a tool call em si, ou seja, o nome da ferramenta e seus parâmetros de entrada. Isso ajuda contra prompt injection, técnica em que um texto escondido em um arquivo ou página web engana o modelo para fazê-lo executar algo prejudicial. O gate nunca vê a armadilha, mas enxerga a chamada maliciosa que ela provoca.

Registre em log cada decisão junto com os números que a embasaram. O log explica por que algo foi bloqueado e fornece dados reais para calibrar os thresholds. O harness escreve uma linha por decisão em um arquivo chamado decisions.jsonl. Como o gate vê tudo o que o agente tenta fazer, o log oculta endereços de e-mail e chaves de API, além de encurtar entradas muito longas.

Teste na prática

O sandbox abaixo executa o harness finalizado deste tutorial, conectado ao Jev real. Ele trabalha na pasta de anotações de levantamento de trilhas, e a ferramenta delete_path realmente pode apagá-las.

Teste aqui: https://academy.dair.ai/resources/jev-decisions-in-a-pi-sdk-harness

Por que criar seu próprio harness

Agentes prontos tomam essas decisões com base em regras internas pré-definidas. Um harness personalizado coloca esse controle no seu código. Você escolhe os modelos, define os thresholds, decide quando uma pessoa precisa intervir e lê no log exatamente o motivo de cada chamada ter sido feita.

O Jev é o que torna isso viável. Cada decisão leva algumas centenas de milissegundos e custa uma fração mínima de centavo, permitindo que você adicione uma verificação sempre que o seu fluxo precisar, e não apenas onde houver orçamento para uma chamada completa de modelo. As três partes deste tutorial são só o ponto de partida. Um harness personalizado para o seu domínio pode fazer ao Jev qualquer pergunta que seja relevante ali.

Outros usos

Essas mesmas três partes funcionam fora do universo de agentes de programação.

  • Bots de code review. Pontue cada alteração sugerida e mostre a um humano apenas aquelas que valem a leitura.
  • Limpeza de registros. Pergunte se dois registros descrevem a mesma coisa antes de mesclá-los e deixe os casos duvidosos para uma pessoa resolver.
  • Pipelines de documentos. Pontue cada página extraída e reprocesse apenas as que tiverem notas baixas.
  • Filas de aprovação. Somente as chamadas que caem na faixa de "perguntar a uma pessoa" chegam a um revisor humano.

Em todos os casos, o modelo de linguagem faz o trabalho aberto e criativo, enquanto o Jev responde às pequenas perguntas ao redor dele.

As perguntas, thresholds e policies deste tutorial são exemplos didáticos, e não configurações otimizadas para produção. Estamos fazendo benchmarks para medir como essas mudanças no harness afetam o custo e a qualidade das respostas, e um guia complementar com esses resultados sai em breve.

Passei uma noite com o Opus 5.5 montando este guia e o sandbox. Se encontrar algum problema, me mande uma DM. Fique à vontade para copiar o artigo e enviá-lo aos seus agentes para continuar experimentando essas ideias.

Salvar com um clique

Faça leitura profunda de artigos virais com IA no YouMind

Salve a fonte, faça perguntas específicas, resuma o argumento e transforme um artigo viral em notas reutilizáveis em um único espaço de trabalho com IA.

Explorar o YouMind
Para criadores

Transforme seu Markdown em um artigo 𝕏 impecável

Quando você publica seus próprios textos longos, formatar imagens, tabelas e blocos de código para o 𝕏 é uma dor de cabeça. O YouMind transforma um rascunho completo em Markdown em um artigo 𝕏 impecável e pronto para publicar.

Experimente Markdown para 𝕏

Mais padrões para decifrar

Artigos virais recentes

Explorar mais artigos virais