For the complete documentation index, see llms.txt. Markdown versions of documentation pages are available by appending .md to the page URL.
Navegación principal
Theme

Llamadas asíncronas a herramientas

Sigue trabajando mientras tu aplicación ejecuta herramientas en segundo plano.

Las llamadas asíncronas permiten que el modelo siga trabajando después de llamar a una herramienta, sin esperar el resultado. Úsalas para iniciar con anticipación las consultas que tardan más, responder partes independientes de una solicitud y entregar los resultados cuando tu aplicación los tenga.

Cómo funcionan las herramientas asíncronas

Una llamada a una función convencional pausa el turno del modelo hasta que la herramienta responde. Configura async: true en la definición de una función o de una herramienta personalizada para que el modelo pueda seguir trabajando después de hacer la llamada, antes de que tu aplicación devuelva el resultado.

Tu aplicación sigue siendo la encargada de ejecutar la herramienta. Las herramientas asíncronas no trasladan la ejecución a OpenAI ni administran tus trabajos en segundo plano.

El modo en segundo plano funciona de otra manera, ya que genera la respuesta de forma asíncrona. Las llamadas asíncronas a herramientas permiten que el modelo siga trabajando mientras tu aplicación ejecuta una herramienta.

Cuando termine un trabajo, incluye su resultado en una solicitud posterior a la API Responses. Usa el call_id original de la API para asociar el resultado con su llamada:

Tipo de herramienta Elemento de llamada Elemento de salida
Función function_call function_call_output
Personalizada custom_tool_call custom_tool_call_output

Llamar a una herramienta asíncrona

Agrega async: true a la definición de la herramienta. Los elementos de llamada correspondientes en response.output incluyen async: true.

Consultar el pronóstico del tiempo en segundo plano
import json
from concurrent.futures import ThreadPoolExecutor

from openai import OpenAI
from openai.types.responses import FunctionToolParam


def get_weather(city):
    # Demo data. Replace this function with your weather service.
    weather = {
        "Paris": {
            "city": "Paris",
            "temperature_c": 22,
            "condition": "Clear",
            "source": "demo weather snapshot",
        }
    }
    return weather[city]


worker = ThreadPoolExecutor()


def main():
    client = OpenAI()
    model = "gpt-6-astra"
    tools: list[FunctionToolParam] = [
        {
            "type": "function",
            "name": "get_weather",
            "description": "Read the demo weather snapshot for a city.",
            "async": True,
            "strict": True,
            "parameters": {
                "type": "object",
                "properties": {"city": {"type": "string"}},
                "required": ["city"],
                "additionalProperties": False,
            },
        },
    ]

    instructions = (
        "Start the weather lookup and answer the independent packing "
        "question without waiting. Use the actual tool result when it "
        "arrives; never invent it. Identify the weather as demo data."
    )
    response = client.responses.create(
        model=model,
        tools=tools,
        instructions=instructions,
        input=(
            "Check the demo weather in Paris. Meanwhile, "
            "list three essentials for any city trip."
        ),
    )

    call = next(item for item in response.output if item.type == "function_call")
    arguments = json.loads(call.arguments)
    if call.name != "get_weather" or arguments != {"city": "Paris"}:
        raise ValueError("Expected a weather lookup for Paris")

    latest_response_id = response.id
    if call.async_:
        job = worker.submit(get_weather, **arguments)
        print(response.output_text)
        # Independent work or conversation turns can happen here.
        # Update latest_response_id after each continuation.
        result = job.result()
    else:
        result = get_weather(**arguments)

    response = client.responses.create(
        model=model,
        tools=tools,
        instructions=instructions,
        previous_response_id=latest_response_id,
        input=[
            {
                "type": "function_call_output",
                "call_id": call.call_id,
                "output": json.dumps(result),
            },
        ],
    )
    print(response.output_text)


if __name__ == "__main__":
    try:
        main()
    finally:
        worker.shutdown(wait=True)

La respuesta puede incluir tanto la llamada asíncrona como una contestación. Si hay otros turnos en la conversación antes de que termine el trabajo, actualiza latest_response_id para continuar a partir de la respuesta más reciente y conserva el call_id original de la llamada a la herramienta.

