YouMind
Iniciar sesión

Creación de un harness personalizado con Pi y Jev

@omarsar0
INGLÉS23 sept 2026
102K
1.1K
115
41
2.2K

TL;DR

Este tutorial guía a los desarrolladores en la creación de un harness de agente de IA personalizado usando el SDK de Pi y Jev, un modelo especializado en toma de decisiones. Demuestra cómo implementar puertas de seguridad, enrutamiento dinámico de modelos y verificación de respuestas para optimizar el rendimiento y los costos.

Un agente de IA es un modelo de lenguaje que trabaja en bucle. Lee la tarea, usa una herramienta como "lee este archivo" o "borra ese archivo", revisa el resultado y sigue adelante hasta terminar el trabajo. Cada vez que el modelo pide usar una herramienta, esa solicitud se llama tool call (llamada a herramienta).

El código que ejecuta este bucle se conoce como harness. El modelo decide qué quiere hacer. El harness lo ejecuta y también define qué tiene permitido hacer el modelo.

Un buen harness toma muchísimas decisiones pequeñas sobre la marcha. ¿Qué modelo debería encargarse de esta solicitud? ¿Es seguro ejecutar este tool call? ¿Esta respuesta es lo bastante buena para entregarla? La mayoría de los harnesses responden esto consultando a un modelo de chat y leyendo su respuesta. Eso cuesta una llamada completa al modelo cada vez, así que en la práctica casi todas las verificaciones se omiten.

Jev, de TypeSafe AI, es un modelo pequeño creado exclusivamente para estas decisiones. Le describes la situación, le haces algunas preguntas y te responde cada una con un número. Nunca genera texto.

Esto cobra mayor importancia cuando construyes un harness personalizado, es decir, tu propio bucle de agente en lugar de usar uno prefabricado. Un harness personalizado te permite elegir qué modelos se ejecutan, qué puede tocar el agente y qué se considera "terminado". Jev hace que las verificaciones detrás de esas decisiones sean tan económicas que puedes ejecutarlas en cada paso.

En este tutorial, vas a construir un harness con el Pi SDK, un kit de herramientas en TypeScript para crear agentes, y usarás Jev en tres puntos clave. Al final, ejecutarás el harness terminado en un sandbox en vivo y podrás modificar su configuración tú mismo.

Accede al tutorial interactivo completo y al playground aquí:

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

Esta guía se inspiró en el artículo de Sydney Runkle Building a Harness with Jev del blog de LangChain, donde muestra el enrutamiento de modelos y el control de herramientas como middleware listo para usar en LangChain. Aquí construirás esas mismas ideas por tu cuenta con el Pi SDK y luego agregarás dos patrones más para manejar fallos y verificar respuestas.

Qué vas a construir

El harness tiene tres partes. Cada una le hace una pregunta a Jev en un momento distinto, y el resto de esta guía se refiere a ellas con estos nombres.

elvis - inline image

El ejemplo que usaremos es un agente que trabaja en una carpeta con notas de inspección de senderos, un archivo por salida. Puede leer, escribir y realmente borrar esas notas, y por eso el gate (puerta de control) es tan importante.

Qué es Jev

TypeSafe llama a Jev un modelo de Sistema Uno. El nombre viene del psicólogo Daniel Kahneman, quien describió dos modos de pensamiento. El Sistema Uno es rápido y automático, como saber que una sartén está caliente. El Sistema Dos es lento y deliberado, como resolver una división larga.

En este harness, un modelo de lenguaje normal hace el trabajo pesado de leer archivos y redactar respuestas. Jev se encarga de los juicios rápidos a su alrededor. Jev es tan económico y veloz que puedes consultarlo en cada tool call, no solo en los que esperabas que fueran riesgosos.

elvis - inline image

Cada número es una probabilidad entre 0 y 1. Un 0.83 significa que Jev está bastante seguro de que la respuesta es sí. Un 0.03 significa que está bastante seguro de que la respuesta es no.

Tres tipos de preguntas

Toda solicitud a Jev tiene dos partes. El estado (state) es la situación que quieres evaluar, como un tool call o la petición de un usuario. Las preguntas son lo que quieres saber sobre esa situación. Jev responde todas las preguntas en una sola llamada y al mismo tiempo, así que hacer tres preguntas tarda casi lo mismo que hacer una.

Jev admite tres tipos de preguntas. La primera, a la que Jev llama noul, es una pregunta de sí o no.

