Jev redujo un 61% el coste de este agente de IA
En julio escribí que los modelos pequeños deberían decidir qué ven los grandes: no se trata de asignar una tarea a un modelo más barato, sino de poner modelos pequeños junto al grande para que elijan qué tokens llega a leer. Terminé aquel artículo diciendo que la economía justificaba experimentar, pero no era una prueba, y que alguien tenía que hacer el ensayo.
Entonces, el 15 de septiembre, se lanzó Jev. Es el primer modelo System One de TypeSafe: no genera texto, devuelve probabilidades calibradas para las respuestas que defina tu código, cuesta $0.042 por millón de tokens de entrada y responde en unos cientos de milisegundos. Esta combinación permite medir de verdad, y a bajo coste, dos versiones muy concretas de la idea de julio.
Así que probé esas dos.
Precargar las skills. Cuando un agente recibe un catálogo de documentos internos, necesita un ciclo entero para decidir cuál leer y llamar a una herramienta para recuperarlo. Jev puede tomar esa decisión antes del primer turno por una fracción de céntimo, y los documentos llegan ya incluidos en el prompt.
Filtrar la carga útil de la herramienta. Una respuesta real de API contiene sobre todo campos sobre los que ningún agente actuará. Además, en una configuración MCP, toda esa información acaba en la ventana de contexto y se vuelve a enviar en cada turno posterior. Jev puede puntuar todos los campos de una respuesta antes de que el agente la vea.
Ambos son problemas de clasificación, no de redacción. Esto es lo que ocurrió en 192 ejecuciones de 8 tareas, con los costes calculados sobre Claude Opus 5:
Otra decisión que podría tomar Jev es si el título de un chat sigue describiendo bien la conversación. Explico ese caso de uso en mi artículo sobre cómo generar títulos para conversaciones. No lo he medido con Jev.
Coste medio de una ejecución del agente con Opus 5
La tarea con mejores resultados salió un 61% más barata. La media de las ocho fue del 29%, y la peor, del 13%. En todos los casos, incluido el agente sin optimizar, se superó el 99% de las comprobaciones de calidad, así que no hubo que sacrificar nada para conseguirlo.
El experimento completo costó $1.17.
Qué es Jev
No genera texto. Se le envía un state y un conjunto de preguntas tipadas, y devuelve una distribución de probabilidad calibrada sobre las respuestas definidas en el código. TypeSafe lo denomina modelo System One, entrenado con lo que describe como aprendizaje por refuerzo para tomar decisiones calibradas.
| Qué | Valor |
|---|---|
| Precio | $0.042 por millón de tokens de entrada, salida gratis |
| Contexto | 32,000 tokens |
| Latencia medida aquí | De 300 a 600 ms, p50, independientemente del tamaño del lote |
| Endpoint | POST /api/alpha/decisions en OpenRouter |
La característica que hace posible este experimento es el procesamiento por lotes. Todas las preguntas se envían en una sola llamada HTTP, y el state se envía una única vez. Puntuar 264 campos de una carga útil requiere una solicitud, no 264.
Mecanismo uno: precargar las skills
Antes del primer turno del agente, Jev lee la solicitud y la descripción de una línea de cada skill. No ve el contenido de ninguna skill. Todo lo que obtiene una puntuación igual o superior a 0.55 se añade íntegramente al prompt del sistema.
Paso 1 · qué pide el usuario
Paso 2 · Jev puntúa las 11 skills a la vez y solo lee sus descripciones de una línea
Una llamada HTTP, 11 preguntas, unos 1,500 tokens, $0.00006. Con un umbral de 0.55, se selecciona una skill.
Paso 3 · el prompt que recibe el agente en su primer turno
La herramienta read_skill sigue disponible, así que el agente aún puede recuperar lo que el enrutador no haya detectado. Y eso importa, porque a veces se le escapan cosas.
Mecanismo dos: filtrar la carga útil de la herramienta
Cuando una herramienta devuelve el resultado y antes de que llegue al agente, se puntúa la relevancia de cada campo hoja de la respuesta para la solicitud actual. Se elimina todo lo que queda por debajo de 0.35.
Paso 1 · el agente llama a una herramienta y la API responde con todos los datos
Paso 2 · lo que Jev sabe de la situación, no solo de la carga útil
Paso 3 · una llamada, una puntuación por campo. Por debajo de 0.35, se tacha el campo
En las seis ejecuciones de esta tarea sobrevivieron entre 58 y 62 de los 124 campos. Los tres de los que depende la tarea (status, dunning.days_past_due, account.id) sobrevivieron en las seis.
Paso 4 · lo que llega a la ventana de contexto del agente
De 3,181 caracteres a unos 1,780, un recorte del 44%. Y nada de lo eliminado vuelve a enviarse en los turnos 3, 4 y 5.
Fíjate en esas puntuaciones: los campos que se eliminan en esta llamada están entre 0.31 y 0.34, y los que se conservan, entre 0.35 y 0.37. El límite es real y algunos campos lo cruzan de una ejecución a otra. trial_end obtuvo 0.34 en una ejecución y 0.37 en otra. Ningún dato necesario para la tarea estuvo cerca del límite.
De dónde viene realmente la seguridad
Todo se decide en el tercer paso, el estado. El mismo umbral con un estado más pobre es peligroso. Con uno más completo, el filtrado es a la vez más seguro y más agresivo.
Medición aislada del campo que determina la tarea de cobro:
| Qué incluye el estado | account.id | metadata.account_id | Conservados |
|---|---|---|---|
| solicitud + herramienta + argumentos | 0.18 | 0.20 | 51 / 124 |
| + las políticas que sigue | 0.19 | 0.18 | 50 / 124 |
| + lo que ya ha hecho | 0.33 | 0.25 | 40 / 124 |
| + las herramientas que aún puede llamar | 0.73 | 0.76 | 27 / 124 |
Las dos columnas centrales muestran las puntuaciones del campo del que realmente depende la tarea. La última indica cuántos de los 124 campos superan el umbral de 0.35.
Añadir las instrucciones no cambia nada. El historial ayuda un poco. Lo decisivo es la lista de acciones pendientes. Hasta que el sistema de puntuación sabe que tiene disponible una llamada a billing_set_account_state(account_id, …), un id de cuenta no es más que otra cadena de texto.
La idea general, aplicable también a otras configuraciones, es esta:
Un campo no es útil por sí solo. Es útil por lo que el agente está a punto de hacer con él, y esa información no está en la carga útil, sino en el esquema de las herramientas que siguen disponibles.
Dónde se nota la mejora y dónde no
Los dos mecanismos responden a factores completamente distintos. Para saber cuál se aplica a tu carga de trabajo, importa más entender esa diferencia que fijarse en la media.
La precarga responde a los turnos que se pueden evitarNo al tamaño de la carga útil
- Ideal para tareas que necesitan una política y gastarían un turno en buscarla
- No aporta nada en tareas que no necesitan instrucciones
- Puede empeorar las cosas: una instrucción cargada por error se vuelve a enviar en cada turno
El filtrado responde a la densidad de la carga útilNo a la duración de la tarea
- Ideal cuando la mayoría de los bytes son texto que nadie lee
- Apenas aporta nada cuando todos los campos son esenciales
- El ahorro se acumula, porque un campo eliminado no se vuelve a enviar en el turno siguiente
La diferencia es grande. En la tarea en la que llegan seis artículos del centro de ayuda y solo importa updated_at, el filtrado elimina el 84% de la carga útil y el 63% de los tokens de entrada. En la tarea de incidencias, donde se usa casi cada campo, elimina el 5%. Mismo agente, mismo umbral, una diferencia de 17 veces.
Coste por tarea con Opus 5: agente sin modificar frente a los dos mecanismos:
| Tarea | Tipo | Sin mecanismos | Con ambos | Ahorro |
|---|---|---|---|---|
| documentación obsoleta | corta · carga útil muy dispersa | $0.0639 | $0.0252 | −61% |
| reembolso | media · mixta | $0.0419 | $0.0249 | −41% |
| incidencia | corta · densa | $0.0340 | $0.0241 | −29% |
| cobro | corta · mixta | $0.0187 | $0.0135 | −28% |
| consulta | una llamada · dispersa | $0.0083 | $0.0068 | −17% |
| gdpr | media · mixta | $0.0336 | $0.0282 | −16% |
| sla | larga · mixta | $0.0442 | $0.0378 | −15% |
| análisis posterior a la incidencia | muy larga · mixta | $0.0906 | $0.0792 | −13% |
| media | $0.0419 | $0.0299 | −29% |
Un agente con Opus 5 que gestione 10,000 tareas al mes pasa de $419 a $299, de los cuales $9 corresponden a Jev.
El precio de tu modelo principal determina si compensa filtrar
Este es el resultado que debería cambiar lo que haces.
Filtrar consume tokens de Jev en cada llamada a una herramienta. Esos tokens tienen un coste fijo. Los tokens que ahorra se cobran al precio del modelo de tu agente. Así que todo depende de una proporción, y el resultado cambia según el caso.
| Modelo del agente | Precio de entrada | Agente sin filtros | Ambos mecanismos | |
|---|---|---|---|---|
| GPT-5.6 Luna | $0.20/M | $0.00182 | $0.00221 | +21% |
| Claude Sonnet 5 | $2.00/M | $0.01676 | $0.01253 | −25% |
| Claude Opus 5 | $5.00/M | $0.04191 | $0.02995 | −29% |
El número de tokens es el mismo en todos los casos. Solo cambia la tarifa del agente. Con el modelo barato, Jev representa el 42% de la factura y filtrar cuesta más de lo que ahorra. Con Opus 5, representa el 3% de la factura.
Al calcular el punto de equilibrio con el número de tokens medido y la estructura de tarifas habitual, el resultado es $0.55 por millón de tokens de entrada con la caché de prompts activada y $0.37 sin ella. Por debajo, no filtres. Por encima, filtra.
Precargar habilidades sale rentable con cualquier modelo, incluso con el más barato, porque apenas cuesta nada: unos 1,500 tokens de Jev por ejecución, $0.00006, a cambio de un turno ahorrado.
Hay un efecto secundario que conviene tener en cuenta. La caché reduce la factura aproximadamente a la mitad y disminuye el valor relativo del filtrado, porque la mayor parte de lo que elimina el filtro se habría leído de la caché a bajo coste. Filtrar compensa más en una implementación sin caché que en una que sí la usa.
El modo de fallo
El umbral de 0.35 solo es seguro gracias al estado enriquecido. Una versión anterior sin él provocó el peor tipo de fallo.
El filtro descartó account.id de una suscripción de Stripe, con una puntuación de 0.18, y también descartó metadata.account_id, la segunda copia. El agente usó el único identificador que quedaba e hizo lo siguiente:
call: billing_set_account_state(account_id="cus_PmT4k9WqLr2XbN", state="read_only")
↑ el ID de cliente de Stripe, no el de la cuenta
report: "He puesto la cuenta asociada en modo de solo lectura, de acuerdo con la política del día 10."El identificador correcto era acct_borealis_4c77. El agente actuó sobre el objeto equivocado y presentó un informe convincente sobre lo que había hecho.
Todo lo que pongas en producción necesita rutas críticas declaradas y un umbral calibrado para ellas. En el enrutamiento, una diferencia de dos centésimas en el umbral separaba «ahorra un turno» de «no ahorra nada». En el filtrado, la diferencia era mucho mayor.
Qué conclusiones saco
Merece la pena dedicar tiempo a mejorar la eficiencia de la IA, y combinar modelos de distintos tamaños y tipos ofrece muchas posibilidades. Lo interesante es que un modelo incapaz de escribir texto resulta ser un buen juez de lo que debería poder ver un modelo que sí escribe.
Aquí se probaron dos puntos de partida. El mismo patrón podría aplicarse en muchos otros casos: elegir qué archivos abre un agente, decidir cuándo resumir una conversación, valorar si un documento recuperado merece el coste de sus tokens o controlar una escritura antes de que se produzca. No se midió nada de eso, así que no daría por hecho que funciona sin comprobarlo.
A continuación encontrarás todos los detalles: el entorno de pruebas, cada tarea, cada umbral, todas las tablas y lo que estos resultados no demuestran.
Todos los detalles
Todo lo que viene a continuación es el experimento completo. Es largo a propósito. Si solo querías ver el resultado, ya lo tienes.
La configuración
El agente
Unas 80 líneas. Sin framework, SDK de agentes ni biblioteca de orquestación. Un bucle while alrededor de fetch:
- Envía una petición POST al endpoint de completions de chat de OpenRouter con la lista de mensajes y los esquemas de herramientas en formato de llamadas a funciones de OpenAI.
- Si la respuesta contiene
tool_calls, ejecuta cada llamada en local, añade el resultado como mensajerole: "tool"y vuelve al principio del bucle. - Si la respuesta no contiene
tool_calls, ese texto es la respuesta final y el bucle termina.
| Parámetro | Valor | Nota |
|---|---|---|
model | openai/gpt-5.6-luna | $0.20/M de entrada, $1.20/M de salida, contexto de 1,050,000 tokens |
tools | 17 esquemas de funciones | |
tool_choice | auto | el agente decide si llama a una herramienta y a cuál |
seed | 1000 + repetition index | lo único que varía entre repeticiones |
max_tokens | 2000 | un límite, no un objetivo |
reasoning / reasoning_effort | no configurado | se deja el valor predeterminado del proveedor |
temperature, top_p | no configurados | se dejan los valores predeterminados del proveedor |
En cuanto al razonamiento, nunca se pasó el parámetro reasoning, así que el modelo funcionó con el valor predeterminado del proveedor. Una llamada de control realizada después devuelve reasoning_tokens: 0, por lo que no se consumió un presupuesto de razonamiento aparte y ningún recuento de tokens incluye tokens de razonamiento ocultos. Si se repitiese con un nivel de razonamiento más alto, las cifras absolutas serían distintas.
Dos límites de seguridad, porque un bucle de agente desbocado cuesta dinero: un máximo de 8 turnos por ejecución y 6 llamadas a herramientas como máximo por turno. No se alcanzó ninguno en las 192 ejecuciones. Hay un tercer límite que suma el coste de todas las llamadas y detiene el proceso al superar un tope, fijado en $2.60 para la campaña.
El entorno
Una empresa ficticia de SaaS B2B llamada Northwind Analytics, con el agente como asistente de operaciones.
17 herramientas con cargas útiles que imitan la estructura real de Stripe, Zendesk, HubSpot, Statuspage, PagerDuty, Slack, Linear y un CMS de centro de ayuda: mismos nombres de claves, misma estructura anidada, mismo ruido. Son funciones locales que devuelven datos de prueba, así que nada sale del equipo. Las operaciones de escritura quedan registradas para su evaluación y devuelven una confirmación verosímil.
| Herramienta | Basada en | Carga útil |
|---|---|---|
kb_list_articles | endpoint de listado de un CMS de centro de ayuda | 28,128 caracteres |
stripe_list_charges | Stripe GET /v1/charges | 6,993 caracteres |
kb_get_article | endpoint de lectura de un CMS de centro de ayuda | 4,966 caracteres |
stripe_get_subscription | Stripe GET /v1/subscriptions/:id | 3,181 caracteres |
zendesk_get_ticket | Zendesk GET /api/v2/tickets/:id con datos relacionados | 2,402 caracteres |
pagerduty_get_incident | PagerDuty GET /incidents/:id | 1,821 caracteres |
statuspage_get_incident | Incidente y disponibilidad de Statuspage | 1,711 caracteres |
crm_get_account | Objeto de empresa de HubSpot | 1,117 caracteres |
read_skill | interno | 988 caracteres |
stripe_create_refund | Stripe POST /v1/refunds | 479 caracteres |
linear_create_issue | Linear issueCreate | 202 caracteres |
billing_apply_credit | API interna de facturación | 147 caracteres |
zendesk_reply | Zendesk PUT /api/v2/tickets/:id | 144 caracteres |
billing_set_account_state | API interna de facturación | 134 caracteres |
slack_post_message | Slack chat.postMessage | 124 caracteres |
billing_apply_discount | API interna de facturación | 98 caracteres |
pagerduty_escalate | Escalado de PagerDuty | 92 caracteres |
11 skills, archivos Markdown con una línea description en el front matter y un cuerpo que contiene los umbrales, cifras y formatos concretos: churn-save-offers, docs-review-cadence, dunning-playbook, enterprise-contract-terms, escalation-matrix, gdpr-data-requests, incident-comms, oncall-handover, refund-policy, release-notes-format, slack-style-guide. Varias no tienen nada que ver con ninguna tarea. Son elementos de distracción para el enrutador.
8 tareas, elegidas para abarcar dos ejes independientes: la duración, desde una sola llamada a una herramienta hasta siete turnos, y la densidad de la carga útil, desde «cada campo importa» hasta «el 76% de los bytes es texto que se puede descartar».
Las tareas, textuales
| Tarea | Mensaje enviado como petición del usuario |
|---|---|
T1-refund | ACME Analytics (cuenta acct_acme_9f21) nos ha escrito: dicen que se les ha cobrado dos veces la factura de noviembre. Comprueba qué ha pasado y resuélvelo por completo, incluido avisar al equipo. |
T2-sla | El ticket 48213 de Zendesk es una reclamación de crédito por SLA de un cliente empresarial, relativa a octubre. Averigua qué importe le corresponde, aplícalo y respóndele. |
T3-dunning | La suscripción sub_1QdRvT2eZvKYlo2CkW8pQm4L está vencida. Aplica el siguiente paso que indique nuestro proceso. |
T4-gdpr | Acaba de llegar el ticket 48377 al buzón de privacidad. Encárgate a partir de aquí y completa todos los pasos que exija el proceso. |
T5-incident | Acaba de activarse el incidente PD-99213. Gestiona el escalado y las comunicaciones. |
T6-stale-docs | ¿Qué artículos publicados en nuestro centro de ayuda tienen pendiente una revisión? Registra el trabajo que haya que hacer. |
T7-postmortem | El incidente INC-4471 ya está resuelto. Haz el seguimiento: averigua a quién afectó, qué les corresponde y comunica a la empresa la situación. |
T8-lookup | ¿Qué plan tiene acct_borealis_4c77 y quién es su CSM? |
Evaluación
Determinista. 59 comprobaciones entre las ocho tareas; cada una consiste en una llamada a una herramienta con argumentos exactos, como stripe_create_refund(charge="ch_3QRk9X…", amount=14900, reason="duplicate"), o en un dato que aparece solo en un documento de skill: el nivel SLA del 25%, la regla del día 10, el equipo PRIV o el plazo de 30 días.
No interviene ningún evaluador LLM. Una ejecución que nunca consulta las skills falla automáticamente las comprobaciones del segundo tipo, que es precisamente el objetivo: permite medir si el agente ha tenido acceso a la política, en lugar de dejarlo a criterio de cada cual.
Cada tarea también define sus rutas de carga útil críticas, es decir, los campos de los que depende la respuesta. Nunca se usan para dirigir el filtro. Sirven para que quede constancia de cualquier filtro demasiado agresivo, incluso en las ejecuciones que, aun así, superan la prueba.
Los brazos
| Brazo | Habilidades precargadas | Carga filtrada |
|---|---|---|
0 | no | no |
A | sí, umbral 0.55 | no |
B | no | sí, umbral 0.35, estado enriquecido |
D | sí, umbral 0.55 | sí, umbral 0.35, estado enriquecido |
8 tareas × 4 brazos × 6 repeticiones = 192 ejecuciones, que solo se diferencian por seed.
Calibración
Ambos umbrales se probaron sin conexión antes de gastar ningún token del agente.
0.55 para el enrutamiento es el valor más alto que mantiene una exhaustividad total en las tareas usadas para calibrarlo. Con 0.60, slack-style-guide obtiene 0.58 en la tarea de reembolso y desaparece el turno ahorrado. Solo dos centésimas separan una reducción de turnos del 15 % de ninguna reducción.
0.35 para el filtrado solo es viable gracias al estado enriquecido descrito arriba. La calibración cuesta unos $0.004, porque ejecuta el enrutador y el evaluador, pero no el agente.
Una lección que se puede generalizar: cada forma de plantear una pregunta requiere su propia calibración. Un umbral no sirve para dos formulaciones distintas de una misma pregunta. Se observaron distribuciones con soportes completamente diferentes para una formulación específica de una tarea y otra independiente de la tarea. Vuelve a calibrar cada vez que cambies la formulación.
Totales de la campaña
| Métrica | Total |
|---|---|
| Ejecuciones | 192 |
| Turnos del agente | 775 |
| Tokens de entrada del agente | 2,118,338, de los cuales 1,685,860 (80%) se sirvieron desde la caché |
| Tokens de salida del agente | 130,003 |
| Tokens de entrada de Jev | 2,065,975 |
| Llamadas a Jev | 96 de enrutamiento + 252 de filtrado |
| Gasto real | agente $0.2977 · Jev $0.0868 |
| Total, incluidas la calibración y las variantes descartadas | $1.17 |
Resultados generales por brazo
| Brazo | Ejecuciones perfectas | Comprobaciones superadas | Turnos | Tokens de entrada | Rutas críticas descartadas |
|---|---|---|---|---|---|
0 | 92% | 99% | 4.44 | 12,960 | n/a |
A | 96% | 99% | 3.69 | 11,809 | n/a |
B | 94% | 99% | 4.31 | 9,967 | 0 |
D | 94% | 99% | 3.71 | 9,396 | 1 |
Ninguna técnica redujo la calidad. En los cuatro brazos se supera el 99% de las comprobaciones. De las 96 llamadas filtradas del brazo D, se descartó exactamente una ruta marcada como crítica, y esa ejecución también superó las comprobaciones. Las diferencias entre el 92% y el 96% de ejecuciones «perfectas» están dentro del margen de ruido con n = 48. Los efectos sólidos se observan en los turnos y los tokens.
Media de tokens por ejecución, desglosados según cómo se facturan:
| Brazo | Entrada nueva | Entrada en caché | Salida | Entrada de Jev |
|---|---|---|---|---|
0 | 2,941 | 10,020 | 741 | 0 |
A | 2,700 | 9,109 | 615 | 1,517 |
B | 1,873 | 8,093 | 723 | 19,457 |
D | 1,496 | 7,900 | 629 | 22,067 |
El brazo D reduce un 49% los tokens de entrada nuevos, que son los más caros.
Ahorro de tokens de entrada por técnica, de menor a mayor
| Técnica | Mínimo | Máximo | Mediana |
|---|---|---|---|
A precarga de habilidades | −3% en la tarea de SLA | +23% en la tarea del RGPD | 10% |
B filtrado de carga | +2% en la tarea del RGPD | +51% en documentación obsoleta | 17% |
D ambas | +9% en el análisis posterior | +63% en documentación obsoleta | 26% |
El único resultado negativo de toda la matriz corresponde a A en la tarea de SLA: el enrutador carga una habilidad de más sin ahorrar ningún turno. Esa habilidad se añade al mensaje del sistema y vuelve a enviarse en cada turno. Además, las dos técnicas no siempre suman sus efectos: en las tareas de SLA y de análisis posterior, D ahorra menos tokens que B por sí sola, precisamente por ese motivo.
Cómo puntuó realmente el enrutador
Probabilidad media por habilidad y tarea. Se considera cargada si alcanza o supera 0.55.
| Tarea | Habilidades cargadas | Puntuaciones más altas |
|---|---|---|
T1-refund | 2.0 | refund-policy 0.82 · slack-style-guide 0.60 · incident-comms 0.32 |
T2-sla | 2.0 | enterprise-contract-terms 0.95 · refund-policy 0.84 · churn-save-offers 0.13 |
T3-dunning | 1.0 | dunning-playbook 0.95 · churn-save-offers 0.32 · oncall-handover 0.13 |
T4-gdpr | 1.0 | gdpr-data-requests 0.87 · refund-policy 0.27 · escalation-matrix 0.22 |
T5-incident | 3.0 | escalation-matrix 0.93 · incident-comms 0.85 · slack-style-guide 0.69 |
T6-stale-docs | 1.0 | docs-review-cadence 0.93 · slack-style-guide 0.15 · oncall-handover 0.05 |
T7-postmortem | 3.0 | enterprise-contract-terms 0.92 · refund-policy 0.89 · incident-comms 0.58 · slack-style-guide 0.47 |
T8-lookup | 0.0 | slack-style-guide 0.07 · enterprise-contract-terms 0.06 · dunning-playbook 0.04 |
Cobertura: se cargaron 132 de las 144 habilidades necesarias, un 92 %. Hay un error sistemático por defecto y otro por exceso, y conviene decirlo claramente.
La habilidad que falta es slack-style-guide en la tarea de post mortem: obtiene 0.47, por debajo del umbral, en 12 de las 12 ejecuciones. La tarea pide «decirle a la empresa en qué situación se encuentra», pero el enrutador no lo interpreta como una cuestión de formato. El agente la consultó por su cuenta cuando la necesitó.
El falso positivo es refund-policy en la tarea de SLA, con 0.84, y en la de post mortem, con 0.89. Un crédito por incumplimiento del SLA parece un reembolso. Es justo la confusión que refund-policy pretende evitar, ya que el documento especifica que la falta de disponibilidad del servicio no da derecho a un reembolso. El enrutador se equivoca en la forma, pero acierta en el fondo, y el agente no salió perjudicado.
La tarea de consulta no carga nada, como debe ser. No hay ninguna habilidad relevante y la puntuación más alta es 0.07.
Cómo se comportó realmente el filtro
Brazo D, desglosado por herramienta, en 96 llamadas filtradas:
| Herramienta | Llamadas | Caracteres antes → después | Variación | Claves conservadas |
|---|---|---|---|---|
kb_list_articles | 8 | 225,024 → 24,834 | −89% | 605 / 1,808 |
stripe_list_charges | 6 | 41,958 → 12,819 | −69% | 405 / 1,584 |
stripe_get_subscription | 6 | 19,086 → 10,637 | −44% | 359 / 744 |
crm_get_account | 30 | 29,400 → 16,723 | −43% | 384 / 1,002 |
zendesk_get_ticket | 12 | 25,620 → 15,787 | −38% | 328 / 822 |
statuspage_get_incident | 9 | 15,399 → 10,734 | −30% | 311 / 540 |
pagerduty_get_incident | 12 | 21,852 → 16,497 | −25% | 428 / 684 |
stripe_create_refund | 6 | 3,012 → 2,610 | −13% | 60 / 108 |
zendesk_reply | 12 | 8,685 → 9,489 | +9% | 24 / 84 |
linear_create_issue | 18 | 5,287 → 6,734 | +27% | 83 / 138 |
billing_apply_credit | 8 | 1,343 → 2,406 | +79% | 42 / 56 |
El ahorro está en las herramientas de lectura, aunque varía muchísimo entre ellas: del −89 % en una lista de documentos al −25 % en un incidente, donde casi todo es imprescindible.
Las respuestas de confirmación de las operaciones de escritura aumentan, no disminuyen. billing_apply_credit devuelve 147 caracteres, y el marcador _trimmed que se añade ocupa más que los campos eliminados. Filtrar un contenido pequeño aumenta el resultado neto, así que cualquier implementación en producción debería omitir directamente los contenidos de menos de unos cientos de caracteres. Lo dejamos para que el efecto quede visible en el registro.
Todas las tareas, todos los brazos
Los precios corresponden al coste total de una ejecución, agente más Jev, según la proporción medida entre solicitudes nuevas y en caché. Las columnas Sonnet 5 y Opus 5 reproducen el tráfico medido con los precios de esos modelos. El coste de Jev es idéntico en las tres columnas.
T1-refund, media · contenido mixto
| Brazo | Perfecto | Comprobaciones | Turnos | Tokens de entrada | Reducción del contenido | $ Luna | $ Sonnet 5 | $ Opus 5 | frente a 0 |
|---|---|---|---|---|---|---|---|---|---|
0 | 100% | 100% | 4.5 | 15,369 | n/a | 0.00180 | 0.0167 | 0.0419 | n/a |
A | 100% | 100% | 4.0 | 14,247 (−7%) | n/a | 0.00165 | 0.0150 | 0.0373 | −11% |
B | 100% | 100% | 4.3 | 10,719 (−30%) | 65% | 0.00285 | 0.0141 | 0.0331 | −21% |
D | 100% | 100% | 4.0 | 9,899 (−36%) | 66% | 0.00252 | 0.0108 | 0.0249 | −41% |
T2-sla, larga · contenido mixto
| Brazo | Perfecto | Comprobaciones | Turnos | Tokens de entrada | Reducción del contenido | $ Luna | $ Sonnet 5 | $ Opus 5 | frente a 0 |
|---|---|---|---|---|---|---|---|---|---|
0 | 83% | 96% | 6.8 | 18,811 | n/a | 0.00192 | 0.0177 | 0.0442 | n/a |
A | 100% | 100% | 6.2 | 19,359 (+3%) | n/a | 0.00193 | 0.0174 | 0.0433 | −2% |
B | 83% | 96% | 6.5 | 15,528 (−17%) | 30% | 0.00286 | 0.0173 | 0.0417 | −6% |
D | 83% | 96% | 6.0 | 16,533 (−12%) | 72% | 0.00312 | 0.0160 | 0.0378 | −15% |
T3-dunning, corta · contenido mixto
| Brazo | Perfecto | Comprobaciones | Turnos | Tokens de entrada | Reducción del contenido | $ Luna | $ Sonnet 5 | $ Opus 5 | frente a 0 |
|---|---|---|---|---|---|---|---|---|---|
0 | 100% | 100% | 4.0 | 8,084 | n/a | 0.00080 | 0.0075 | 0.0187 | n/a |
A | 100% | 100% | 3.0 | 6,704 (−17%) | n/a | 0.00079 | 0.0069 | 0.0171 | −9% |
B | 100% | 100% | 4.0 | 7,384 (−9%) | 44% | 0.00129 | 0.0069 | 0.0163 | −13% |
D | 100% | 100% | 3.0 | 6,002 (−26%) | 44% | 0.00123 | 0.0058 | 0.0135 | −28% |
T4-gdpr, media · contenido mixto
| Variante | Perfectas | Comprobaciones | Turnos | Tokens de entrada | Recorte de carga | $ Luna | $ Sonnet 5 | $ Opus 5 | frente a 0 |
|---|---|---|---|---|---|---|---|---|---|
0 | 50% | 94% | 4.2 | 8,344 | n/a | 0.00150 | 0.0134 | 0.0336 | n/a |
A | 100% | 100% | 3.0 | 6,467 (−23%) | n/a | 0.00132 | 0.0114 | 0.0285 | −15% |
B | 83% | 98% | 4.2 | 8,167 (−2%) | 14% | 0.00186 | 0.0129 | 0.0315 | −6% |
D | 83% | 98% | 3.0 | 6,159 (−26%) | 16% | 0.00178 | 0.0116 | 0.0282 | −16% |
T5-incident, breve · carga densa
| Variante | Perfectas | Comprobaciones | Turnos | Tokens de entrada | Recorte de carga | $ Luna | $ Sonnet 5 | $ Opus 5 | frente a 0 |
|---|---|---|---|---|---|---|---|---|---|
0 | 100% | 100% | 3.8 | 8,647 | n/a | 0.00151 | 0.0136 | 0.0340 | n/a |
A | 67% | 96% | 3.0 | 7,004 (−19%) | n/a | 0.00121 | 0.0104 | 0.0259 | −24% |
B | 83% | 98% | 3.7 | 8,153 (−6%) | 6% | 0.00168 | 0.0127 | 0.0313 | −8% |
D | 83% | 98% | 3.0 | 6,935 (−20%) | 5% | 0.00143 | 0.0099 | 0.0241 | −29% |
T6-stale-docs, breve · carga muy escasa
| Variante | Perfectas | Comprobaciones | Turnos | Tokens de entrada | Recorte de carga | $ Luna | $ Sonnet 5 | $ Opus 5 | frente a 0 |
|---|---|---|---|---|---|---|---|---|---|
0 | 100% | 100% | 4.0 | 19,821 | n/a | 0.00265 | 0.0256 | 0.0639 | n/a |
A | 100% | 100% | 3.0 | 18,468 (−7%) | n/a | 0.00260 | 0.0246 | 0.0614 | −4% |
B | 100% | 100% | 4.0 | 9,639 (−51%) | 78% | 0.00262 | 0.0139 | 0.0329 | −49% |
D | 100% | 100% | 3.0 | 7,387 (−63%) | 84% | 0.00235 | 0.0109 | 0.0252 | −61% |
T7-postmortem, muy largo · carga mixta
| Variante | Perfectas | Comprobaciones | Turnos | Tokens de entrada | Recorte de carga | $ Luna | $ Sonnet 5 | $ Opus 5 | frente a 0 |
|---|---|---|---|---|---|---|---|---|---|
0 | 100% | 100% | 6.0 | 21,294 | n/a | 0.00406 | 0.0363 | 0.0906 | n/a |
A | 100% | 100% | 5.3 | 19,224 (−10%) | n/a | 0.00339 | 0.0297 | 0.0743 | −18% |
B | 100% | 100% | 5.7 | 17,064 (−20%) | 34% | 0.00488 | 0.0343 | 0.0841 | −7% |
D | 100% | 100% | 5.7 | 19,430 (−9%) | 33% | 0.00472 | 0.0324 | 0.0792 | −13% |
T8-lookup, una llamada · carga escasa
| Variante | Perfectas | Comprobaciones | Turnos | Tokens de entrada | Recorte de carga | $ Luna | $ Sonnet 5 | $ Opus 5 | frente a 0 |
|---|---|---|---|---|---|---|---|---|---|
0 | 100% | 100% | 2.2 | 3,314 | n/a | 0.00036 | 0.0033 | 0.0083 | n/a |
A | 100% | 100% | 2.0 | 3,004 (−9%) | n/a | 0.00038 | 0.0030 | 0.0073 | −12% |
B | 100% | 100% | 2.2 | 3,080 (−7%) | 62% | 0.00047 | 0.0026 | 0.0062 | −24% |
D | 100% | 100% | 2.0 | 2,819 (−15%) | 62% | 0.00056 | 0.0029 | 0.0068 | −17% |
Cómo se calcularon los precios
Se mide una vez y después se recalcula el precio. El recuento de tokens es la base; la factura de cada modelo se calcula con esos mismos recuentos y las tarifas correspondientes.
La fórmula de facturación se dedujo de los datos, no se dio por sentada. En las 192 ejecuciones, el coste observado del agente coincide
fresh_input × $0.25/M + cached_input × $0.02/M + output × $1.20/Mcon un error relativo mediano del 0.04%. De aquí se desprenden dos cosas. La caché de prompts estuvo activada automáticamente todo el tiempo, sin marcadores cache_control, y el 80% de los tokens de entrada fueron lecturas de caché. Además, cada token de entrada nuevo se factura al precio de escritura en caché, que es 1.25× el precio nominal de entrada. Por eso, en un bucle de varios turnos, prácticamente nunca se paga la tarifa nominal de $0.20/M.
Un modelo teórico anterior de la caché, según el cual las lecturas en el turno t equivalen al prefijo del turno t−1, subestimaba las lecturas reales de caché en un 19%. Se descartó y se optó por el desglose medido para cada turno.
| Modelo | Entrada | Salida | Lectura de caché | Escritura en caché |
|---|---|---|---|---|
openai/gpt-5.6-luna | $0.20/M | $1.20/M | $0.02/M | $0.25/M |
anthropic/claude-sonnet-5 | $2.00/M | $10.00/M | $0.20/M | $2.50/M |
anthropic/claude-opus-5 | $5.00/M | $25.00/M | $0.50/M | $6.25/M |
typesafe/jev-1.13 | $0.042/M | gratis | n/a | n/a |
| Variante | Luna | Sonnet 5 | Opus 5 | Parte de Jev, Opus 5 |
|---|---|---|---|---|
0 | $0.00182 | $0.01676 | $0.04191 | n/a |
A | $0.00166 (−9%) | $0.01479 (−12%) | $0.03688 (−12%) | 0% |
B | $0.00232 (+27%) | $0.01435 (−14%) | $0.03466 (−17%) | 2% |
D | $0.00221 (+21%) | $0.01253 (−25%) | $0.02995 (−29%) | 3% |
Como referencia, las mismas ejecuciones sin caché:
| Variante | Luna | Sonnet 5 | Opus 5 |
|---|---|---|---|
0 | $0.00348 | $0.03333 | $0.08332 |
A | $0.00316 | $0.02984 | $0.07450 |
B | $0.00368 | $0.02798 | $0.06874 |
D | $0.00356 | $0.02601 | $0.06362 |
Una de las hipótesis es conservadora, no neutral. OpenAI almacena en caché automáticamente y factura cada token de entrada nuevo al precio de escritura, tal como se observó. La caché de Anthropic es opcional: solo el contenido dentro de un punto de control cache_control se factura al precio de escritura; el resto, al precio normal de entrada. Por tanto, cobrar todos los tokens nuevos al precio de escritura sobreestima ligeramente las columnas de Anthropic. Si se recalculan los tokens nuevos al precio normal de entrada, la media de Opus 5 pasa de $0.04191 → $0.02995 (−29%) a $0.03823 → $0.02808 (−27%), y ninguna cifra por tarea varía más de 3 puntos.
Lo que esto no muestra
- Un solo modelo de agente. Todo se mide con
openai/gpt-5.6-lunay el nivel de razonamiento predeterminado. Los recuentos de tokens son el resultado medido, y las columnas de precios se calculan a partir de ellos. Un modelo distinto daría otros recuentos de tokens, no solo otros precios. - n = 6 por celda. Es suficiente para los recuentos de turnos y de tokens, que son casi deterministas. No basta para distinguir una calidad del 92 % de una del 96 %.
- Entornos de prueba, no API en directo. Las estructuras de las cargas útiles son fieles a las reales. Los endpoints reales tienen paginación, fallos parciales y límites de solicitudes que este entorno no pone a prueba.
- La misma persona escribió las tareas y las habilidades. La evaluación es determinista, pero el mundo no es adverso.
- No se auditó la calibración de Jev. Se midió cómo afectan sus puntuaciones a un agente, no si están bien calibradas en sentido estadístico.
- Una sola configuración de agente. Un bucle
whilecon llamadas a funciones. Los subagentes, las llamadas paralelas a herramientas y las sesiones de larga duración cambian los cálculos.

