Tu LLM no ejecuta nada: Function Calling explicado de verdad

La primera vez que armé un agente que "consultaba el clima", asumí lo obvio: el modelo llamaba a la API y me traía el dato. Me tomó un rato entender que el LLM nunca tocó esa API. Ni una vez.
Y ese malentendido es justo lo que separa a quien copia tutoriales de quien entiende lo que está construyendo. Así que vamos por partes.
El malentendido que casi todos arrastramos
Un modelo de lenguaje, por dentro, hace una sola cosa: predecir el siguiente token (el siguiente pedacito de texto). No tiene internet en vivo, no corre código, no consulta tu base de datos. Su conocimiento se congeló el día que lo entrenaron.
Entonces, ¿cómo hace un "agente" para reservar una cita o leer un saldo? No lo hace el modelo. Lo hace tu código. El function calling es el mecanismo que los pone de acuerdo.
El LLM no ejecuta la función. Decide cuál llamar y con qué datos, y te lo pasa como un JSON. Ejecutar es tu trabajo.

Piénsalo como un mesero, no como un cocinero
Imagina un restaurante. Tú (el usuario) le pides algo al mesero. El mesero no cocina: anota tu pedido en una comanda con un formato claro —plato, cantidad, término— y la pasa a la cocina. La cocina prepara y le devuelve el plato. El mesero te lo trae y te explica qué es.
El LLM es el mesero. La comanda es el JSON con los argumentos. La cocina es tu código (la API, la base de datos, la función real). El modelo es buenísimo entendiendo lo que quieres y escribiendo la comanda perfecta. Pero de la cocina no sabe nada, ni debería.
Ese es el clic: el modelo traduce lenguaje a una intención estructurada. Nada más. Y nada menos.

El ciclo completo, paso a paso
Cuando armas function calling, el flujo tiene cinco momentos. Vale la pena tenerlos claros porque aquí es donde la gente se confunde.

- Tú defines las herramientas. Cada una con un nombre, una descripción y un esquema de sus argumentos. Y mandas la pregunta del usuario.
- El modelo decide. ¿Puede responder solo o necesita una herramienta? Si la necesita, emite algo como
{ "name": "consultar_clima", "arguments": { "ciudad": "Lima" } }. - Tu código ejecuta la función real con esos argumentos.
- Le devuelves el resultado al modelo.
- El modelo integra y responde en lenguaje natural.
¿Y si tras el resultado el modelo decide llamar otra herramienta? Entonces vuelves al paso 2. Ese "pensar → actuar → observar → repetir" tiene nombre: es el patrón ReAct, el corazón de casi todos los agentes. De hecho, function calling es el "actuar" de ReAct: sin herramientas, ReAct no tiene manos. Le dedico el próximo post de la serie (te dejo el enlace al final).
Anatomía de una herramienta (spoiler: la descripción es un prompt)
Una herramienta tiene tres partes, y el modelo lee las tres para decidir:
- Nombre: el identificador, tipo
validar_cobertura. Un nombre con sentido ya ayuda a que el modelo lo elija bien. - Descripción: qué hace y cuándo usarla. Esto es lo más importante y lo que más se descuida.
- Parámetros: el esquema de los argumentos (tipos, obligatorios, valores permitidos).
Quédate con esto: la descripción de tu herramienta es un prompt. Si escribes "busca cosas", el modelo la usará mal o en el momento equivocado. Si escribes "verifica si un distrito está en la zona de reparto; úsala antes de cotizar", el modelo sabe exactamente cuándo dispararla. La descripción viaja al modelo y consume tokens, así que pocas herramientas bien descritas le ganan a muchas ambiguas.
Un ejemplo que puedes tocar
Primero la versión "cruda", para que veas la mecánica real:
// 1) Defines la herramienta (esquema):
{ "name": "validar_cobertura",
"description": "Verifica si un distrito está en la zona de atención. Úsala antes de cotizar.",
"parameters": { "type": "object",
"properties": { "distrito": { "type": "string" } },
"required": ["distrito"] } }
// 2) El modelo NO ejecuta. Emite esto:
{ "name": "validar_cobertura", "arguments": { "distrito": "Chaclacayo" } }
// 3) Tú ejecutas y le devuelves el resultado:
{ "role": "tool", "content": { "cubierto": true } }
// 4) Recién ahora el modelo responde:
// "Sí atendemos Chaclacayo. ¿Para qué fecha sería tu evento?"
En un framework como LangChain esto se ve más limpio, pero pasa exactamente lo mismo por debajo:
from langchain.tools import tool
# El docstring ES la descripción del esquema: lo que el modelo lee
# para decidir cuándo llamar la herramienta.
@tool
def validar_cobertura(distrito: str) -> str:
"""Verifica si el distrito está en la zona de atención. Úsala antes de cotizar."""
cubierto = distrito.strip().lower() in DISTRITOS
return {"distrito": distrito, "cubierto": cubierto}
Fíjate en el detalle que casi nadie te dice: ese docstring no es documentación para ti. Es contexto para el modelo. Cámbialo y cambia cómo tu agente decide.
Lo que cambió en 2026
Function calling existe desde que OpenAI lo lanzó en junio de 2023, pero maduró bastante. Tres cosas que hoy dan por sentado los que van en serio:
- Llamadas en paralelo. El modelo puede pedir varias herramientas en una sola respuesta y tú las ejecutas a la vez. En tareas con varias búsquedas, esto llega a ser ~4x más rápido que hacerlas en fila. Regla práctica: trata las llamadas como una lista, nunca asumas que viene una sola.
- Salida estructurada garantizada. Con el modo estricto, el proveedor te asegura que el JSON cumple tu esquema —sin campos faltantes ni inventados—. Antes fallaba a veces; hoy puedes confiar en él.
- MCP para no reescribir tus herramientas. El function calling es el mecanismo (cómo el modelo pide una tool). MCP es el estándar para publicar y reutilizar catálogos de herramientas entre apps y proveedores sin reprogramarlas cada vez (Anthropic lanzó MCP en noviembre de 2024).
¿Y cómo sabes qué modelo llama mejor a las herramientas? Para eso hay un benchmark serio: el Berkeley Function-Calling Leaderboard (BFCL) de UC Berkeley, que ya va por su v4 con evaluación agéntica y más de 67.000 casos reales. Es la mejor brújula pública para comparar modelos por su tool calling —no por marketing—.
Los errores que cuestan caro
Aquí es donde hablo por experiencia, no por teoría.

