Function calling: cómo conectar un LLM con tus funciones
Aprende cómo conectar un LLM con tus funciones: un ejemplo completo, las diferencias entre OpenAI, Anthropic y Gemini, y cuándo usar salidas estructuradas.
Publicado el

El function calling, o llamada a funciones, permite que un modelo de lenguaje de gran tamaño (LLM) solicite tareas a tu software. La separación de responsabilidades tiene 3 partes: el modelo propone una llamada estructurada, tu código la valida y la ejecuta, y tú le devuelves el resultado. Conectar una base de datos consiste en construir esa separación, no en darle al modelo la contraseña de acceso.
¿Cómo funciona el function calling?
El modelo genera una solicitud. Tu aplicación realiza la operación. Si vas a conectar un LLM con una API o una base de datos, esta es la distinción más útil que conviene tener clara antes de escribir código.
Piensa en la comanda de un restaurante. Quien atiende la mesa puede pedir un plato, pero la comanda no cocina nada. En la cocina revisan el pedido, preparan lo que pueden y comunican el resultado. En tu aplicación, la llamada a una herramienta es la comanda; la función es la cocina.
Al modelo le proporcionas un esquema de herramienta: una descripción de la operación disponible y de los campos de entrada que acepta. El modelo puede responder con el nombre de la función y sus argumentos, es decir, los valores que deben ocupar esos campos. Tu aplicación comprueba la solicitud, invoca la función y devuelve el resultado para que el modelo pueda responder o pedir otra operación. La guía de llamada a funciones de Google asigna explícitamente la ejecución a tu aplicación.
Una herramienta puede tanto leer como escribir. Consultar un pedido, buscar en una colección de documentos o comprobar la disponibilidad son operaciones de herramientas aunque no modifiquen nada. Para una primera integración, conviene empezar por una consulta de alcance limitado: permite examinar todo el recorrido sin introducir una transacción que luego haya que deshacer.

