Ir al contenido principal

Tutorial sobre llamadas a funciones en GPT-5

Guía práctica para llamar a funciones GPT-5: desde funciones JSON-schema hasta herramientas de formato libre, restricciones Lark/CFG, preámbulos y listas de herramientas permitidas.
Actualizado 7 oct 2025  · 11 min de lectura

Con el lanzamiento de GPT-5, OpenAI amplió las llamadas a herramientas/funciones en la API para incluir llamadas a herramientas de formato libre (texto sin formato, sin JSON), restricciones gramaticales a través de Lark/CFG, listas de herramientas permitidas y un razonamiento mejorado sobre el uso de las herramientas. En conjunto, todo ello convierte a GPT-5 en un modelo verdaderamente agente: puedes conectar API, bases de datos y herramientas personalizadas a la API de respuestas y generar respuestas fundamentadas o incluso automatizar flujos de trabajo.

En este tutorial, voy a explicar herramientas de funciones, herramientas personalizadas, restricciones gramaticales, listas de herramientas permitidasy preámbulos, con ejemplos de código y explicaciones claras sobre cómo funcionan y cuándo utilizarlos.

Llamada a funciones en GPT-5: Qué y por qué

La llamada a funciones en GPT-5 te permite mejorar el modelo con los datos y las acciones de tu aplicación. El modelo puede determinar cuándo llamar a una herramienta, mientras tú te encargas de la lógica y devuelves los resultados para obtener una respuesta final y fundamentada. 

Tipos de llamadas a funciones:

  1. Herramientas funcionales (esquema JSON): Estos ofrecen entradas y salidas estructuradas que el modelo puede invocar con precisión.
  2. Herramientas personalizadas (forma libre): Proporcionan entradas y salidas de texto flexibles para integraciones no estructuradas.

¿Qué es una llamada a función?

GPT-5 admite tanto herramientas de funciones estructuradas (que utilizan JSON Schema) como herramientas personalizadas que aceptan cargas útiles de texto de formato libre (como SQL, scripts o configuraciones) para una integración perfecta con entornos de ejecución externos. 

Las herramientas funcionales se definen mediante JSON Schema, lo que garantiza que el modelo comprenda exactamente qué argumentos pasar y permite una validación estricta de los datos introducidos. Puedes obtener más información en nuestro tutorial sobre llamadas a funciones de OpenAI.

¿Por qué utilizar llamadas a funciones?

  • Flexibilidad: Las herramientas de formato libre permiten que el modelo genere el texto exacto que requiere tu sistema, sin las limitaciones del rígido JSON, lo que las hace ideales para código, consultas o configuraciones.
  • Fiabilidad y control: Las herramientas funcionales imponen argumentos estructurados, lo que mejora la previsibilidad y reduce los errores de análisis sintáctico.
  • Flujos de trabajo agenticos: GPT-5 está diseñado para tareas complejas de codificación y uso de herramientas de varios pasos, por lo que la activación de herramientas es una de sus características principales.

¿Cómo funciona la llamada a funciones?

  1. Envía un mensaje que incluya todas las herramientas disponibles.
  2. El modelo emite una llamada a la herramienta (ya sea con argumentos o con texto libre).
  3. Tu aplicación ejecuta la herramienta (ejecuta la función Python).
  4. Devuelve el resultado de la herramienta al modelo.
  5. A continuación, el modelo responde o puede recurrir a herramientas adicionales.

Fuente: Llamada a funciones - API de OpenAI

Cuándo utilizar la función frente a Herramientas personalizadas

  • Utiliza herramientas funcionales cuando desees una validación estricta y argumentos predecibles y tipificados a través de JSON Schema.
  • Utiliza herramientas personalizadas (forma libre) cuando tu tiempo de ejecución requiera texto sin formato (como scripts, SQL o configuraciones) o cuando necesites iteraciones rápidas sin esquemas.

Herramientas funcionales (esquema JSON): Enviar datos estructurados

El uso de herramientas de función con JSON Schema te permite obtener resultados predecibles y estructurados del modelo. El modelo evalúa las herramientas que has declarado, determina cuándo utilizar una, propone argumentos validados por JSON y, a continuación, ejecuta la función correspondiente en tu código. 

