Al final de esta guía, podrás definir una herramienta, enviarla a OpenAI, leer la llamada a la herramienta que devuelve el modelo y ejecutar tu propia función con los argumentos estructurados que te proporciona. También activarás el modo estricto y las llamadas paralelas, luego verificarás y simularás el lado de la herramienta con Apidog para que confíes en la salida antes de que llegue a producción. Mantén la documentación de llamadas a funciones de OpenAI abierta en otra pestaña como fuente de la verdad, y consulta nuestra introducción sobre cómo construir agentes con el SDK de Agentes de OpenAI para una visión más general.
Lo que necesitas antes de empezar
La llamada a funciones (a menudo llamada llamada a herramientas) es cómo un modelo se conecta a tu código y sistemas externos. Tú describes las funciones que expone tu aplicación, el modelo lee la solicitud del usuario y, cuando una función encaja, devuelve el nombre de la función más un objeto JSON de argumentos. El modelo nunca ejecuta nada por sí mismo. Te entrega una solicitud estructurada, y tu código hace el trabajo.
Esa división es lo que debes tener en cuenta mientras construyes. El modelo elige la intención y rellena los parámetros. Tú mantienes el control de la ejecución. Un mensaje como "obtener el clima en París" se convierte en una llamada limpia get_weather({"location": "Paris, France"}) en lugar de un párrafo que tendrías que analizar manualmente.
Para seguir adelante, necesitas una clave API de OpenAI y una función en tu propio código que quieras que el modelo pueda activar. Una cosa más que decidir de antemano: en qué endpoint estás. La misma característica funciona en dos lugares. La API de Chat Completions más antigua la soporta, y también la API de Responses más nueva, que unifica lo que antes estaba dividido entre Chat Completions y la API de Assistants. Las formas difieren ligeramente, y los pasos siguientes cubren ambas.
Paso 1: Define tu herramienta
Una herramienta es una definición de función que el modelo puede leer. Le das un nombre, una descripción y un Esquema JSON para los argumentos. La descripción hace un trabajo real aquí. Le dice al modelo cuándo debe usar la función, así que escríbela como una instrucción, no como una etiqueta.
Aquí tienes una definición de herramienta en el formato de Chat Completions, donde la función reside bajo un contenedor function:
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Obtiene el clima actual de una ciudad. Úsalo cuando el usuario pregunte por la temperatura o las condiciones.",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "Ciudad y país, p. ej. Bogotá, Colombia"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"]
}
},
"required": ["location"],
"additionalProperties": false
}
}
}
La API de Responses aplana esto. Los campos name, description, parameters y strict se encuentran en el nivel superior del objeto de la herramienta, sin una clave function anidada. Misma información, menos capas.
Si ya mantienes una especificación OpenAPI para el servicio subyacente, las formas de los parámetros se trasladan casi directamente. Nuestro tutorial sobre la generación de colecciones de pruebas a partir de especificaciones OpenAPI muestra cómo ese trabajo de esquema rinde frutos dos veces.
Paso 2: Realiza tu primera solicitud
Envía tu herramienta al modelo junto con el mensaje del usuario. Una solicitud completa de Chat Completions que hace esto se ve así:
curl https://api.openai.com/v1/chat/completions \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4.1",
"messages": [
{"role": "user", "content": "¿Cuál es el clima en París ahora mismo?"}
],
"tools": [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Obtiene el clima actual de una ciudad.",
"parameters": {
"type": "object",
"properties": {
"location": {"type": "string"}
},
"required": ["location"],
"additionalProperties": false
}
}
}
]
}'
El array tools contiene cada función que quieres exponer en este turno. El modelo lee el mensaje del usuario, decide si alguna herramienta encaja y responde. Cuando selecciona una, recibes una llamada a la herramienta en lugar de prosa, que es lo que leerás en el siguiente paso.
Paso 3: Lee la llamada a la herramienta que devuelve el modelo
Cuando el modelo decide llamar a una función, no devuelve texto. Devuelve una llamada a una herramienta que lees de la respuesta.
En Chat Completions, el mensaje del asistente contiene un array tool_calls. Cada entrada tiene un id, un type de function y un objeto function con el name y una cadena arguments:
{
"id": "call_12345xyz",
"type": "function",
"function": {
"name": "get_weather",
"arguments": "{\"location\":\"Paris, France\"}"
}
}
En la API de Responses, la llamada aparece en el array output con una forma más plana: un type de function_call, un call_id, un name y arguments:
{
"type": "function_call",
"call_id": "call_12345xyz",
"name": "get_weather",
"arguments": "{\"location\":\"Paris, France\"}"
}
Un detalle que confunde a la gente: arguments es una cadena codificada en JSON, no un objeto parseado. Tú mismo la parseas, ejecutas tu función y luego envías el resultado de vuelta para que el modelo pueda terminar su respuesta.
Paso 4: Devuelve el resultado al modelo
Después de ejecutar tu función, devuelve el resultado para que el modelo pueda producir una respuesta final. En Chat Completions, adjuntas un mensaje con el rol tool asociado al id de la llamada. En la API de Responses, envías un elemento function_call_output asociado al call_id. De cualquier manera, el ciclo es el mismo: el modelo pregunta, tú ejecutas, tú devuelves el resultado, el modelo responde.
Paso 5: Agrega llamadas paralelas y modo estricto
Dos configuraciones cambian la fiabilidad y la velocidad de esto, y las añades una vez que el bucle básico funciona.
Llamadas paralelas a herramientas. Por defecto, el modelo puede devolver más de una llamada a herramienta en un solo turno. Si un usuario pregunta por el clima en tres ciudades, podrías obtener tres llamadas a la vez y ejecutarlas juntas. Si prefieres forzar como máximo una llamada por turno, establece parallel_tool_calls en false.
Modo estricto. Establece strict: true en la definición de la función y los argumentos del modelo garantizan que coincidirán con tu Esquema JSON en lugar de ser un mejor esfuerzo. OpenAI recomienda habilitarlo siempre. El modo estricto tiene reglas: cada objeto necesita additionalProperties: false, y cada campo en properties debe aparecer en required. Para hacer un campo opcional, no lo elimines de required; añade null a su lista de tipos permitidos.
| Configuración | Qué controla | Por defecto | Cuándo cambiarlo |
|---|---|---|---|
parallel_tool_calls |
Si se pueden devolver múltiples llamadas a herramientas en un turno | true |
Establece false cuando las llamadas dependen entre sí o deben ejecutarse en orden |
strict |
Si los argumentos se ven obligados a coincidir con el esquema | mejor esfuerzo a menos que se establezca; recomendado activado | Actívalo para cualquier llamada que parsees sin código defensivo |
tool_choice |
Si y qué función puede llamar el modelo | auto |
required para forzar una llamada, none para deshabilitar, o nombra una para fijarla |
La regla del campo opcional sorprende a la gente. Digamos que unit es opcional en get_weather. En modo estricto, aún lo incluyes en required, luego lo marcas como anulable en el esquema, como "unit": {"type": ["string", "null"], "enum": ["celsius", "fahrenheit"]}. El modelo ahora puede pasar una unidad real o un null explícito, pero nunca puede omitir la clave. Esa previsibilidad es el objetivo principal: tu código de análisis sabe exactamente qué claves esperar en cada ocasión.
El modo estricto reduce el JSON mal formado, pero no verifica que los valores tengan sentido comercial. Una ubicación puede ser válida según el esquema y aún así ser una ciudad que no sirves. Ahí es donde entra la prueba.
Cómo probarlo en Apidog
El modelo te proporciona una llamada a una herramienta. Antes de conectarla a una función en vivo, quieres dos garantías: que los argumentos coincidan con la forma que esperas y que la API descendente a la que tu función accedería se comporte como asumes. Apidog cubre ambos lados de esto, y vale la pena ser preciso sobre cuál.