Function calling y tool calling: ¿hay alguna diferencia?
Cuando se trata de funciones propias, ambos términos suelen describir el mismo mecanismo. OpenAI utiliza las dos denominaciones, y Anthropic señala que el uso de herramientas también recibe el nombre de function calling. El término más amplio, «herramienta», puede abarcar tanto capacidades alojadas por el proveedor como funciones que tú implementas. Lo decisivo es dónde se ejecuta la operación: si la función consulta tu propia base de datos, tu aplicación es responsable de ejecutarla.
La documentación de los tres proveedores que veremos a continuación permite concretar esa distinción. Sus formatos de mensaje son diferentes, por lo que conviene usar juntos los formatos de solicitud y de resultado de cada proveedor.
Un ejemplo mínimo de llamada a funciones de principio a fin
Expón una función para consultar el estado de un pedido y devuelve únicamente el estado que proporcione la base de datos. El siguiente ejemplo utiliza un pedido inventado a propósito, ORD-1042, en una base de datos SQLite local. Es un dato de prueba con fines didácticos, no un registro de cliente ni una respuesta observada del modelo.
Function calling con OpenAI: el ciclo completo
La documentación de llamada a funciones de OpenAI muestra el ciclo completo con la Responses API: declarar la función, recibir una function_call, ejecutar tu código y devolver un function_call_output con el mismo call_id.
Instala el SDK de Python con python -m pip install openai, configura OPENAI_API_KEY en tu entorno y guarda este código como order_tool.py. El ejemplo utiliza gpt-6-astra, el modelo que aparece en el ejemplo de Responses de la documentación actual; eso no significa que sea el único modelo adecuado. Al ejecutar el script se envían solicitudes reales a la API, mientras que la base de datos permanece en memoria.
import json
import re
import sqlite3
from openai import OpenAI
client = OpenAI()
model = "gpt-6-astra"
# Demo identity. In a web app, obtain this from your authenticated session.
tenant_id = "tenant_demo"
db = sqlite3.connect(":memory:")
db.execute("CREATE TABLE orders (tenant_id TEXT, order_id TEXT, status TEXT)")
db.execute(
"INSERT INTO orders VALUES (?, ?, ?)",
(tenant_id, "ORD-1042", "shipped"),
)
# The tool schema: a name, a purpose, and an input contract.
tool = {
"type": "function",
"name": "get_order_status",
"description": (
"Look up the current status of an existing order by order ID. "
"Use for status questions, not refunds or address changes. "
"Returns the order ID and status, or an error."
),
"strict": True,
"parameters": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "The order ID supplied by the user, such as ORD-1042.",
}
},
"required": ["order_id"],
"additionalProperties": False,
},
}
def execute(name, raw_arguments):
if name != "get_order_status":
return {"error": "unknown_tool"}
try:
args = json.loads(raw_arguments)
except (json.JSONDecodeError, TypeError):
return {"error": "invalid_arguments"}
if not isinstance(args, dict) or set(args) != {"order_id"}:
return {"error": "invalid_arguments"}
order_id = args["order_id"]
if not isinstance(order_id, str) or not re.fullmatch(r"ORD-[0-9]+", order_id):
return {"error": "invalid_order_id"}
row = db.execute(
"SELECT status FROM orders WHERE tenant_id = ? AND order_id = ?",
(tenant_id, order_id),
).fetchone()
if row is None:
return {"error": "order_not_found"}
return {"order_id": order_id, "status": row[0]}
history = [{"role": "user", "content": "What is the status of order ORD-1042?"}]
response = client.responses.create(
model=model,
input=history,
tools=[tool],
tool_choice={"type": "function", "name": "get_order_status"},
parallel_tool_calls=False,
)
# Keep every output item, including any reasoning items.
history.extend(response.output)
calls = [item for item in response.output if item.type == "function_call"]
if len(calls) != 1:
raise RuntimeError("Expected one tool call; inspect the response before continuing.")
call = calls[0]
result = execute(call.name, call.arguments)
history.append({
"type": "function_call_output",
"call_id": call.call_id,
"output": json.dumps(result),
})
answer = client.responses.create(
model=model,
input=history,
tools=[tool],
tool_choice="none",
instructions="Answer from the tool result. If it contains an error, report the failure.",
)
print(answer.output_text)
db.close()Este ejemplo, limitado de forma deliberada, realiza 2 solicitudes al modelo y 1 consulta a la base de datos cuando todo funciona correctamente. En la primera solicitud obliga a usar la consulta prevista y en la segunda desactiva las llamadas adicionales a herramientas. Así queda a la vista el funcionamiento del mecanismo; un asistente de uso general también tendría que gestionar solicitudes para las que ninguna herramienta sea adecuada, falte información o haga falta otra consulta.
El tenant_id no aparece en el esquema de la herramienta porque la aplicación ya sabe quién ha iniciado sesión. La consulta a la base de datos utiliza esa identidad de confianza junto con el identificador del pedido solicitado. Convertir la identidad en un argumento aportado por el modelo eliminaría la separación de responsabilidades que el ejemplo pretende enseñar.
La llamada del modelo y el resultado que devuelves
La solicitud y el resultado son mensajes distintos, vinculados por un identificador de llamada. Una llamada representativa tendría este aspecto. Los identificadores y los valores son ilustrativos; no se trata de una respuesta capturada de la API.
{
"type": "function_call",
"id": "fc_demo",
"call_id": "call_demo",
"name": "get_order_status",
"arguments": "{\"order_id\":\"ORD-1042\"}"
}Cuando la función encargada de ejecutar la solicitud devuelve el estado del pedido de prueba, la aplicación añade este resultado. En una respuesta real, copia el valor de call.call_id; nunca inventes uno nuevo.
{
"type": "function_call_output",
"call_id": "call_demo",
"output": "{\"order_id\":\"ORD-1042\",\"status\":\"shipped\"}"
}Ahora el modelo dispone de datos que respaldan una respuesta como «El pedido ORD-1042 ha sido enviado». El estado procede de la base de datos. La aportación del modelo consiste en convertir la solicitud en argumentos y los datos recibidos en una respuesta.
La misma idea en la documentación de los tres proveedores
El patrón de ejecución se mantiene entre proveedores; el formato de intercambio, no. La siguiente comparación se verificó con la documentación vigente de los proveedores el 17 de octubre de 2026. Distingue sus ejemplos actuales para evitar tratar como intercambiables campos que tienen nombres parecidos.
Uso de herramientas con Anthropic
La documentación de uso de herramientas de Anthropic define las entradas de tu función mediante input_schema. Si se trata de una herramienta de cliente, tu código procesa el bloque tool_use del asistente y envía un tool_result dentro del siguiente mensaje de usuario, conservando el mensaje del asistente en la conversación.
Esa documentación deja clara la separación: las herramientas de cliente se ejecutan en tu aplicación y las de servidor, en la infraestructura de Anthropic. Por tanto, una herramienta de búsqueda alojada por el proveedor no demuestra que Claude pueda ejecutar directamente una función de tu base de datos privada. Esa implementación sigue siendo responsabilidad tuya.
Llamada a funciones con Gemini
La documentación de llamada a funciones de Gemini de Google también separa la solicitud del modelo de la ejecución por parte de la aplicación. Su guía actual utiliza la Interactions API, con pasos function_call y function_result, y previous_interaction_id para continuar la interacción.
Sigue el ejemplo que corresponda a la API que estés utilizando. Copiar la declaración de una API y el mensaje de resultado de otra no aporta portabilidad. Conserva la operación común, como get_order_status, y adapta tanto su declaración como el formato del mensaje de resultado.
Por qué las llamadas a herramientas sostienen el ciclo de un agente
Un agente que utiliza herramientas elige una tarea, recibe el resultado y decide qué hacer después, una y otra vez. La llamada a funciones conecta esa decisión con una operación que tu software puede realizar.
Por ejemplo, un asistente de pedidos podría consultar un envío, examinar la referencia del transportista recibida y pedir después la información de seguimiento antes de responder. La segunda operación depende del resultado de la primera. Ese ciclo de retroalimentación es más útil que pedirle al modelo que invente todos los pasos de antemano.
Las recomendaciones de arquitectura de agentes de Anthropic distinguen entre flujos de trabajo fijos y agentes que deciden por sí mismos cómo utilizar las herramientas. También describen los resultados de las herramientas y las condiciones de parada como partes del ciclo.
Decir que esto es «la base de todo agente» sirve como simplificación, pero tiene sus límites. La documentación no establece que todos los sistemas llamados agentes utilicen una API concreta de llamada a funciones. La idea que perdura es el ciclo que conecta el modelo con la acción. Una consulta aislada puede seguir siendo un flujo de trabajo fijo; no necesita un planificador autónomo.
Tres problemas habituales en producción
La calidad del esquema, la selección de herramientas y la validación de argumentos son problemas distintos. Resolver uno no demuestra que los demás estén resueltos.
Esquemas ambiguos: el contrato permite interpretaciones equivocadas
Un campo llamado id no le indica al modelo si necesitas un número de pedido, un identificador de cliente o una referencia de envío. Una cadena sin restricciones llamada action abre la puerta a valores que tu función podría no reconocer. Mejora el contrato antes de añadir más instrucciones a su alrededor.
Pon nombres precisos a los parámetros, explica su significado y usa una enumeración cuando solo se acepte un conjunto fijo de valores. Mantén el alcance de la primera herramienta lo bastante acotado como para explicar su propósito en una frase sencilla. En el ejemplo, order_id es explícito y la descripción excluye los reembolsos y los cambios de dirección.
El modo estricto de OpenAI exige additionalProperties: false en los objetos y que todas las propiedades aparezcan en required; si un valor puede faltar, se puede admitir null. Su guía recoge estos requisitos del modo estricto. Google también documenta restricciones de esquema, por lo que un esquema aceptado por tu validador local no será necesariamente aceptado por todas las API de modelos.
El límite: un esquema puede restringir la representación, pero un identificador de pedido válido puede corresponder al pedido equivocado. Esa comprobación le toca a la aplicación.
El modelo elige la herramienta equivocada: argumentos válidos, operación incorrecta
Un cliente que pregunta «¿Qué pasó con mi reembolso?» necesita consultar su estado, no iniciar un reembolso nuevo. Si las dos herramientas dicen que «gestionan reembolsos», la elección queda abierta a interpretaciones.
Describe cuándo debe utilizarse cada herramienta y cuándo no, y expón solo las operaciones adecuadas para la tarea y el usuario actuales. Las recomendaciones de Anthropic para definir herramientas aconsejan expresamente explicar su propósito, el significado de los parámetros, los límites de uso y las limitaciones.
Cuando tu aplicación ya sabe qué operación debe realizarse, utiliza un control de selección de herramientas compatible o llama directamente a esa operación. El ejemplo fuerza una consulta conocida con fines didácticos; no lo conviertas en una regla según la cual «cada mensaje del usuario debe activar una herramienta». Un saludo o una pregunta incompleta sobre un pedido pueden requerir una respuesta conversacional.
El límite: unos argumentos bien formados no permiten saber si el modelo eligió la acción de negocio correcta. Evalúa la herramienta seleccionada con solicitudes representativas de los usuarios, incluidos casos en los que no debería producirse ninguna llamada.
Argumentos sin validar: la forma es correcta, pero el acceso no
La función que procesa la llamada es un punto de entrada. Comprueba que la función solicitada figure en una lista explícita de funciones permitidas, analiza sus argumentos, valida su estructura y su significado, y controla el acceso con la identidad autenticada por tu aplicación.
En el ejemplo de los pedidos, una prueba de fallo útil consiste en solicitar un pedido perteneciente a otro tenant, es decir, a otra cuenta de cliente. La consulta no debe devolverlo aunque su identificador sea una cadena perfectamente válida. Otras pruebas consisten en omitir el identificador del pedido, incluir un campo inesperado o solicitar una operación que el código encargado de procesarla no implemente.
La descripción general de Anthropic advierte que, si falta información, el modelo puede inferir valores para los argumentos. No des por hecho que un campo obligatorio demuestra que el usuario proporcionó su valor. Si la acción tiene consecuencias relevantes, compara la operación solicitada y sus entradas con lo que el usuario autorizó realmente.
Si la ejecución falla, devuelve un error reconocible. Que se agote el tiempo de espera no demuestra que la operación no se haya realizado: antes de reintentar una escritura, utiliza un mecanismo de idempotencia en la aplicación, es decir, una forma de reconocer que se está intentando la misma operación y evitar repetir sus efectos. Estas son recomendaciones de implementación, no garantías de la API del modelo.
¿Cuándo conviene usar salidas estructuradas?
Usa salidas estructuradas cuando necesites dar una forma concreta a una respuesta basada en información que ya tienes. Usa una herramienta cuando necesites una operación externa. Un clasificador de mensajes de soporte que devuelve una categoría y un nivel de urgencia puede generar una salida estructurada. Un asistente que necesita el estado actual de un pedido debe obtenerlo mediante una consulta.
La guía de Structured Outputs de OpenAI distingue entre conectar las funciones de una aplicación y dar formato a la respuesta del modelo. También explica que los esquemas estrictos de funciones se apoyan internamente en Structured Outputs. Son capacidades complementarias, no productos mutuamente excluyentes.