Si usas streaming, puedes iniciar el trabajo antes. Hazlo en cuanto recibas el elemento de llamada completo y sigue leyendo la respuesta.

Agregar una herramienta de espera

Una herramienta de espera permite que el modelo decida en qué momento necesita un resultado pendiente. Por ejemplo, puede iniciar dos consultas de precios, trabajar en otra tarea independiente y esperar los resultados solo cuando esté listo para comparar los precios.

Agrega un argumento task_handle a cada herramienta asíncrona. El modelo asigna un identificador de tarea a cada llamada y tu aplicación lo vincula con el call_id original de la API y con el trabajo en curso. Usa identificadores únicos durante toda la conversación, incluso para las tareas completadas y las consultas repetidas.

Define la herramienta de espera como una función síncrona convencional. Omite async o asígnale el valor false. Tu aplicación define el esquema y el comportamiento de la herramienta. wait_for_tasks no es una herramienta integrada de la API Responses.

Usa estas definiciones en el arreglo tools de la solicitud:

[
  {
    "type": "function",
    "name": "lookup_price",
    "async": true,
    "description": "Look up a product price in the background. Choose a fresh task_handle unique within this conversation, including completed tasks.",
    "strict": true,
    "parameters": {
      "type": "object",
      "properties": {
        "sku": { "type": "string" },
        "task_handle": { "type": "string" }
      },
      "required": ["sku", "task_handle"],
      "additionalProperties": false
    }
  },
  {
    "type": "function",
    "name": "wait_for_tasks",
    "description": "Wait for selected tasks whose results you need. Pass a nonempty list of distinct task_handles from your earlier async tool calls. Results arrive on their original calls; this tool returns status only. Do not wait again for results that have already arrived.",
    "strict": true,
    "parameters": {
      "type": "object",
      "properties": {
        "task_handles": {
          "type": "array",
          "items": { "type": "string" }
        }
      },
      "required": ["task_handles"],
      "additionalProperties": false
    }
  }
]

Registrar cada trabajo

Registra e inicia cada trabajo antes de procesar una llamada de espera que dependa de él. Las llamadas pueden llegar juntas o en respuestas distintas. Los siguientes elementos de salida muestran dos llamadas que inician trabajos y una llamada de espera que depende de ambos:

[
  {
    "type": "function_call",
    "name": "lookup_price",
    "async": true,
    "call_id": "call_widget",
    "arguments": "{\"sku\":\"WIDGET\",\"task_handle\":\"widget_price_1\"}"
  },
  {
    "type": "function_call",
    "name": "lookup_price",
    "async": true,
    "call_id": "call_gadget",
    "arguments": "{\"sku\":\"GADGET\",\"task_handle\":\"gadget_price_1\"}"
  },
  {
    "type": "function_call",
    "name": "wait_for_tasks",
    "call_id": "call_wait",
    "arguments": "{\"task_handles\":[\"widget_price_1\",\"gadget_price_1\"]}"
  }
]

El registro de tu aplicación vincula cada identificador de tarea con su llamada original y con el trabajo en curso:

Identificador de tarea ID de la llamada original Trabajo
widget_price_1 call_widget Consulta del precio de WIDGET
gadget_price_1 call_gadget Consulta del precio de GADGET

Conserva el registro durante toda la conversación para evitar que se reutilice el identificador de una tarea completada.

Entregar los resultados antes del estado de la llamada de espera

Busca en el registro los trabajos correspondientes a los identificadores solicitados y espera solo a que terminen esos trabajos. Devuelve el resultado de cada trabajo recién completado con su call_id original y luego devuelve el estado con el call_id de la propia llamada de espera. Así, el modelo dispone de los resultados cuando reanuda su trabajo.

Por ejemplo, envía estos elementos de salida en el arreglo input de la siguiente solicitud. Los precios son de ejemplo:

[
  {
    "type": "function_call_output",
    "call_id": "call_widget",
    "output": "{\"task_handle\":\"widget_price_1\",\"price_cents\":1200,\"currency\":\"USD\"}"
  },
  {
    "type": "function_call_output",
    "call_id": "call_gadget",
    "output": "{\"task_handle\":\"gadget_price_1\",\"price_cents\":1500,\"currency\":\"USD\"}"
  },
  {
    "type": "function_call_output",
    "call_id": "call_wait",
    "output": "{\"status\":\"completed\",\"completed_task_handles\":[\"widget_price_1\",\"gadget_price_1\"]}"
  }
]

