Hay una frase que se repite en cada hilo sobre frameworks de IA: "te inyectan miles de tokens de prompts ocultos que tú no has escrito".
La he leído decenas de veces. Nunca con un número al lado.
Así que la medí. Levanté un endpoint falso que se hace pasar por la API de Anthropic, apunté a él el SDK oficial, el Vercel AI SDK y LangChain, y guardé el cuerpo exacto de la petición HTTP que cada uno manda por el cable.
El resultado no es el que esperaba, y probablemente tampoco es el que esperas tú.
Cómo lo medí
La idea es simple: si quieres saber qué manda una librería, no leas su código. Ponte en medio.
import http from "node:http";
const capturas = [];
const server = http.createServer((req, res) => {
let body = "";
req.on("data", c => (body += c));
req.on("end", () => {
capturas.push(body); // esto es lo que se manda de verdad
res.writeHead(200, { "content-type": "application/json" });
res.end(JSON.stringify({
id: "msg_x", type: "message", role: "assistant", model: "claude-opus-5",
content: [{ type: "text", text: "ok" }],
stop_reason: "end_turn", stop_sequence: null,
usage: { input_tokens: 1, output_tokens: 1 },
}));
});
});
await new Promise(r => server.listen(0, r));
const BASE = `http://127.0.0.1:${server.address().port}`;
Después, cada librería apuntando a BASE con la misma tarea: un mensaje de sistema idéntico, la misma pregunta y —en la segunda tanda— la misma herramienta.
Versiones medidas: @anthropic-ai/sdk 0.120.0, ai 7.0.77 con @ai-sdk/anthropic 4.0.41, y langchain 1.5.10 con @langchain/anthropic 1.5.8. Los números son de estas versiones; si lees esto dentro de seis meses, vuelve a correrlo.
Resultado 1: nadie inyecta un prompt oculto
Primera tanda, sin herramientas. Mensaje de sistema de 47 caracteres, escrito por mí.
| Librería | Cuerpo total | Campo system |
|---|---|---|
| SDK oficial de Anthropic | 194 B | 47 B |
| LangChain (modelo directo) | 210 B | 47 B |
| Vercel AI SDK | 246 B | 74 B |
LangChain manda exactamente mis 47 caracteres. Ni uno más. El SDK oficial, lo mismo.
Vercel AI SDK manda 74 en vez de 47, y esos 27 caracteres de diferencia no son prosa: es que envuelve el string en la forma de bloques de contenido, [{"type":"text","text":"…"}]. Estructura, no instrucciones.
Y ahora el dato que cierra el asunto. Repetí la prueba con el agente prefabricado de LangChain —el createAgent que viene de fábrica, justo la abstracción que se supone que te llena el contexto de basura— y el campo system de la petición venía así:
system = 0 bytes
Vacío. El agente prefabricado de LangChain no manda ningún prompt de sistema que tú no hayas puesto.
Sea cual sea el origen de la leyenda de los "1.500 tokens ocultos", no describe estas librerías en 2026.
Resultado 2: donde sí se paga es en los esquemas
Segunda tanda, misma tarea pero declarando una herramienta: get_weather, con un solo parámetro string y su descripción.
| Librería | Cuerpo total | system |
tools |
|---|---|---|---|
| SDK oficial de Anthropic | 393 B | 47 B | 213 B |
| LangChain (agente prefabricado) | 436 B | 0 B | 299 B |
| Vercel AI SDK | 556 B | 74 B | 294 B |
Aquí sí hay diferencia, y no está donde la buscaba todo el mundo: está en cómo cada librería serializa el esquema de la herramienta.
El SDK oficial manda el JSON Schema que tú escribiste, tal cual: 213 bytes. Vercel AI SDK y LangChain lo generan a partir de tu esquema de Zod, y el resultado es más verboso: 294 y 299 bytes. Un 38% y un 40% más para describir exactamente la misma función.
En el total de la petición: 393 bytes contra 556 del Vercel AI SDK. Un 41% más.
Qué significan de verdad 163 bytes
Aquí es donde hay que ser honesto en las dos direcciones.
En una llamada, no significa nada. 163 bytes son unos 40 tokens. Si tu agente hace diez peticiones al día, esta discusión es irrelevante y deberías dedicar el rato a otra cosa.
Pero no escala como una constante, escala con tus herramientas. El 40% no es de la petición: es del bloque de esquemas. Un agente serio no tiene una tool, tiene quince o veinte. Ese bloque va en cada turno del bucle, no una vez por conversación. Y si el prefijo de tu prompt cambia entre peticiones, además pierdes los aciertos de caché.
Así que el número que importa no es el mío: es el tuyo. Coge tu agente real, con tus tools reales, y mide el bloque tools de una petición. Si te sale un bloque de 6 KB repitiéndose en veinte turnos, ahí tienes una conversación que merece la pena. Cómo desglosar en qué se te va la factura lo conté en medir el consumo de tokens de un agente, y el efecto de cambiar de modelo con ese mismo contexto, en el coste de los subagentes.
Y la palanca real, una vez lo has medido, no es quitar el framework: es tener menos herramientas y mejor descritas. Ese criterio lo desarrollé al montar un servidor de herramientas para tu agente sin MCP.
Entonces, ¿framework o código directo?
Si has llegado hasta aquí esperando que te diga que quites el framework, malas noticias: el argumento de los tokens no sostiene esa decisión. La diferencia existe, es medible y es pequeña comparada con lo que de verdad decide.
Lo que sí decide:
Depurabilidad. Cuando un agente falla en producción necesitas ver el mensaje exacto que salió. Con el SDK directo pones un console.log en la llamada. Con capas por encima, tienes que aprender dónde mirar. No es imposible —el arnés de esta prueba son cuarenta líneas— pero es trabajo.
Retraso frente a la API. Los proveedores sacan capacidades nuevas constantemente. Con el SDK directo las usas el mismo día. Con una capa intermedia, esperas a que la abstraiga. Este es, en mi experiencia, el coste real de un framework, y no aparece en ninguna tabla de bytes.
Acoplamiento de tu dominio. Si la lógica de decisión de tu negocio vive dentro de las clases de un tercero, no eres dueño de tu arquitectura. Esto es lo mismo que llevamos treinta años diciendo de los ORM y de los frameworks de UI, y aplica igual.
Y en la otra dirección: hay problemas donde un grafo de estados expresa cosas que un while no expresa bien —ramificaciones, reanudar tras una pausa humana, estado explícito entre pasos—. Si tu bucle ya se está llenando de banderas, esa es la señal.
Si lo que quieres es el bucle explícito bien hecho, con control de pasos y detección de estancamiento, está entero en Agentic Loop en TypeScript.
Mide el tuyo antes de opinar
El arnés completo cabe en un archivo. Levanta el servidor de arriba, apunta tu cliente a BASE en lugar de a la API real, lanza una petición representativa y mira el cuerpo:
const cuerpo = capturas.pop();
const j = JSON.parse(cuerpo);
console.log("total :", cuerpo.length, "bytes");
console.log("system :", (j.system ? JSON.stringify(j.system).length : 0), "bytes");
console.log("tools :", (j.tools ? JSON.stringify(j.tools).length : 0), "bytes");
console.log("mensajes:", JSON.stringify(j.messages).length, "bytes");
Cuatro líneas y dejas de discutir de oídas. Y si el bloque de esquemas te sorprende, el sitio donde arreglarlo es el diseño de tus contratos: los patrones de Zod para que un esquema diga lo justo están en el curso de Zod para TypeScript.
Definir esas interfaces antes de escribir el agente es lo que evita acabar con veinte tools que nadie recuerda para qué son, y es la metodología del libro de Spec-Driven Development. El flujo completo con agentes CLI lo enseño en el curso Construye con IA.
En Dominicode Labs comparto las mediciones reales de los agentes que tengo corriendo.
La conclusión que me llevo no es "framework sí" ni "framework no". Es que llevábamos dos años repitiendo un número que nadie había comprobado, y que el sitio donde de verdad se te va el contexto —los esquemas de tus herramientas— no sale en ningún hilo.
Preguntas frecuentes
¿Es verdad que LangChain inyecta prompts ocultos en cada petición?
En las versiones medidas para este post, no. Con langchain 1.5.10 y @langchain/anthropic 1.5.8, tanto el modelo directo como el agente prefabricado mandan en el campo system exactamente lo que tú pones — y el agente prefabricado, cuando no le das mensaje de sistema, manda ese campo vacío. La afirmación de los "miles de tokens ocultos" no describe estas versiones.
¿Cuánto overhead añade entonces un framework?
En la prueba, con una sola herramienta declarada: el bloque tools pasó de 213 bytes con el SDK oficial a 294 con Vercel AI SDK y 299 con LangChain, un 38% y un 40% más. En el cuerpo total de la petición, 393 bytes frente a 556. La diferencia viene de generar el JSON Schema a partir de Zod, que sale más verboso que un esquema escrito a mano.
¿Cómo mido el overhead de mi propio agente?
Levanta un servidor HTTP local que responda con la forma de respuesta del proveedor, apunta tu cliente a esa URL con la opción baseURL, lanza una petición representativa y mide la longitud del cuerpo por campos: system, tools y messages. Son unas cuarenta líneas y te da el dato exacto de tu caso, que es el único que importa.
¿Merece la pena quitar el framework para ahorrar tokens?
Casi nunca. La diferencia medida es real pero pequeña frente a otras decisiones. Si vas a quitarlo, que sea por depurabilidad, por no ir con retraso respecto a las capacidades nuevas de la API o por no acoplar tu lógica de negocio a un tercero. El ahorro de tokens es el peor de los argumentos disponibles.
¿Por qué el bloque de tools pesa más que el prompt de sistema?
Porque describe una interfaz completa: nombre, descripción, tipos de cada parámetro, cuáles son obligatorios y las descripciones de cada campo. Y porque se manda en cada turno del bucle agéntico, no una vez por conversación. Con quince o veinte herramientas, ese bloque es la mayor parte del contexto fijo que pagas en cada llamada.

Leave a Reply