Después, puedes pedirle al modelo que genere una respuesta basada únicamente en los datos devueltos por la herramienta, asegurándote de que el resultado sea sólido, legible por máquina y fácil de integrar.

Este ejemplo ilustra varios conceptos clave:

  • Descubrimiento de herramientas y generación de argumentos: El modelo selecciona la herramienta adecuada y rellena automáticamente sus argumentos de tipo JSON.
  • Bucle de ejecución de la herramienta: Tu aplicación ejecuta las herramientas solicitadas y envía los resultados al modelo.
  • Respuesta final en forma de esquema: La respuesta final se basa estrictamente en los resultados de las herramientas, lo que minimiza las imprecisiones y garantiza la fiabilidad.

1. Configuración

  1. Crea una cuenta de OpenAI y genera una clave API en el panel de control de la plataforma. En el panel de control, abre la sección API, luego «Ver claves API» y haz clic en «Crear nueva clave secreta».
  2. Añade un método de pago o créditos a tu cuenta para que las llamadas API puedan ejecutarse; el uso se deduce de tu saldo prepagado a medida que realizas solicitudes.
  3. Guarda tu clave API como una variable de entorno denominada OPENAI_API_KEY antes de iniciar tu aplicación. 
  4. Instala el SDK oficial de OpenAI para Python con pip install openai.

2. Definir herramientas

Proporcionas una lista de herramientas con un nombre, una descripción y un esquema JSON para los parámetros. El esquema ayuda al modelo a proporcionar argumentos bien formados.

  • make_coffee Espera un parámetro de cadena: coffee_type.
  • random_coffee_fact No toma ningún parámetro (objeto vacío). Estas definiciones se pasan a través de un argumento tools en la llamada a la API para que el modelo sepa qué está disponible.
import os
from openai import OpenAI
import json

client = OpenAI(api_key = os.environ["OPENAI_API_KEY"])

tools = [
    {
        "type": "function",
        "name": "make_coffee",
        "description": "Gives a simple recipe for making a coffee drink.",
        "parameters": {
            "type": "object",
            "properties": {
                "coffee_type": {
                    "type": "string",
                    "description": "The coffee drink, e.g. espresso, cappuccino, latte"
                }
            },
            "required": ["coffee_type"],
        },
    },
    {
        "type": "function",
        "name": "random_coffee_fact",
        "description": "Returns a fun fact about coffee.",
        "parameters": {"type": "object","properties":{}}
    }
]

3. Implementar herramientas

Implementas las funciones de Python que realmente hacen el trabajo:

  • make_coffee(coffee_type) devuelve una cadena concisa con la receta correspondiente a la bebida solicitada.
  • random_coffee_fact() devuelve una pequeña carga útil de datos. 

Ambos devuelven diccionarios serializables en JSON, ideales para retroalimentar al modelo.

def make_coffee(coffee_type):
    recipes = {
        "espresso": "Grind fine, 18g coffee → 36g espresso in ~28s.",
        "cappuccino": "Brew 1 espresso shot, steam 150ml milk, pour and top with foam.",
        "latte": "Brew 1 espresso shot, steam 250ml milk, pour for silky texture.",
    }
    return {"coffee_type": coffee_type, "recipe": recipes.get(coffee_type.lower(), "Unknown coffee type!")}

def random_coffee_fact():
    return {"fact": "Coffee is the second most traded commodity in the world, after oil."}

4. Iniciar una conversación

Inicia la conversación con la pregunta del usuario: {"role": "user", "content": "How do I make a latte?"}

El modelo puede devolver mensajes que incluyan un elemento function_call, como make_coffee con {"coffee_type":"latte"}. A continuación, debes volver a añadir los mensajes del modelo en input_list: input_list += response.output. Esto ayuda a mantener el estado de la conversación para el siguiente turno.

# Track used tools
used_tools = []

input_list = [{"role": "user", "content": "How do I make a latte?"}]

response = client.responses.create(
    model="gpt-5",
    tools=tools,
    input=input_list,
)
input_list += response.output

5. Ejecutar llamadas a herramientas y adjuntar resultados

Debes iterar sobre response.output e identificar los elementos en los que item.type es igual a "function_call". Para estos elementos, analiza item.arguments y envía las solicitudes a tus funciones de Python.