Asigna a previous_response_id el ID de la respuesta más reciente e incluye las herramientas y las instrucciones en la solicitud de continuación. Tu aplicación también puede entregar los resultados a medida que estén disponibles, sin una llamada de espera. Usa la herramienta de espera solo cuando el siguiente paso del modelo dependa de resultados que aún no hayan llegado.

Agregar una herramienta para pedir información al usuario

Una herramienta asíncrona puede hacerle una pregunta al usuario mientras el modelo sigue trabajando en tareas independientes. Por ejemplo, el modelo puede preguntar a quién va dirigido un informe, recopilar datos mientras el usuario responde y adaptar el informe según la respuesta.

Define una función con async: true para pedir información que falte o preguntar por una preferencia. Tu aplicación muestra la pregunta, recibe la respuesta y la devuelve como resultado de la herramienta. Tu aplicación define el esquema y el comportamiento de la herramienta. request_user_input_async no es una herramienta integrada de la API Responses.

Agrega esta definición al arreglo tools de la solicitud junto con wait_for_tasks:

{
  "type": "function",
  "name": "request_user_input_async",
  "async": true,
  "description": "Ask the user for missing information or a preference. Choose a fresh task_handle unique within this conversation, including completed tasks. Continue independent work while the answer is pending. Use wait_for_tasks when your next step depends on the answer.",
  "strict": true,
  "parameters": {
    "type": "object",
    "properties": {
      "question": { "type": "string" },
      "task_handle": { "type": "string" }
    },
    "required": ["question", "task_handle"],
    "additionalProperties": false
  }
}

Mostrar la pregunta

Cuando recibas el elemento de llamada completo, registra el task_handle de la pregunta y su call_id original. Luego, muestra la pregunta al usuario. En este ejemplo, el elemento de salida contiene una pregunta sobre el público del informe:

{
  "type": "function_call",
  "name": "request_user_input_async",
  "async": true,
  "call_id": "call_audience",
  "arguments": "{\"question\":\"Who is the report for: executives or engineers?\",\"task_handle\":\"report_audience_1\"}"
}

Mantén la pregunta pendiente en el mismo registro que usa la herramienta de espera. Mientras el usuario responde, sigue leyendo la respuesta del modelo. No completes la llamada a la herramienta con una confirmación de que mostraste la pregunta. El resultado de la llamada es la respuesta del usuario.

Devolver la respuesta del usuario

Cuando el usuario responda, envía su respuesta con el call_id original de la pregunta. Por ejemplo, incluye este elemento de salida en el arreglo input de la siguiente solicitud:

[
  {
    "type": "function_call_output",
    "call_id": "call_audience",
    "output": "{\"task_handle\":\"report_audience_1\",\"answer\":\"Executives\"}"
  }
]

Asigna a previous_response_id el ID de la respuesta más reciente e incluye las herramientas y las instrucciones en la solicitud de continuación. Si el modelo llamó a wait_for_tasks para esperar el resultado de report_audience_1, devuelve la respuesta del usuario antes del estado de la llamada de espera, como en el ejemplo de la herramienta de espera.

La ejecución asíncrona no mantiene abierta la respuesta del modelo hasta que el usuario conteste. Indícale al modelo que siga trabajando en tareas independientes y que espere antes de dar un paso que requiera la respuesta del usuario. Si tu aplicación permite descartar una pregunta o establece un tiempo límite para responderla, devuelve un resultado que indique explícitamente que no hubo respuesta para que el modelo decida cómo proceder.

Compatibilidad

GPT-6 Astra y los modelos posteriores admiten llamadas asíncronas a herramientas.

La ejecución asíncrona se aplica a las funciones y a las herramientas personalizadas que ejecuta tu aplicación. No se aplica a las herramientas integradas alojadas. Usa llamadas directas a herramientas. No configures herramientas asíncronas para las llamadas programáticas a herramientas.

En el modo multiagente, no combines herramientas asíncronas con llamadas a herramientas en paralelo.