Llamadas paralelas y transmisión con herramientas
Type: Build
Languages: Python (stdlib, thread pool + streaming harness)
Prerequisites: Phase 13 · 02 (function calling deep dive)
Time: ~75 minutes
Objetivos de aprendizaje
- ¿ Por qué ?
parallel_tool_calls: trueexiste y cuándo desactivarlo. - Correlación de los trozos de argumento en streaming con la identificación de llamada de herramienta correcta durante el ventilador paralelo.
- Reassemblar parcialmente
argumentslas cadenas en JSON completo sin analizar temprano. - Ejecutar un indicador meteorológico de tres ciudades que demuestre latencia secuencial vs paralelo.
El problema
Sin llamadas paralelas, un agente respondiendo a "cuál es el tiempo en Bengaluru, Tokio y Zurich" hace esto:
user -> LLM
LLM -> call get_weather(Bengaluru)
host -> run executor, reply with result
LLM -> call get_weather(Tokyo)
host -> run executor, reply with result
LLM -> call get_weather(Zurich)
host -> run executor, reply with result
LLM -> final text answerTres viajes de ida y vuelta de LLM, cada uno de los cuales también paga la latencia del ejecutor.
Con llamadas paralelas:
user -> LLM
LLM -> call get_weather(Bengaluru); call get_weather(Tokyo); call get_weather(Zurich)
host -> run all three executors concurrently, reply with three results
LLM -> final text answerUn viaje de ida y vuelta de LLM. El tiempo de ejecución es el máximo de los tres, no la suma. Los índices de producción en OpenAI, Anthropic y Gemini muestran una reducción del 60 a 70 por ciento en el reloj de pared en las cargas de trabajo de ventilador.
Cuando las tres llamadas terminan fuera de orden, sus resultados deben llevar la coincidencia tool_call_idCuando los resultados se transmiten, se debe reunir fragmentos de argumento parciales en JSON completo antes de ejecutar. Gemini 3 agregó ids únicos en parte para resolver un problema en el mundo real donde dos llamadas paralelas a la misma herramienta eran indistinguibles.
El concepto
Permitir el paralelo
- OpenAI.
parallel_tool_calls: trueen el por defecto.falsepara forzar a la serie. - Anthropic.Paralelamente a través de
disable_parallel_tool_use: false(por defecto en Claude 3.5 y más).truepara la serie. - Gemini.Siempre paralela .
tool_config.function_calling_config.mode = "AUTO"Deje que el modelo decida.
Deshabilitar el paralelo cuando las herramientas tengan dependencias de orden (create_fileEntonces ...write_file), cuando la salida de una llamada informa la entrada de otra, o cuando el limitador de velocidad no puede manejar el ventilador.
Correlación de identidad
Cada llamada que emite el modelo tiene unidCada resultado que devuelva el anfitrión debe incluir la misma identificación.
- OpenAI.
tool_call_iden cada mensaje de papel de herramienta. - Anthropic.
tool_use_iden cada unotool_resultEl bloque. - Gemini.
iden cada unofunctionResponse(Gemini 3 y arriba; Gemini 2 coincidió por nombre que rompió para llamadas paralelas del mismo nombre).
Ejecutar llamadas simultáneamente
El anfitrión ejecuta el ejecutor de cada llamada en su propio hilo, coroutine o trabajador remoto.asyncio.gatherEl orden de finalización es impredecible el id es el identificador.
Un error común: responder con resultados en orden de lista de llamadas en lugar de orden de finalización. Esto suele funcionar porque el modelo solo se preocupa por tool_call_id, pero si un resultado se deja caer o se duplica, la presentación fuera de orden hace que el descomposición sea más difícil.
Las llamadas de herramientas de transmisión
Cuando el modelo fluye,argumentsTres flujos separados de trozos para tres llamadas paralelas se interponen en el cable.
Forma por proveedor:
- OpenAI.Cada pieza es
choices[0].delta.tool_calls[i].function.argumentsEl pedazo llevaindexSe acumula por índice, se leeidcuando aparece por primera vez, y analizar JSON cuandofinish_reason = "tool_calls"¿ Qué ? - Anthropic.Los eventos de transmisión son
message_start, luego uno .content_block_startpor bloque con tipotool_use(contiene identificación, nombre, entrada vacía).content_block_deltalos eventos llevaninput_json_deltaLos trozos.content_block_stopcierra cada cuadra. - Gemini.
streamFunctionCallArguments(Gemini 3 y arriba) emite trozos con unfunctionCallIdAntes de Gemini 3, la transmisión devolvió una llamada completa a la vez.
JSON parcial y la trampa de análisis precoz
No puedes analizar .argumentsJSON parcial como {"city": "BengLa puerta correcta es la señal de final de llamada del proveedor: OpenAI finish_reason = "tool_calls", Anthropic's content_block_stop, o el evento de la línea de salida de Géminis.json.loads. Un enfoque más robusto utiliza un parser JSON incremental que produce eventos a medida que se completa la estructura; la guía de transmisión de OpenAI lo recomienda para UX que muestra un indicador de "pensamiento" en vivo. La cuenta de correcciones es poco confiable como prueba de integridad (las correcciones dentro de las cadenas citadas o el contenido escapado causan falsos positivos) y solo debe usarse como una heurística de defecto informal.
Completado fuera de orden
call_A: fast API, returns first
call_B: slow API, returns second
call_C: median API, returns thirdLa respuesta de la anfitriona deberá seguir citando las identidades siguientes:
[{role: "tool", tool_call_id: "call_A", content: ...},
{role: "tool", tool_call_id: "call_B", content: ...},
{role: "tool", tool_call_id: "call_C", content: ...}]El orden en la respuesta no importa para la corrección en OpenAI o Anthropic. Gemini acepta cualquier orden siempre que coincidan las identidades.
Indicador de referencia: secuencial vs paralelo
El arnés en code/main.pySe ejecuta en 1800 ms total. Se ejecuta en paralelo en max ((400, 600, 800) = 800 ms. La diferencia es constante, no proporcional, por lo que los ahorros crecen con el número de herramientas.
Advertencia en el mundo real: llamadas paralelas ponen en riesgo las APIs en el aguas abajo. Una ventaja de 10 vías a un servicio limitado de velocidad fallará. La fase 13 · 17 cubre la presión de retroceso a nivel de puerta de entrada; se planea volver a probar la semántica para una fase futura.
Reloj de pared de ventilador en streaming
Si el modelo en sí mismo transmite, puede comenzar a ejecutar tan pronto como los argumentos de una llamada estén completos, en lugar de esperar a que todas las llamadas se finalicen. Esta es una optimización de los documentos OpenAI pero no todos los SDK exponen. El arnés de esta lección lo hace: tan pronto como el flujo simulado produzca un objeto de argumento completo, el host inicia esa llamada.
Usalo
code/main.pyLa primera ejecuta tres llamadas meteorológicas simuladas secuencialmente y en paralelo utilizandoconcurrent.futures.ThreadPoolExecutorLa segunda mitad reproduce una respuesta de transmisión falsa trozos de argumentspara tres llamadas paralelas entrelazadas en una corriente y las reúne por identificación con StreamAccumulatorNo LLM, no red, sólo la lógica de reensamblaje.
Qué ver:
- El temporizador secuencial alcanza 1,8 segundos y el temporizador paralelo alcanza 0,8 segundos en las mismas latencias falsas.
- El acumulador maneja los trozos que llegan fuera de orden mediante el amortiguamiento por identificación y el análisis solo cuando el JSON de cada llamada esté completo.
- El ejecutor comienza tan pronto como finalizan los argumentos de un ID, no después de que terminen todas las corrientes.
Envío
Esta lección produceoutputs/skill-parallel-call-safety-check.md. Dado un registro de herramientas, las auditorías de habilidades que son seguras para paralelar las herramientas, que tienen dependencias de orden y que abrumarían los límites de tasas a continuación devolver un registro revisado con herramienta por herramienta parallel_safelas banderas.
Los ejercicios
- - ¿ Qué ?
code/main.pyConfirmar que la relación paralelo-secuencial es aproximadamentemax/sum(las carreras reales se desvían ligeramente de la ideal debido a la programación de hilos, la serialización y el gasto superior del arnés).
- Extensión del acumulador para manejar un caso de "llamada fue cancelada en medio de la corriente" dejando caer su amortiguador y emitiendo un
cancelled¿Qué proveedor documenta explícitamente este caso?content_block_stopLa semántica y OpenAIfinish_reason: "length"el comportamiento.
- Remplaza el hilo de hilo con
asyncio.gatherSe deberían ver pequeñas ganancias en async debido al menor costo de cambio de contexto, pero sólo si los ejecutores hacen I/O real.
- Elegir dos herramientas que NO deben estar en paralelo (por ejemplo
create_fileEntonces ...write_fileAñadir unordering_dependencyEl sistema de programación de dependencias es el mínimo que una futura fase de ingeniería de agentes formaliza.
- Lea la sección de llamadas paralelas de funciones de OpenAI y la de Anthropic
disable_parallel_tool_useDocuments. Identifique el tipo de herramienta en el mundo real en el que Anthropic recomienda desactivar el paralelismo.
Términos clave
| Term | What people say | What it actually means |
|---|---|---|
| Parallel tool calls | "Fan-out in one turn" | Model emits multiple tool calls in a single assistant message |
parallel_tool_calls | "OpenAI's flag" | Enable or disable multi-call emission |
disable_parallel_tool_use | "Anthropic's inverse" | Opt-out flag; default is parallel enabled |
| Tool call id | "Correlation handle" | Per-call identifier the result message must echo |
| Accumulator | "Stream buffer" | Per-id string buffer for partial arguments chunks |
| Out-of-order completion | "Fastest first" | Parallel calls finish in unpredictable order; ids are the glue |
| Dependency graph | "Ordering constraints" | Tools whose outputs feed into inputs of other tools; cannot parallelize |
| Parse-early trap | "JSON.parse exploded" | Attempting to parse an incomplete arguments string |
streamFunctionCallArguments | "Gemini 3 feature" | Streamed argument chunks with unique id per call |
| Completion-order reply | "Don't wait for all" | Reply with results as they arrive, keyed by id |
Leer más
- OpenAI — Parallel function calling El comportamiento predeterminado y la bandera de exclusión
- Anthropic — Parallel tool use¿ Qué es esto ?
disable_parallel_tool_usey lotes de resultados - Google — Gemini function calling parallel section Llamadas paralelas correlacionadas con id de Gemini 3
- OpenAI — Streaming responses with tools reensamblaje de argumentos en fragmentos para flujos OpenAI
- Anthropic — Streaming messages¿ Qué es esto ?
content_block_deltaconinput_json_delta
This free lesson is part of the AI Engineering from Scratch curriculum. Read the full explanation, run the lesson code, and verify the result in the interactive reader or from the repository source.
Browse the complete course catalog or open this lesson on GitHub.