Para la función make_coffee, llámala utilizando make_coffee(args["coffee_type"]). Para la función « random_coffee_fact », simplemente llama a « random_coffee_fact() ».

Después de ejecutar las funciones, añade un mensaje « function_call_output » (Añadido correctamente) que incluya lo siguiente:

  • call_id (que vincula esta salida con la solicitud del modelo) 
  • output (una cadena JSON con el resultado de tu función).
for item in response.output:
    if getattr(item, "type", "") == "function_call":
        used_tools.append(item.name)
        args = json.loads(item.arguments or "{}")

        if item.name == "make_coffee":
            result = make_coffee(args["coffee_type"])
        elif item.name == "random_coffee_fact":
            result = random_coffee_fact()
        else:
            result = {"error": f"Unknown tool {item.name}"}

        input_list.append({
            "type": "function_call_output",
            "call_id": item.call_id,
            "output": json.dumps(result)
        })

6. Genera la respuesta final.

Realizas una segunda llamada a client.responses.create, pasando el objeto input_list actualizado, que ahora incluye los resultados de la herramienta.

La variable used_tools captura los nombres de las herramientas que aparecieron en las llamadas a funciones del modelo. Lo utilizaremos para mostrar qué herramientas se utilizaron. 

final = client.responses.create(
    model="gpt-5",
    tools=tools,
    input=input_list,
    instructions="Answer using only the tool results."
)

print("Final output:\n", final.output_text)

print("\n--- Tool Usage ---")
for t in tools:
    status = "USED ✅" if t["name"] in used_tools else "NOT USED ❌"
    print(f"{t['name']}: {status}")

Como el usuario preguntó por un café con leche, el modelo seleccionó make_coffee con coffee_type = "latte", tu código lo ejecutó y la respuesta final se construyó únicamente a partir del resultado de esa herramienta.

Final output:
 {"coffee_type":"latte","recipe":"Brew 1 espresso shot, steam 250ml milk, pour for silky texture."}

--- Tool Usage ---
make_coffee: USED ✅
random_coffee_fact: NOT USED ❌

Herramientas personalizadas (forma libre): Enviar texto sin formato

Utiliza las herramientas personalizadas de formato libre de GPT-5 para permitir que el modelo envíe texto sin procesar directamente a tu herramienta, como código, SQL, comandos de terminal o CSV simple, sin necesidad de JSON Schema. 

Esta capacidad va más allá de las antiguas llamadas a funciones solo JSON, lo que te proporciona una mayor flexibilidad para la integración con ejecutores, motores de consulta o intérpretes de lenguajes específicos de dominio (DSL). 

En el modo de formato libre, el modelo genera una llamada a una herramienta personalizada con una carga útil de texto no estructurado que puedes dirigir a tu tiempo de ejecución. A continuación, devuelves el resultado para que el modelo lo utilice en la finalización de la respuesta dirigida al usuario.

Ahora escribiremos el código que permite al modelo seleccionar las herramientas adecuadas y devolver texto sin estructurar como resultado. A continuación, este resultado se pasará a una función de Python para generar un resultado. De esta manera, el usuario puede indicar los ingredientes que tienes, y el modelo generará recetas que se adapten a tus necesidades.

En este código de ejemplo, tenemos:

  1. Inicialicé el cliente OpenAI y definí una única herramienta personalizada llamada meal_planner que acepta entradas de texto sin formato.
  2. Creé el Python plan_meal, que toma una cadena de ingredientes separados por comas y devuelve una idea para una comida.
  3. Inicié la conversación con un mensaje de usuario en el que enumeraba los ingredientes disponibles.
  4. Realicé una llamada inicial al modelo indicando a GPT-5 que invocara la herramienta utilizando únicamente una lista limpia de ingredientes, y añadí el resultado del modelo al historial de conversaciones.
  5. Localizaste la llamada a la herramienta personalizada emitida y extrajiste la cadena de entrada sin procesar separada por comas.
  6. Ejecuté la herramienta pasando la lista a plan_meal y, a continuación, envié el resultado al modelo como un function_call_output vinculado a través de call_id.
  7. Realicé una llamada de modelo final para convertir la idea inicial de la herramienta en una receta concisa y paso a paso, e imprimí tanto los detalles de la llamada a la herramienta como el resultado final.
from openai import OpenAI
import json
import random

client = OpenAI()