elvis - inline image

Jev solo sabe lo que tú le dices, así que describe cada opción y cada nivel con palabras claras. Esas descripciones son el prompt.

Configuración

Jev está disponible a través de OpenRouter, un servicio que te da acceso a muchos modelos de IA con una sola clave de API. Esa única clave cubre tanto el modelo de lenguaje como Jev. Instala los dos paquetes de Pi y configura tu clave.

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

Jev tiene su propia dirección web, distinta a la habitual de chat. Siempre especifica una versión exacta, como typesafe/jev-1.13. Todo el cliente de Jev es una sola llamada 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}

El agente espera mientras Jev responde, por eso la llamada se cancela después de dos segundos. Una respuesta normal tarda entre 200 y 400 milisegundos.

Dónde se integra Jev

La clase Agent de Pi ejecuta el bucle por ti y permite que tu propio código corra en momentos específicos de ese ciclo. Estos puntos se llaman hooks. El harness usa un hook para cada una de sus tres partes.

elvis - inline image

Un primer gate

Empecemos con la versión más simple y útil del gate. Antes de cada tool call, hazle a Jev una pregunta de sí o no y bloquea la llamada si la respuesta parece ser afirmativa.

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: "Este tool call destruye o sobrescribe datos que no fueron creados en esta ejecución.",
14 criteria: {
15 true: "Borra archivos, trunca o sobrescribe contenido existente, elimina datos o hace un force-push sobre el historial.",
16 false: "Lee, lista, crea un archivo nuevo o agrega contenido a un archivo que esta ejecución ya creó.",
17 },
18 },
19 },
20 );
21
22 if (answers.destructive.noul >= 0.65) {
23 return { block: true, reason: "Bloqueado: esto parece destructivo.", terminate: true };
24 }
25 },
26});

El 0.65 es un umbral, el punto de corte donde el harness deja de confiar en una llamada. Todo lo que Jev puntúe en ese valor o por encima queda bloqueado.

Ahora, un agente que intente borrar tus notas se detendrá antes de que ocurra el borrado. Borrar una nota obtiene una puntuación de unos 0.83, mientras que leerla saca 0.01. Sin embargo, el gate es poco preciso. Crear un archivo completamente nuevo obtiene cerca de 0.70, así que también se bloquea.

Consultar cuesta muy poco. Jev cobra $0.042 por millón de tokens de entrada, menos de un tercio del precio de entrada de GLM 5.3 Flash, el más barato de los dos modelos que usa este harness.

Del primer gate al harness completo

El primer gate funciona, pero deja cuatro vacíos.

  1. El umbral está escondido dentro del hook, así que es difícil ajustarlo o probarlo.
  2. Todas las solicitudes se ejecutan en el mismo modelo, sin importar si son fáciles o difíciles.
  3. Nada indica qué pasa si no se puede contactar a Jev.
  4. Nada verifica si la respuesta final es buena.

Cada sección numerada a continuación cierra uno de esos vacíos.

1. Mantén los umbrales en un solo lugar

Esta sección mejora el gate.

Los umbrales definen qué puede hacer el agente, y los ajustarás constantemente en cuanto veas resultados reales. Por eso, sácalos del hook y ponlos en una función sencilla: decideGate(). Recibe los números de Jev y devuelve un veredicto: la decisión final del harness sobre una llamada. Mantener estas reglas en un solo lugar se conoce como política.

La política también suma una opción intermedia. Un solo umbral únicamente puede permitir o bloquear. Dos umbrales dan tres veredictos.

  • En blockAt o por encima, la llamada se bloquea.
  • Por debajo de askAt, la llamada se ejecuta.
  • En medio, la llamada espera a que una persona la apruebe.

Ese rango intermedio atrapa las llamadas sobre las que Jev tiene dudas y que un único punto de corte clasificaría mal en un sentido u otro.

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 es una función común y corriente, puedes probarla pasándole números como los de arriba, sin necesidad de involucrar un modelo en vivo.

2. Elige un modelo por solicitud

Esta sección agrega el router.

Algunas solicitudes son fáciles, como leer un archivo. Otras son difíciles, como rastrear por qué algo falló. Ejecutar todo en el modelo más potente desperdicia dinero, y ejecutar todo en uno barato da respuestas débiles a las solicitudes complejas. El router asigna cada solicitud al tier adecuado, es decir, al modelo rápido y económico o al potente y costoso.

