Cargando

Llamadas paralelas a herramientas: reduce la latencia

Lección 310 min
Cargando

Llamadas paralelas a herramientas: reduce la latencia

ResumenTranscripción

Claude puede solicitar varias herramientas en una sola respuesta, y tu código puede ejecutarlas juntas. El video revisa un sitio de trabajo para Meridian, una consultora de ingeniería ficticia. Ejecutar las llamadas a herramientas una por una toma 19.9 segundos, mientras que las llamadas paralelas a herramientas toman 10.8.

La demostración de este video se grabó en septiembre de 2026. Se ejecutó en Claude Sonnet 5 (claude-sonnet-5). Los resultados pueden diferir en modelos más nuevos.

Ejecutar las llamadas a herramientas una a la vez hace que tu usuario espere por cada una en su turno.

Cuando las herramientas que Claude solicita no dependen unas de otras, puede pedirlas todas en una sola respuesta. Claude hace esto por defecto, así que tu bucle tiene que manejar cada llamada a herramienta y enviar un resultado de vuelta por cada una.

Tres llamadas a herramientas en una sola respuesta

El uso de herramientas en paralelo significa que una respuesta contiene varios bloques tool_use.

Meridian tiene un script en Python que verifica si un sitio de trabajo está listo para el trabajo de campo. La verificación del sitio necesita tres búsquedas que no dependen unas de otras: el estado del proyecto, el clima en el sitio y el estado del permiso.

Aquí está la respuesta de Claude a la verificación del sitio de Meridian, con un bloque tool_use para cada herramienta que solicita.

json
{
  "role": "assistant",
  "stop_reason": "tool_use",
  "content": [
    {"type": "tool_use", "id": "toolu_01", "name": "get_project_status",
     "input": {"job_number": "MEG-2026-0142"}},
    {"type": "tool_use", "id": "toolu_02", "name": "get_site_weather",
     "input": {"site": "Riverside"}},
    {"type": "tool_use", "id": "toolu_03", "name": "get_permit_state",
     "input": {"permit_id": "P-88213"}}
  ]
}

El stop_reason de la respuesta es tool_use, y cada llamada a herramienta tiene su propio id.

Ejecuta cada llamada a herramienta

Un bucle escrito para una sola llamada a herramienta solo lee el primer bloque tool_use. Envía un solo resultado, dos llamadas a herramientas nunca obtienen el suyo, y la API rechaza la solicitud. Así que recopila cada bloque tool_use en la respuesta.

python
calls = [b for b in resp.content if b.type == "tool_use"]

A continuación, ejecuta esas llamadas a herramientas al mismo tiempo. Cada búsqueda pasa la mayor parte de su tiempo esperando a otro sistema. Dale a cada una su propio hilo, y las tres esperas se superponen en lugar de sumarse.

python
with ThreadPoolExecutor() as pool:
    results = list(pool.map(run_tool, calls))

run_tool ejecuta una llamada a herramienta y devuelve su resultado, y las siguientes dos secciones lo construyen.

Ejecutar llamadas a herramientas al mismo tiempo suele ser seguro cuando solo leen datos y no dependen unas de otras, como las búsquedas de Meridian. Cuando las herramientas cambian datos, o deben ir en un orden establecido, podría ser mejor ejecutarlas una tras otra.

Envía cada resultado de vuelta en un solo mensaje

Una vez que las tres llamadas a herramientas se han ejecutado, Claude está esperando sus resultados. Cada resultado vuelve en un bloque tool_result, y su tool_use_id contiene el id de la llamada a herramienta que responde.

python
result = {"type": "tool_result", "tool_use_id": call.id}

Cada bloque tool_use obtiene un tool_result, y todos van en el siguiente mensaje de usuario.

python
messages.append({"role": "assistant", "content": resp.content})
messages.append({"role": "user", "content": results})
Una franja en la parte superior muestra la única respuesta de Claude con tres llamadas a herramientas: toolu_01 get_project_status, toolu_02 get_site_weather y toolu_03 get_permit_state. Abajo, el panel izquierdo, marcado con una marca de verificación, muestra un mensaje de usuario que contiene los tres resultados de herramientas. El panel derecho, marcado con una cruz, muestra tres mensajes de usuario que contienen un resultado cada uno.

Un mensaje de usuario con los tres resultados mantiene a Claude llamando herramientas en paralelo.

Si tu bucle envía cada resultado en su propio mensaje, la conversación se lee como si Claude hubiera pedido una herramienta a la vez. Esa es una razón común por la que Claude hace menos llamadas paralelas a herramientas.

Devuelve un resultado de error para una llamada a herramienta fallida

Ejecutar tres llamadas a herramientas a la vez significa que una puede fallar mientras las otras dos tienen éxito. Si tu código lanza una excepción y nada la captura, tu bucle se detiene, y los dos resultados buenos se pierden con él.

Así que envía el fallo de vuelta como un resultado. Es un tool_result ordinario con el mensaje de error como su content, más is_error: true. El mensaje debe decir qué salió mal y qué debería intentar Claude a continuación.

python
try:
    result["content"] = HANDLERS[call.name](**call.input)
except Exception as exc:
    result["content"] = f"{call.name} failed: {exc}"
    result["is_error"] = True

HANDLERS es un diccionario que mapea nombres de herramientas a las funciones de Python que realizan el trabajo de cada herramienta. Cada función devuelve una cadena, porque el content de un tool_result es una cadena o una lista de bloques de contenido.

Arma el bucle completo

Los fragmentos anteriores encajan en el bucle de Meridian que se muestra a continuación. El script ya ha configurado client, tools, prompt y HANDLERS.

Cargando

Puntos clave

  • Ejecuta cada llamada a herramienta en una respuesta, y ejecútalas al mismo tiempo cuando no dependan unas de otras.
  • Envía de vuelta un tool_result por cada llamada a herramienta, y ponlos todos en un solo mensaje de usuario.
  • No envíes cada resultado en su propio mensaje, porque eso reduce el uso paralelo de herramientas.
  • Envía un fallo de vuelta como resultado con is_error: true, para que una llamada a herramienta fallida no detenga el bucle.