# --- Custom tool ---
tools = [
    {
        "type": "custom",
        "name": "meal_planner",
        "description": "Takes ONLY a comma-separated list of ingredients and suggests a meal idea."
    }
]

# --- Fake meal planner ---
def plan_meal(ingredients: str) -> str:
    ideas = [
        f"Stir-fry: {ingredients} with garlic & soy sauce.",
        f"One-pot rice: cook {ingredients} together in broth until fluffy.",
        f"Soup: simmer {ingredients} in stock with herbs.",
        f"Sheet-pan bake: roast {ingredients} at 200°C for ~20 min."
    ]
    return random.choice(ideas)

# --- Start conversation ---
messages = [
    {"role": "user", "content": "I only have chicken, rice, and broccoli. Any dinner ideas?"}
]

# 1) Ask model with clear instruction
resp = client.responses.create(
    model="gpt-5",
    tools=tools,
    input=messages,
    instructions="If the user mentions ingredients, call the meal_planner tool with ONLY a comma-separated list like 'chicken, rice, broccoli'."
)

messages += resp.output

# 2) Find the tool call
tool_call = next((x for x in resp.output if getattr(x, "type", "") == "custom_tool_call"), None)
assert tool_call, "No tool call found!"

# Get clean CSV input
ingredients_csv = tool_call.input.strip()

# 3) Run the tool
meal_result = plan_meal(ingredients_csv)

# 4) Send tool output back
messages.append({
    "type": "function_call_output",
    "call_id": tool_call.call_id,
    "output": meal_result
})

# 5) Final model response
final = client.responses.create(
    model="gpt-5",
    tools=tools,
    input=messages,
    instructions="Turn the meal idea into a short recipe with 3-4 steps."
)

print("\n--- Tool Call ---")
print("Name:", tool_call.name)
print("Input:", ingredients_csv)
print("Output:", meal_result)


print("\n--- Final Output ---\n", final.output_text)

Como resultado, recibimos estadísticas sobre las herramientas utilizadas, incluyendo la instalación, la entrada y la salida. Además, el resultado final proporciona una receta completa sobre cómo preparar la comida.

--- Tool Call ---
Name: meal_planner
Input: chicken, rice, broccoli
Output: One-pot rice: cook chicken, rice, broccoli together in broth until fluffy.

--- Final Output ---
 One-Pot Chicken, Rice & Broccoli

- Season bite-size chicken pieces with salt and pepper; sear in a little oil in a pot until lightly browned.
- Add 1 cup rinsed rice and 2 cups broth (or water + salt). Bring to a boil, then cover and simmer on low for 12 minutes.
- Scatter 2 cups small broccoli florets on top, cover, and cook 5-7 more minutes until rice is fluffy and broccoli is tender.
- Rest 5 minutes off heat, fluff, and adjust seasoning. Optional: stir in a knob of butter or a splash of soy.

Restricciones gramaticales (Lark): Restringir las salidas de la herramienta

GPT-5 ahora admite gramática libre de contexto (CFG) para garantizar que los formatos de salida estén estrictamente controlados. 

Al aplicar una gramática, como SQL o un lenguaje específico de dominio (DSL), a sus respuestas, GPT-5 garantiza que los resultados sigan de forma coherente la estructura requerida. CFG es especialmente importante para los procesos automatizados y los flujos de trabajo de alto riesgo. 

GPT-5 puede utilizar gramáticas definidas en formatos como Lark para restringir los resultados de la herramienta durante la generación. Este enfoque de decodificación restringida mejora la fiabilidad al evitar la deriva de formato y garantizar la coherencia estructural.

Ahora escribiremos el código en el que el modelo selecciona una herramienta y genera ÚNICAMENTE una expresión aritmética gramaticalmente válida; a continuación, esta expresión se evalúa en Python, el resultado se devuelve a la conversación y la respuesta final se presenta de forma clara en lenguaje natural.