Antes de que empiece una solicitud, el router le hace dos preguntas a Jev en una sola llamada. Una elección (choice) selecciona el tier, y una puntuación (score) evalúa la complejidad de la solicitud.

elvis - inline image
javascript
1const ROUTER_QUESTIONS = {
2 tier: choice("¿Qué tier de modelo debería encargarse de esta solicitud?", {
3 fast: "Leer un archivo, extraer un dato de él o hacer una edición pequeña en un solo lugar.",
4 powerful: "Trabajo que abarca varios archivos o un fallo sin causa evidente.",
5 }),
6 complexity: score("¿Cuánto razonamiento necesita esta solicitud?", [
7 "Mecánico. Un solo paso, sin juicio.",
8 "Localizado. Algunos pasos dentro de una misma área.",
9 "Arquitectónico. Muchas piezas móviles o una causa raíz desconocida.",
10 ]),
11};

La política del router usa ambas respuestas de esta manera.

  • Si la puntuación de complejidad es alta, usa el modelo potente, incluso si Jev eligió el rápido.
  • Si Jev no confía en su elección, usa el modelo potente por seguridad.
  • De lo contrario, usa el modelo que eligió Jev.
javascript
1if (complexity.score >= policy.escalateAtComplexity) return powerful;
2if (tierAnswer.confidence < policy.minConfidence) return policy.fallbackTier;
3return tierAnswer.choice;

Este es solo un ejemplo de política. La tuya puede ponderar las respuestas de otra forma según tu dominio; por ejemplo, inclinándose por lo barato en un proceso por lotes de alto volumen o escalando siempre cualquier cosa que toque producción. Jev solo aporta las respuestas; tu código decide qué hacer con ellas.

Por qué elegir solo una vez

El router elige un modelo una sola vez, cuando arranca la solicitud, y lo mantiene hasta terminarla. Esto se debe al prompt caching (caché de prompts).

Cada vez que el agente da un paso, el modelo vuelve a leer toda la conversación hasta ese momento. Los proveedores de IA almacenan las conversaciones leídas recientemente para que releerlas sea barato. Pero cada modelo tiene su propio almacenamiento. Si cambias de modelo a mitad de camino, el nuevo tendrá que leer todo de nuevo a precio completo.

El fundador de Jev desglosa los números en un documento de diseño sobre agentes de programación. En una sesión larga, cambiar de Claude Opus al más económico Sonnet y volver costó cerca de un 50 % más que quedarse en Opus todo el tiempo. Así que elige el modelo al principio, cuando la conversación aún es corta, y mantente ahí.

3. Prepárate para cuando Jev no responda

Esta sección modifica tanto el gate como el router.

Una vez que el harness consulta a Jev por cada tool call, el agente depende de él. Como cualquier servicio en línea, Jev puede ir lento o caerse. Decide de antemano qué hará cada parte cuando no obtenga respuesta. La decisión correcta varía según el caso.

El gate bloquea la llamada. Si el gate no puede consultar a Jev, no tiene idea de si la llamada es segura. Dejarla pasar podría borrar archivos, así que el gate la rechaza. En ingeniería esto se llama failing closed (fallar en cerrado), como una puerta que se traba cuando se va la luz.

El router usa el modelo potente. Si el router no puede consultar a Jev, no sabe qué tan difícil es la solicitud. El modelo potente puede con todo, así que la solicitud igual recibe una buena respuesta y tú pagas un poco más. Esto es failing open (fallar en abierto), dejar que el trabajo siga adelante.

elvis - inline image

4. Verifica la respuesta

Esta sección agrega el verificador. En los harnesses de agentes, un verifier (verificador) es el paso que revisa el trabajo del agente antes de darlo por terminado.

Un agente puede terminar con una respuesta incompleta o afirmando cosas que nunca verificó realmente en los archivos. Quien la lee muchas veces no se da cuenta. Revisar la respuesta antes de devolverla detecta esto mientras el agente todavía puede intentarlo de nuevo.

El verificador le envía a Jev la respuesta terminada junto con los archivos y resultados de herramientas en los que se basó. Jev puntúa la calidad de la respuesta e indica si sus afirmaciones están fundamentadas (grounded), es decir, respaldadas por lo que el agente realmente leyó.