Apidog valida y simula el lado de la API. No ejecuta las funciones de tu aplicación. Lo que hace bien es el contrato alrededor de ellas.
Verifica la estructura de los argumentos. Toma la cadena arguments de una llamada a una herramienta real, trátala como un cuerpo de solicitud y ejecuta aserciones sobre ella en Apidog. Verifica que location existe y es una cadena, que un campo de enumeración solo contiene un valor permitido, que los campos requeridos están presentes. Extraer campos específicos de la carga útil es fácil con expresiones JSONPath, y para las comprobaciones estructurales más profundas existe la validación contra un Esquema JSON, que refleja el mismo esquema que le entregaste a OpenAI en modo estricto. Si la salida del modelo pasa el mismo esquema que tu función espera, has cerrado el ciclo.
Simula la API descendente a la que llamaría la función. Tu función get_weather probablemente llama a un proveedor de clima. Durante el desarrollo, ese proveedor puede tener límites de tarifa, ser de pago o aún no estar construido. Configura una API simulada en Apidog que devuelva una carga útil de clima realista, apunta tu función a la simulación y ejercita toda la ruta de llamada sin gastar una solicitud en el servicio real. Tú controlas la respuesta, incluidos los casos de error que la API en vivo rara vez produce bajo demanda, para que puedas confirmar que tu código maneja un tiempo de espera o un error 429 antes de que un usuario lo encuentre.
En resumen, el flujo de trabajo es: captura una llamada a una herramienta de OpenAI, verifica sus argumentos contra tu esquema en Apidog, luego ejecuta tu función contra una simulación de Apidog de la API real. Verificas el contrato en ambos extremos sin consumir llamadas en vivo ni adivinar casos extremos.
Preguntas frecuentes
¿Funciona la llamada a funciones tanto en Chat Completions como en la API de Responses? Sí. Ambos endpoints la soportan. La API de Responses unifica capacidades que antes estaban divididas entre Chat Completions y la API de Assistants. La principal diferencia es la forma: Chat Completions anida la función bajo una clave function y devuelve tool_calls, mientras que la API de Responses utiliza una definición de herramienta plana y devuelve elementos function_call en el array output.
¿Por qué el modelo devuelve los argumentos como una cadena en lugar de un objeto? El campo arguments es texto codificado en JSON. Lo parseas en tu código antes de usarlo. Esto es consistente en ambas APIs, así que siempre pásalo por tu parser JSON y valida el resultado en lugar de confiar ciegamente en él. Ejecutar esos argumentos a través de la validación de Esquema JSON detecta una carga útil mal formada antes de que llegue a tu función.
¿El modo estricto garantiza que la función tendrá éxito? No. El modo estricto garantiza que los argumentos coincidan con tu Esquema JSON, por lo que la estructura es fiable. No verifica que los valores sean correctos para tu lógica de negocio, y no ejecuta tu función. Todavía debes validar los valores y manejar los fallos de la llamada descendente tú mismo.
¿Puede Apidog ejecutar mi función real? No, y no lo intenta. Apidog valida los argumentos que el modelo produjo y simula la API de la que depende tu función. Tu aplicación aún ejecuta sus propias funciones. Apidog cubre el contrato en ambos lados para que confíes en las entradas y las dependencias antes de salir en vivo.
Conclusión
Ahora tienes el ciclo completo: define tus herramientas claramente, envíalas con la solicitud, lee la salida de tool_calls o function_call, devuelve el resultado, luego activa el modo estricto y decide si las llamadas paralelas ayudan o perjudican. Finaliza con pruebas, verificando que los argumentos coincidan con tu esquema y simulando la API descendente para tener confianza antes de la producción.
¿Quieres probar el lado de las pruebas? Descarga Apidog para verificar los argumentos de las llamadas a herramientas contra tu esquema y simular las APIs de las que dependen tus funciones, todo en un solo lugar.