Supongamos que ya proporcionaste el registro de un pedido y solo necesitas {order_id, status, explanation} para tu interfaz. Basta con una respuesta estructurada. Si falta el registro o hay que actualizarlo, realiza primero la consulta. Después también puedes estructurar la respuesta final.
Un objeto JSON que afirma que se envió un correo sigue siendo solo un objeto de salida. Para enviar el correo hace falta ejecutar una operación y disponer de un resultado que puedas comprobar.
Function calling frente a MCP
El function calling gestiona la solicitud de una operación por parte del modelo. Model Context Protocol (MCP) ofrece una interfaz común para exponer herramientas y otros datos de contexto a aplicaciones compatibles. Puedes conectar una función directamente con una aplicación antes de incorporar un servidor de herramientas independiente.
MCP y tool calling: ¿cuándo conviene compartir herramientas?
Si varias aplicaciones necesitan la misma consulta de pedidos, un servidor MCP puede exponer la herramienta para que puedan descubrirla e invocarla. La documentación de arquitectura de MCP describe tools/list para el descubrimiento y tools/call para las solicitudes de ejecución. El servidor sigue necesitando una implementación y controles de acceso.
Para dar ese siguiente paso, lee qué es MCP y cómo encajan su host, su cliente y su servidor. Una vez que funcione la consulta directa, la guía de implementación de un servidor MCP explica cómo agrupar capacidades para reutilizarlas. Incorporar MCP no elimina la necesidad de validar la operación solicitada.
Qué se exagera sobre esta tecnología
Superar la validación de un esquema demuestra que se cumple una restricción de formato, no que la tarea esté terminada. La operación puede ser inadecuada, el registro puede ser inaccesible o el servicio subyacente puede no estar disponible. Una frase final bien redactada no resuelve ninguna de esas cuestiones.
Tampoco basta con una lista de herramientas para crear un agente. Sigues necesitando reglas que determinen qué herramientas están disponibles, cómo se incorporan sus resultados a la conversación, cuándo detenerse y qué hacer tras un error. Un framework puede agrupar ese trabajo, pero la política de ejecución sigue siendo una decisión de diseño.
El primer objetivo útil es modesto: que la solicitud llegue a la función prevista, que solo se devuelvan datos permitidos y que la respuesta refleje ese resultado. Haz visible ese recorrido antes de ampliar los permisos del sistema.
Qué llevar primero a producción
Empieza por una operación de solo lectura que responda a una pregunta frecuente de los usuarios. El ejemplo del estado de un pedido es un patrón útil porque permite examinar con facilidad tanto el resultado esperado como los límites de acceso.
Si desarrollas el producto, empieza ahora si la respuesta depende de datos que tu aplicación puede obtener de forma fiable. Conserva un flujo de trabajo fijo cuando ya se conozca la siguiente operación. Antes de permitir escrituras elegidas por el modelo, necesitas permisos explícitos, gestión de fallos y una forma de evitar efectos repetidos.
Si operas el sistema, revisa qué se ejecutó y qué se devolvió. Registra la herramienta seleccionada, el resultado de la validación, el estado de la ejecución y los datos que permiten correlacionar la llamada, sin incluir argumentos sensibles en los registros habituales. Define tiempos de espera y un número máximo de rondas de herramientas adecuados para la tarea; no dejes que el ciclo conversacional continúe sin límites.
Si evalúas una compra, pide al equipo de implementación que muestre una consulta denegada y una operación fallida, además de una respuesta correcta. Si el producto solo resume información que ya se le ha proporcionado, quizá no necesite llamada a funciones. Una salida estructurada o la generación de texto convencional pueden ser suficientes.
Para empezar el lunes: implementa una consulta de alcance limitado, prueba con un registro permitido, otro inaccesible y una solicitud incompleta, y examina qué resultado se devuelve al modelo en cada caso. Amplía la lista de herramientas solo cuando puedas explicar por qué se aceptó o rechazó cada solicitud.
Preguntas frecuentes
¿Qué es el function calling?
Es un mecanismo que permite a un modelo solicitar una operación indicando el nombre de una función y sus argumentos. Si la función la defines tú, tu aplicación la ejecuta y devuelve el resultado a la conversación.
¿En qué se diferencian tool calling y function calling en un LLM?
Cuando se trata de funciones propias, los proveedores suelen usar ambos términos indistintamente. El uso de herramientas también puede incluir capacidades alojadas por el proveedor, así que comprueba dónde se ejecuta la operación en lugar de deducirlo por el nombre.
¿Cuál sería un ejemplo de llamada a funciones?
Un modelo solicita get_order_status con order_id igual a ORD-1042. Tu código valida la solicitud, comprueba el acceso, consulta el pedido y devuelve su estado. El pedido y el estado que aparecen en este artículo son datos inventados para el ejemplo.
¿Cómo se usa el function calling en GPT-5?
Sigue el flujo documentado de Responses con un modelo compatible disponible en tu proyecto: envía las definiciones de las herramientas, procesa los elementos de salida de llamada a función y devuelve los resultados con los identificadores de llamada correspondientes. Conserva los elementos de razonamiento al continuar la conversación. El ejemplo ejecutable anterior utiliza el modelo que aparece en la guía actual, sin dar por hecho que tu cuenta tenga habilitado un modelo concreto de GPT-5.
Para recibir guías prácticas sobre cómo desarrollar con IA, suscríbete al boletín.
- Publicado
- Categoría
- Build
- Idioma










