Diez años haciendo RPA y BPM me enseñaron algo con claridad: el flujo es el artefacto. Lo dibujas, lo versionas, lo auditas. Sabes exactamente qué va a pasar antes de que pase.
Un agente de IA rompe esa garantía a propósito. El modelo decide qué hacer, con qué argumentos, y cuándo terminar. Dos ejecuciones con el mismo input pueden tomar caminos distintos.
Quería datos, no la intuición del hype. Necesitaba saber cuándo esa inversión de control paga, y cuándo es puro costo.
El experimento
Construí tres sistemas para resolver las mismas tareas de análisis bancario (transacciones, políticas de comisiones, cálculos) — sobre datos sintéticos, en mi propio homelab:
- Un pipeline determinista: clasifica la intención con una llamada al LLM y enruta a una de tres rutas fijas.
- Un agente ReAct con tool calling nativo, sobre Qwen 2.5 7B corriendo en mi RTX 3070.
- La misma arquitectura de agente, pero probada también con Qwen 2.5 14B y con Claude Sonnet vía API — para separar “el diseño falla” de “el modelo de 7B no da”.
25 tareas, tres categorías: simples, compuestas (requieren combinar dos o tres herramientas) y trampa (irresolubles a propósito — la respuesta correcta es rehusar, no inventar).
El loop completo en una frase: el modelo piensa, actúa, observa el resultado de esa acción, y repite hasta decidir por su cuenta que ya tiene la respuesta final.
Lo que esperaba
Que el agente ganara en tareas compuestas — para eso existe, para combinar herramientas que un pipeline rígido no puede encadenar. Esperaba que pasara del 50% de éxito.
Sacó 0%.
Los números completos
210 ejecuciones reales. Cada celda es n=30 (10 tareas × 3 repeticiones) salvo trampa, que es n=15 (5 tareas × 3 repeticiones). Ni Qwen 2.5 14B ni Claude Sonnet se probaron en tareas simples ni trampa — la corrida de control se limitó a compuestas, por diseño, para controlar costo.
| Sistema | Categoría | n | Éxito | Tasa | LLM calls (avg) | Latencia p50 | Latencia p95 |
|---|---|---|---|---|---|---|---|
| Pipeline | Simple | 30 | 27 | 90.0% | 1.70 | 0.89s | 1.11s |
| Agente (7B) | Simple | 30 | 21 | 70.0% | 1.70 | 1.34s | 2.89s |
| Pipeline | Compuesta | 30 | 0 | 0.0% | 1.60 | 0.93s | 2.01s |
| Agente (7B) | Compuesta | 30 | 0 | 0.0% | 1.70 | 2.82s | 7.70s |
| Agente (14B) | Compuesta | 30 | 5 | 16.7% | 1.40 | 7.91s | 49.99s |
| Agente (Claude Sonnet) | Compuesta | 30 | 30 | 100.0% | 4.13 | 13.00s | 23.01s |
| Pipeline | Trampa | 15 | 12 | 80.0% | 1.60 | 0.95s | 1.46s |
| Agente (7B) | Trampa | 15 | 15 | 100.0% | 1.40 | 0.90s | 1.64s |
El p95 de 49.99s del 14B no es el modelo siendo lento — es el modelo no cabiendo. Mi RTX 3070 tiene 8GB de
VRAM; el 14B en Q4_K_M pesa ~10.3GB, así que Ollama hace offload parcial a CPU (confirmé vía ollama ps
que solo ~6.9GB del modelo quedan en GPU). Esa latencia refleja mi hardware al límite, no una propiedad del
modelo en condiciones normales — con VRAM suficiente para cargarlo entero, esperaría algo mucho más cercano
al 7B.
Cero ejecuciones (0/210) llegaron al límite de iteraciones sin que el modelo decidiera terminar. Y en las 207 llamadas reales a tools registradas en los traces — 52 del 7B (en sus 75 ejecuciones de las tres categorías), 14 del 14B (en sus 30 ejecuciones, solo compuestas — no corrió simples ni trampa) y 141 de Claude (también solo en sus 30 ejecuciones de compuestas) — cero fueron a una tool inexistente y cero tuvieron argumentos malformados. Los tres alcances son distintos (el 7B corrió las 25 tareas completas, 14B y Claude solo las 10 compuestas), así que no son directamente comparables entre sí en volumen — pero el resultado de cero errores de formato se sostiene igual en los tres. Con tool calling nativo, ninguno de los tres modelos falló la interfaz de las herramientas ni una sola vez. Fallaron en otra parte.
Contra mis hipótesis, con números
| Hipótesis | Predicción | Resultado real |
|---|---|---|
| H1 — pipeline gana en simples a 1/3 del costo | ~95% vs ~80%, agente 3x más barato | 90% vs 70% (dirección correcta) — pero el costo en llamadas LLM fue igual (1.70 vs 1.70), no un tercio |
| H2 — agente pasa el 50% en compuestas | >50% de éxito | 0% — refutada con fuerza. Causa raíz abajo |
| H3 — agente 7B alucina en al menos 1/5 tareas trampa | ≥1 alucinación de 5 | 0 alucinaciones de 15 ejecuciones — refutada, a favor del agente |
| H4 — Etapa A falla formato 10-25%, Etapa B baja de 5% | Etapa B sustancialmente mejor | No medida a esta escala (solo corrí Etapa A manualmente, 1 ejecución) — queda pendiente, ver Limitaciones. Etapa B: 0 errores de formato en sus 207 llamadas reales combinadas (7B + 14B + Claude) |
Para H3 específicamente: el agente de 7B nunca inventó un saldo, una tasa o un dato que no existiera — rechazó las 15 tareas trampa correctamente. El pipeline determinista rechazó 12 de 15 (ver la sorpresa del año hardcodeado, más abajo). El 100% de Claude Sonnet en la tabla de arriba es solo sobre tareas compuestas — nunca se probó contra las tareas trampa, así que no puedo (todavía) decir que “nunca alucina” en general, solo que no lo hizo en las 30 tareas donde sí se midió.
Lo que realmente pasó en compuestas
En ninguna de las 30 ejecuciones del agente 7B, ni en ninguna de las 30 del 14B, se llamó a la herramienta de búsqueda documental. Ni una sola vez, entre los dos modelos combinados — 0 de 60.
Esto es un trace real, completo, de las 3 repeticiones de la misma tarea contra el 7B (“según la política de comisiones vigente, ¿cuánto debió pagar C-102 por sus transacciones de marzo 2026?”):
Repetición 1: → tool: obtener_transacciones(cliente_id=C-102, desde=2026-03-01, hasta=2026-03-31) ← Observation: [transacciones reales de C-102...] → Final: "Ahora que tenemos las transacciones de C-102 en marzo de 2026, necesitamos saber cuáles comisiones se aplican... Sin esa información específica, no puedo calcular el monto total de comisiones. No puedo responder esto."
Repetición 2: → tool: obtener_transacciones(cliente_id=C-102, desde=2026-03-01, hasta=2026-03-31) ← Observation: [transacciones reales de C-102...] → Final: "Ahora que tengo las transacciones de C-102... necesito conocer la política actual de comisiones para poder calcular cuánto debió pagar."
Repetición 3: → Final (sin ninguna tool call): "Para responder a tu pregunta, necesito conocer las transacciones... no tengo información disponible sobre las comisiones vigentes... No puedo responder esto."Tenía buscar_documentos disponible, con una descripción que dice literalmente “busca en la base documental interna y devuelve pasajes relevantes”. La necesitaba. La nombra casi textualmente en su propio razonamiento (“necesito conocer la política de comisiones”). No la llamó ni una vez en 30 intentos.
En las tareas donde sí actuó con datos completos, a veces resolvió la aritmética mentalmente en vez de usar la calculadora — y ahí sí se equivocó: dijo que un cliente gastó $497.400 en una tarea simple, cuando la cifra real y verificable en los datos era $507.800.
Con Claude Sonnet, mismo agente, mismas tools, mismo prompt: encadenó buscar_documentos + obtener_transacciones + calcular sin que se lo pidiera explícitamente, delegando cada cálculo intermedio a la herramienta en vez de hacerlo “de memoria”. 100% en las 30 ejecuciones de compuestas.
Los cuatro modos de falla (no tres)
La lectura obvia es “el modelo chico falla más”. La lectura útil es cómo falla, porque no es un solo modo:
- Elegir la tool equivocada — 0 casos en las 207 llamadas reales a tools (52 del 7B, 14 del 14B, 141 de Claude).
- Formatear mal los argumentos — 0 casos con tool calling nativo. (Con parsing de texto libre sí pasa — lo documenté en el capítulo, pero con una sola ejecución manual, no a esta escala.)
- Alucinar el resultado en vez de delegarlo — el caso de los $497.400. El modelo tenía el dato correcto en el contexto y calculó mal de todas formas.
- No actuar en absoluto — dar por sentado que la información no está disponible, sin intentar la herramienta que la conseguiría. 0 de 60 intentos combinados (7B + 14B) en tareas que literalmente requerían esa tool.
El modo 4 es el que no esperaba y el que más me interesa. No es “el modelo ejecuta mal la tool” — es “el modelo ni siquiera considera que la tool aplica”. Ninguna de mis cuatro hipótesis lo anticipaba.
Y el pipeline “aburrido” también tuvo su sorpresa
El pipeline determinista rechazó bien 4 de 5 categorías de tareas trampa. En la quinta, falló las tres repeticiones, porque mi código fijaba el año en 2026 sin extraerlo de la pregunta. Una tarea sobre marzo de 2027 devolvió, con total confianza, datos reales de 2026.
El agente, que deja que el LLM extraiga la fecha completa como argumento, no cometió ese error ni una vez.
La lección no es “el pipeline es peor”. Es que forzar el orden no elimina el riesgo de alucinación — lo traslada. De “el modelo inventa” a “el programador asumió algo que no siempre es cierto”.
Ese segundo tipo de error es silencioso. No hay ningún log de “esto se ve raro”. El código hace lo que se le dijo que hiciera.
Limitaciones (y el próximo experimento)
Antes de sacar conclusiones grandes de un 0%, dos confounders que no controlé en este experimento — y uno de los dos tiene evidencia directa, no solo sospecha.
- El system prompt le da al modelo una salida verbatim, y el modelo la usa literal. El prompt dice: “Si la información no está disponible con tus herramientas, di explícitamente ‘no puedo responder esto’.” La respuesta real del 14B al rendirse: “No puedo responder esto. La información sobre políticas de comisiones específicas… no está disponible.” No es una frase parecida — es la frase exacta que el prompt le ofreció, usada como vía de escape antes de intentar la herramienta que sí tenía la respuesta. El modelo no “decidió” que la tarea era irresoluble de forma independiente. Repitió la salida que yo mismo le di.
- La descripción de
buscar_documentoses genérica. Dice “busca en la base documental interna y devuelve pasajes relevantes” — no menciona que ahí vive la política de comisiones, ni da un ejemplo de qué tipo de pregunta la necesita.
El Capítulo 2 es exactamente esto: una ablación sobre diseño de tools y prompts, con el mismo modelo de 7B, para separar “el modelo no puede” de “el modelo no tenía por qué saber que debía intentarlo” — y para dejar de ofrecerle al modelo una frase de escape tan cómoda de repetir. Si el 7B mejora sustancialmente con mejores descripciones y un prompt sin vía de escape verbatim, la conclusión de este post cambia — y esa corrección se documenta acá mismo, en un bloque “Actualización” fechado, no editando en silencio el texto de arriba.
Un tercer pendiente, más chico pero igual de real: H4 (fallos de formato en Etapa A textual vs. Etapa B nativa) quedó sin medir a escala en este experimento — solo tengo una ejecución manual de referencia. No la voy a dejar como hipótesis colgada indefinidamente. El Capítulo 2 la resuelve corriendo Etapa A sobre las 10 tareas compuestas con n decente, o la retira explícitamente del registro con una línea fechada si no alcanza el tiempo — pero una de las dos, no un silencio.
Lo que me llevo
Cinco horas armando el harness. 210 ejecuciones reales. El hallazgo más valioso no estaba en ninguna de mis cuatro hipótesis iniciales. Fue una pregunta nueva: ¿cuánta capacidad de modelo necesito para justificar la agencia que le estoy cediendo?
Con este diseño puntual de agente y de tools, la respuesta con 7B fue “no alcanza, para esta tarea”. Con un frontier model, sí. En un punto intermedio está la frontera real, donde un Tech Lead tiene que decidir si vale la pena — el 14B mostró esa frontera con un 16.7% que no es ni fracaso total ni éxito.
Todavía tengo que responder si esto vale para banca regulada, y dónde queda la auditabilidad. También qué pasa cuando el agente tiene que planificar en vez de solo reaccionar, y si un mejor diseño de tools cierra la brecha del modo de falla 4. Eso viene en los próximos capítulos.