No confíes en los argumentos. El modelo puede alucinar un DNI, un monto absurdo o una fecha imposible. Antes de ejecutar, valida. Siempre.
El resultado de una herramienta es entrada no confiable. Si tu tool lee un documento o una página web, ahí puede venir escondida una instrucción maliciosa (prompt injection). Trata ese texto como dato, nunca como orden. Este tema da para un post entero sobre seguridad de agentes; está en la serie, abajo.
Pon un humano antes de lo irreversible. ¿Pagos, borrados, envíos? Confirmación humana. Un JSON no es autorización.
Y ponle un tope al bucle. Un agente que llama herramientas sin límite puede entrar en loop y quemarte miles de dólares en tokens sin que te des cuenta. Un máximo de iteraciones no es opcional.
La regla que resume todo: el dato duro siempre sale de la herramienta, nunca del modelo. Y toda acción con consecuencias pasa por una validación tuya.
Cuándo NO es function calling
Esto se confunde seguido, así que lo dejo claro:

- Salida estructurada solo te devuelve JSON con un formato fijo. No ejecuta nada.
- RAG recupera contexto para no alucinar. Es conocimiento, no acción.
- MCP es el protocolo para distribuir herramientas, no el acto de llamarlas.
- Un agente es todo junto en bucle: modelo + herramientas + memoria + control.
Confundirlos lleva a sobre-diseñar. Si lo que necesitas es un pago, quizá sea una simple API, no un agente autónomo.
Para cerrar
Function calling es de esas ideas que, una vez que hacen clic, cambian cómo ves a los agentes. El modelo no es un empleado que hace cosas: es un traductor brillante entre lo que quiere una persona y lo que tu código sabe ejecutar. Tú pones las manos; él pone el criterio para decidir cuándo usarlas.
Si estás armando tu primer agente, empieza por una sola herramienta, escribe su descripción como si fuera un prompt (lo es) y observa el JSON que emite el modelo antes de ejecutar nada. Ese momento —ver la comanda antes de que llegue a la cocina— es donde de verdad entiendes lo que estás construyendo.

Sigue la serie: "cómo se arma un agente, sin humo"
Function calling no vive solo. Es una pieza de un mapa más grande, y estos son los que le siguen la pista:
- ReAct — el bucle pensar → actuar → observar del que function calling es el "actuar". Sin tools, ReAct no tiene manos. (próximo)
- Structured Outputs — el primo del function calling: usa la misma maquinaria de JSON, pero solo devuelve datos, no ejecuta. Clave para extraer info confiable. (próximo)
- MCP (Model Context Protocol) — cómo publicar tus herramientas una vez y reutilizarlas entre apps y modelos sin reescribirlas. (próximo)
- Seguridad de agentes — por qué el resultado de una tool es entrada no confiable, y cómo frenar el prompt injection con guardrails y human-in-the-loop. (próximo)
- Cómo evaluar un agente — que no "acierte por suerte": se mide el camino (qué tools usó y en qué orden), no solo la respuesta. (próximo)
Referencias
- OpenAI — Function calling (guía oficial)
- OpenAI — Structured Outputs (ago 2024)
- Anthropic — Tool use (docs)
- Anthropic — Model Context Protocol (nov 2024)
- Google — Gemini function calling (docs)
- UC Berkeley — Berkeley Function-Calling Leaderboard (BFCL)
- Yao et al. — ReAct: Synergizing Reasoning and Acting in LLMs (2022)