elvis - inline image
javascript
1const VERIFY_QUESTIONS = {
2 quality: score("¿Qué tan bien satisface la respuesta la solicitud?", [
3 "No responde a la solicitud.",
4 "Responde parcialmente, con un vacío que el lector notaría.",
5 "Responde por completo la solicitud.",
6 ]),
7 grounded: noul("Cada afirmación fáctica está respaldada por los archivos o resultados de herramientas en la transcripción."),
8};

Dos reglas evitan que el agente reintente eternamente. Tiene un máximo de dos intentos en total. Y cuando Jev no confía en su propia calificación, el harness acepta la respuesta en lugar de pagar por otro intento.

Seguridad y registro

Jev te da una probabilidad, y una probabilidad puede estar equivocada. Por eso, todo lo que el código pueda verificar con certeza debería comprobarse directamente en el código. En este harness, cualquier herramienta de archivos rechaza rutas fuera de la carpeta del proyecto, sin importar lo que diga Jev. Deja a Jev para los juicios que el código no puede hacer.

El gate solo mira el tool call en sí, es decir, el nombre de la herramienta y sus entradas. Eso ayuda contra la inyección de prompts, donde texto oculto en un archivo o página web engaña al modelo para que haga algo dañino. El gate nunca ve el engaño, pero sí ve la llamada perjudicial que este provoca.

Registra cada decisión junto con los números que la respaldan. El log explica por qué se bloqueó algo y muestra cifras reales para definir umbrales. El harness escribe una línea por decisión en un archivo llamado decisions.jsonl. Como el gate ve todo lo que el agente intenta hacer, el log oculta correos electrónicos y claves, y acorta las entradas largas.

Pruébalo

El sandbox de abajo ejecuta el harness terminado de este tutorial, conectado al Jev real. Trabaja sobre la carpeta de notas de inspección de senderos, y su herramienta delete_path realmente puede borrarlas.

Pruébalo aquí: https://academy.dair.ai/resources/jev-decisions-in-a-pi-sdk-harness

Por qué construir tu propio harness

Los agentes prefabricados toman estas decisiones con sus propias reglas integradas. Un harness personalizado las pone en tu código. Tú eliges los modelos, defines los umbrales, decides cuándo interviene una persona y lees en el log exactamente por qué se tomó cada decisión.

Jev es lo que hace que esto sea viable. Cada decisión tarda unos cientos de milisegundos y cuesta una fracción mínima de centavo, así que puedes agregar una verificación donde tu trabajo la necesite, no solo donde puedas pagar una llamada completa al modelo. Las tres partes de este tutorial son un punto de partida. Un harness personalizado para tu propio dominio puede hacerle a Jev las preguntas que sean relevantes ahí.

Otros usos

Estas mismas tres partes funcionan fuera de los agentes de programación.

  • Bots de revisión de código. Puntúa cada cambio sugerido y muéstrale a una persona solo los que valga la pena leer.
  • Limpieza de registros. Pregunta si dos registros describen lo mismo antes de fusionarlos y deja los pares dudosos para una persona.
  • Pipelines de documentos. Puntúa cada página extraída y reprocesa solo las de baja puntuación.
  • Colas de aprobación. Solo las llamadas en el rango de "preguntar a una persona" llegan a un revisor humano.

En cada caso, el modelo de lenguaje hace el trabajo abierto y Jev responde las pequeñas preguntas a su alrededor.

Las preguntas, umbrales y políticas de este tutorial son ejemplos didácticos, no configuraciones optimizadas para producción. Estamos evaluando cómo estos cambios en el harness afectan el costo y la calidad de las respuestas, y pronto publicaremos una guía de seguimiento con esos resultados.

Dediqué una tarde junto a Opus 5.5 para armar esta guía y el sandbox. Si te topas con algún problema, escríbeme por DM. Siéntete libre de copiar el artículo y pasárselo a tus agentes para seguir experimentando con estas ideas.

Guardar con un clic

Lee artículos virales en profundidad con IA en YouMind

Guarda la fuente, haz preguntas concretas, resume el argumento y convierte un artículo viral en notas reutilizables en un único espacio de trabajo con IA.

Explora YouMind
Para creadores

Convierte tu Markdown en un artículo de 𝕏 impecable

Cuando publicas tus propios textos largos, dar formato en 𝕏 a imágenes, tablas y bloques de código es un fastidio. YouMind convierte un borrador completo en Markdown en un artículo de 𝕏 impecable y listo para publicar.

Prueba Markdown a 𝕏

Más patrones por descifrar

Artículos virales recientes

Explorar más artículos virales