En este código de ejemplo, tenemos:

  1. Inicialicé el cliente OpenAI y definí una herramienta personalizada math_solver que debe generar ÚNICAMENTE una expresión aritmética gramaticalmente válida (Lark CFG).
  2. Inició la conversación con una pregunta matemática en lenguaje natural del usuario.
  3. Realicé una primera llamada de modelo indicando a GPT-5 que llamara a math_solver con una expresión que se ajustara a la gramática.
  4. Localizó la llamada a la herramienta emitida y extrajo la cadena de expresión sin procesar de la carga útil de la herramienta.
  5. Evaluaste la expresión localmente en un entorno restringido para producir un resultado concreto.
  6. Devolvió el resultado de la ejecución de la herramienta a la conversación, vinculado a través del enlace original call_id.
  7. Realizaste una llamada final al modelo para presentar el resultado evaluado de forma clara en lenguaje natural.
from openai import OpenAI
import json

client = OpenAI()

# --- Local fake evaluator ---
def eval_expression(expr: str) -> str:
    try:
        # Evaluate safely using Python's eval on restricted globals
        result = eval(expr, {"__builtins__": {}}, {})
        return f"{expr} = {result}"
    except Exception as e:
        return f"Error evaluating expression: {e}"

# --- Custom tool with grammar constraint ---
tools = [
    {
        "type": "custom",
        "name": "math_solver",
        "description": "Solve a math problem by outputting ONLY a valid arithmetic expression.",
        "format": {
            "type": "grammar",
            "syntax": "lark",
            "definition": r"""
start: expr

?expr: term
     | expr "+" term   -> add
     | expr "-" term   -> sub

?term: factor
     | term "*" factor -> mul
     | term "/" factor -> div

?factor: NUMBER
       | "(" expr ")"

%import common.NUMBER
%ignore " "
"""
        },
    }
]

# --- User asks ---
msgs = [
    {"role": "user", "content": "What is (12 + 8) * 3 minus 5 divided by 5?"}
]

# 1) First model call: GPT-5 must emit a grammar-valid expression
resp = client.responses.create(
    model="gpt-5",
    tools=tools,
    input=msgs,
    instructions="Always call the math_solver tool with a grammar-valid arithmetic expression like '(12 + 8) * 3 - 5 / 5'."
)

msgs += resp.output

tool_call = next(
    x for x in resp.output
    if getattr(x, "type", "") in ("custom_tool_call", "tool_call", "function_call")
)

expr = getattr(tool_call, "input", "") or getattr(tool_call, "arguments", "")
print("\n=== Grammar-Constrained Expression ===")
print(expr)

# 2) Run the local evaluator
tool_result = eval_expression(expr)
print("\n=== Tool Execution Result ===")
print(tool_result)

# 3) Return tool output
msgs.append({
    "type": "function_call_output",
    "call_id": tool_call.call_id,
    "output": tool_result
})

# 4) Final pass: GPT-5 presents answer nicely
final = client.responses.create(
    model="gpt-5",
    input=msgs,
    tools=tools,
    instructions="Present the evaluated result clearly in natural language."
)

print("\n=== Final Output ===")
print(final.output_text)

Como puedes ver, el modelo ha seleccionado la herramienta y, a continuación, ha generado una expresión con restricciones gramaticales. Después, se pasa a través de la función Python para generar la respuesta. Al final, tenemos una respuesta adecuada en lenguaje natural.

=== Grammar-Constrained Expression ===
(12 + 8) * 3 - 5 / 5

=== Tool Execution Result ===
(12 + 8) * 3 - 5 / 5 = 59.0

=== Final Output ===
59

Listas de herramientas permitidas: Limita de forma segura lo que puede utilizar el modelo

La configuración « allowed_tools » (Selección de herramientas) te permite restringir el modelo a una selección segura de herramientas de tu kit de herramientas completo. Esto mejora la previsibilidad y evita llamadas a herramientas no deseadas, al tiempo que proporciona al modelo flexibilidad dentro del conjunto permitido. 

Puedes permitir que el modelo elija entre las herramientas permitidas o exigirle que utilice una, reflejando los comportamientos de «herramienta forzada» que se observan en otras pilas y alineándote con las mejores prácticas generales para la coordinación de llamadas a herramientas.

Ahora escribiremos el código en el que permitimos una sola herramienta, hacemos que el modelo llame solo a esa herramienta, la ejecutamos, retroalimentamos los resultados y, a continuación, generamos un resumen conciso dirigido al usuario.

Nota: Crea una cuenta gratuita cuenta gratuita en Firecrawl, genera una clave API, guárdala como variable de entorno FIRECRAWL_API_KEY e instala el SDK de Python de Firecrawl utilizando pip install firecrawl-py.

En este código de ejemplo, tenemos:

  1. Se ha definido un conjunto completo de herramientas con dummy_web_search y firecrawl_search.
  2. Restringí el modelo a firecrawl_search solo a través de tool_choice = { type: "allowed_tools", mode: "required", tools: [...] }.
  3. Emitió la primera llamada al modelo, capturó el nombre y los argumentos de la llamada a la herramienta y los imprimió para que fueran visibles.
  4. Cuando se invoca firecrawl_search, los argumentos deserializados ejecutan Firecrawl, convierten su respuesta en un diccionario serializable JSON y extraen la carga útil de datos seguros.
  5. Introducí los resultados de la herramienta en la conversación utilizando function_call_output vinculado por call_id y, a continuación, realicé una llamada final al modelo para resumirlo en 3-4 puntos con enlaces Markdown.
  6. Se incluyó una rama alternativa que ejecutaría la herramienta ficticia (aunque la lista de permitidos lo impide en esta ejecución).
  7. Imprimiste la respuesta final en lenguaje natural.
from openai import OpenAI
from firecrawl import Firecrawl
import json
import os

client = OpenAI()
firecrawl = Firecrawl(api_key=os.environ["FIRECRAWL_API_KEY"])

# --- Full toolset ---
tools = [
    {
        "type": "function",
        "name": "dummy_web_search",
        "description": "A fake web search that always returns static dummy results.",
        "parameters": {
            "type": "object",
            "properties": {
                "query": {"type": "string"},
                "limit": {"type": "integer"}
            },
            "required": ["query"]
        },
    },
    {
        "type": "function",
        "name": "firecrawl_search",
        "description": "Perform a real web search using Firecrawl.",
        "parameters": {
            "type": "object",
            "properties": {
                "query": {"type": "string"},
                "limit": {"type": "integer"}
            },
            "required": ["query"]
        },
    },
]

# --- Dummy implementation ---
def dummy_web_search(query, limit=3):
    return {
        "query": query,
        "results": [f"[Dummy] Result {i+1} for '{query}'" for i in range(limit)]
    }

# --- User asks ---
messages = [
    {"role": "user", "content": "Find me the latest info about the stock market."}
]

# --- Restrict to Firecrawl only ---
resp = client.responses.create(
    model="gpt-5",
    tools=tools,
    input=messages,
    instructions="Only the firecrawl_search tool is allowed. Do not use dummy_web_search.",
    tool_choice={
        "type": "allowed_tools",
        "mode": "required",  # force Firecrawl
        "tools": [{"type": "function", "name": "firecrawl_search"}],
    },
)

for item in resp.output:
    if getattr(item, "type", "") in ("function_call", "tool_call"):
        print("\n--- Tool Call ---")
        print("Tool name:", item.name)
        print("Arguments:", item.arguments)

        if item.name == "firecrawl_search":
            args = json.loads(item.arguments)

            # Firecrawl returns a SearchData object → convert it
            results_obj = firecrawl.search(
                query=args["query"],
                limit=args.get("limit", 3),
            )

            # 🔥 Convert to JSON-serializable dict
            if hasattr(results_obj, "to_dict"):
                results = results_obj.to_dict()
            elif hasattr(results_obj, "dict"):
                results = results_obj.dict()
            else:
                results = json.loads(results_obj.json()) if hasattr(results_obj, "json") else results_obj

            print("\n--- Firecrawl Raw Results ---")
            print(json.dumps(results, indent=2)[:500])

            # ✅ Extract only the data portion for summarization
            safe_results = results.get("data", results)

            # Feed back to GPT
            messages += resp.output
            messages.append({
                "type": "function_call_output",
                "call_id": item.call_id,
                "output": json.dumps(safe_results)  # now safe
            })

            # Final pass
            final = client.responses.create(
                model="gpt-5",
                tools=tools,
                input=messages,
                instructions="Summarize the Firecrawl search results into 3-4 bullet points with clickable [Title](URL) links."
            )

            print("\n--- Final Natural Language Answer ---")
            print(final.output_text)

        elif item.name == "dummy_web_search":
            args = json.loads(item.arguments)
            results = dummy_web_search(args["query"], args.get("limit", 3))
            print("\n--- Dummy Web Search Results ---")
            print(json.dumps(results, indent=2))

Ha seleccionado la búsqueda Firecrawl y, utilizando esa búsqueda, ha generado la respuesta final en formato Markdown.

Preámbulos: Indica al modelo cómo llamar a las herramientas

Los preámbulos son breves explicaciones que el modelo genera antes de invocar una herramienta, aclarando el motivo de la llamada. Mejoran la transparencia, generan confianza en los usuarios y aumentan la claridad en la depuración de errores en flujos de trabajo complejos. Puedes habilitarlos utilizando una instrucción sencilla como «explicar antes de llamar a una herramienta», normalmente sin añadir una latencia apreciable. 

Ahora escribiremos el código en el que el modelo primero genera una breve línea «Preámbulo:» que explica por qué llama a una herramienta, luego llama a la herramienta, tú la ejecutas localmente, devuelve el resultado y el modelo produce una respuesta final clara.

En este código de ejemplo, tenemos:

  1. Inicialicé el cliente OpenAI y definí una herramienta de función de tipo estricto (medical_advice) con JSON Schema.
  2. Se ha añadido una instrucción del sistema que indica al modelo que genere un mensaje de « “Preamble:” » (Aviso de llamada a la herramienta) de una línea antes de cualquier llamada a la herramienta.
  3. Inicia la conversación con una pregunta sobre los síntomas del usuario.
  4. Realizó la primera llamada al modelo para obtener tanto el preámbulo como la llamada a la herramienta con sus argumentos.
  5. Extraje y ejecuté la herramienta localmente para generar recomendaciones.
  6. Devolvió el resultado de la herramienta al modelo, vinculado a través de call_id.
  7. Se realizó una llamada al modelo final para que GPT-5 presentara el resultado como una respuesta concisa y fácil de usar.
from openai import OpenAI
import json
import random

client = OpenAI()

# --- Fake tool implementation ---
def medical_advice(symptom: str):
    remedies = {
        "headache": "You can take acetaminophen (paracetamol) or ibuprofen, rest in a quiet room, and stay hydrated.",
        "cough": "Drink warm fluids, use honey in tea, and consider over-the-counter cough syrup.",
        "fever": "Use acetaminophen to reduce fever, stay hydrated, and rest. See a doctor if >39°C.",
    }
    return {"advice": remedies.get(symptom.lower(), "Please consult a healthcare provider for guidance.")}

# --- Tool definition ---
tools = [{
    "type": "function",
    "name": "medical_advice",
    "description": "Provide safe, general over-the-counter advice for common symptoms.",
    "parameters": {
        "type": "object",
        "properties": {"symptom": {"type": "string"}},
        "required": ["symptom"],
        "additionalProperties": False
    },
    "strict": True,
}]

# --- Messages (system preamble instruction) ---
messages = [
    {"role": "system", "content": "Before you call a tool, explain why you are calling it in ONE short sentence prefixed with 'Preamble:'."},
    {"role": "user", "content": "What should I take for a headache?"}
]

# 1) First call: expect preamble + tool call
resp = client.responses.create(model="gpt-5", input=messages, tools=tools)
print("=== First Response ===")
for item in resp.output:
    t = getattr(item, "type", None)
    if t == "message":
        # Extract just the model's text
        content = getattr(item, "content", None)
        text = None
        if isinstance(content, list):
            text = "".join([c.text for c in content if hasattr(c, "text")])
        elif content:
            text = str(content)
        if text:
            # ✅ Only print once
            print(text)
    if t in ("function_call", "tool_call", "custom_tool_call"):
        print("Tool:", getattr(item, "name", None))
        print("Args:", getattr(item, "arguments", None))

# Extract tool call
tool_call = next(x for x in resp.output if getattr(x, "type", None) in ("function_call","tool_call","custom_tool_call"))
messages += resp.output

# 2) Execute tool locally
args = json.loads(getattr(tool_call, "arguments", "{}"))
symptom = args.get("symptom", "")
tool_result = medical_advice(symptom)

# 3) Return tool result
messages.append({
    "type": "function_call_output",
    "call_id": tool_call.call_id,
    "output": json.dumps(tool_result)
})

# 4) Final model call → natural answer
final = client.responses.create(model="gpt-5", input=messages, tools=tools)
print("\n=== Final Answer ===")
print(final.output_text)

Puedes ver que, antes de llamar a la herramienta, se proporciona una explicación de por qué se llama a la herramienta. Esto es bueno para la observabilidad y la depuración.

Resumen

GPT-5 es el modelo más avanzado de OpenAI hasta la fecha, que destaca especialmente en codificación y flujos de trabajo basados en agentes. Sus últimas funciones API permiten el desarrollo sencillo de sistemas de nivel de producción de principio a fin.

En este tutorial, has aprendido a:

  1. Devuelve resultados estructurados utilizando herramientas de funciones y esquemas JSON para una automatización descendente fiable.
  2. Habilita la ejecución de formato libre con herramientas personalizadas (texto sin formato), lo que permite que el modelo genere código, SQL, scripts de terminal y archivos CSV más allá de las simples llamadas JSON.
  3. Formatos restringidos que utilizan restricciones gramaticales de Lark cuando la precisión es crucial, como en matemáticas, SQL o lenguajes específicos de dominio (DSL).
  4. Restringe el acceso a las herramientas con listas de permitidos (o imponiendo el uso de una única herramienta) para mejorar la seguridad, el control y el determinismo.
  5. Mejora la transparencia con breves preámbulos, de modo que el modelo explique por qué está llamando a una herramienta específica, lo que facilita la observabilidad y la depuración.

Para obtener más información sobre lo que puedes hacer con las diversas herramientas de OpenAI, te recomiendo que realices nuestro programa de formación OpenAI Fundamentals y cursos Trabajar con la API de OpenAI.


Abid Ali Awan's photo
Author
Abid Ali Awan
LinkedIn
Twitter

Soy un científico de datos certificado que disfruta creando aplicaciones de aprendizaje automático y escribiendo blogs sobre ciencia de datos. Actualmente me centro en la creación de contenidos, la edición y el trabajo con grandes modelos lingüísticos.

Temas

Los mejores cursos de DataCamp

Programa

Fundamentos de OpenAI

0 min
Empieza a crear sistemas de IA utilizando modelos de OpenAI. Aprende a utilizar la API de OpenAI para solicitar los modelos GPT y Whisper de OpenAI.
Ver detallesRight Arrow
Comienza el curso
Ver másRight Arrow
Relacionado
An avian AI exits its cage

blog

12 alternativas de código abierto a GPT-4

Alternativas de código abierto a GPT-4 que pueden ofrecer un rendimiento similar y requieren menos recursos informáticos para funcionar. Estos proyectos vienen con instrucciones, fuentes de código, pesos del modelo, conjuntos de datos e IU de chatbot.
Abid Ali Awan's photo

Abid Ali Awan

9 min

Tutorial

Tutorial de llamada a funciones de OpenAI

Descubra cómo la nueva capacidad de llamada a funciones de OpenAI permite a los modelos GPT generar salidas JSON estructuradas, resolviendo problemas comunes de desarrollo causados por salidas irregulares.
Abid Ali Awan's photo

Abid Ali Awan

Tutorial

Visión GPT-4: Guía completa para principiantes

Este tutorial le presentará todo lo que necesita saber sobre GPT-4 Vision, desde cómo acceder a él hasta ejemplos prácticos del mundo real y sus limitaciones.
Arunn Thevapalan's photo

Arunn Thevapalan

Tutorial

Guía para principiantes de la API de OpenAI: Tutorial práctico y prácticas recomendadas

Este tutorial te presenta la API de OpenAI, sus casos de uso, un enfoque práctico para utilizar la API y todas las prácticas recomendadas que debes seguir.
Arunn Thevapalan's photo

Arunn Thevapalan

Tutorial

Guía para principiantes sobre el uso de la API ChatGPT

Esta guía te acompanya a través de los fundamentos de la API ChatGPT, demostrando su potencial en el procesamiento del lenguaje natural y la comunicación impulsada por la IA.
Moez Ali's photo

Moez Ali

Tutorial

Cómo utilizar Custom Instructions de ChatGPT

Explora la función Custom Instructions de ChatGPT. Aprende a afinar las respuestas, explora casos de uso para profesores, empresarios y creadores de contenidos.
Moez Ali's photo

Moez Ali

Ver másVer más