Descripción general
Multiagente permite que un modelo cree y coordine subagentes en paralelo y sintetice su trabajo para proporcionar una respuesta final. Esto resulta especialmente eficaz para aplicaciones con tareas complejas que se benefician de delegar trabajo en paralelo, como la exploración de bases de código, la documentación y la implementación.
Multiagente está disponible como función beta con todos los modelos GPT-5.6. Consulta la página del modelo antes de habilitar Multiagente en tu aplicación.
Cuándo usar Multiagente
Las tareas suelen poder dividirse en partes independientes que un solo agente completaría de forma secuencial, pero que varios agentes pueden abordar en paralelo. Multiagente permite que un agente raíz delegue en varios subagentes que realizan el trabajo de forma concurrente. Esto puede ofrecer varios beneficios:
- Ejecución en paralelo. Las tareas independientes de investigación, análisis o implementación pueden avanzar al mismo tiempo, lo que puede acelerar la ejecución.
- Contexto enfocado. Cada subagente recibe una tarea acotada y mantiene su propio contexto, lo que reduce la interferencia entre los contextos de líneas de trabajo no relacionadas y mejora el rendimiento.
- Coordinación dirigida por el modelo. El agente raíz puede crear subagentes, enviarles información adicional, esperar resultados y sintetizar una respuesta final sin que tu aplicación tenga que implementar la orquestación.
La orquestación multiagente resulta más útil cuando una tarea puede dividirse en líneas de trabajo concretas e independientes, como:
- Explorar partes distintas de una base de código grande
- Comparar varias propuestas, documentos o hipótesis
- Investigar varias fuentes en paralelo
- Implementar componentes independientes o escribir conjuntos de pruebas independientes
- Investigar distintas causas posibles de una falla en paralelo
- Explorar distintos enfoques para resolver un problema de forma concurrente
Ten en cuenta que agregar subagentes puede aumentar el uso de tokens y quizá no resulte tan beneficioso para tareas que dependen de una única secuencia ordenada de razonamiento, requieren escrituras frecuentes en un estado mutable compartido o cuyo tiempo de ejecución ya depende principalmente de una sola operación externa lenta.
| Usa Multiagente cuando | Prefiere un solo agente cuando |
|---|---|
| El trabajo se puede dividir en tareas independientes y acotadas | Cada paso depende directamente del anterior |
| Mantener contextos separados ayuda a centrarse en cada tarea | La tarea es lo suficientemente pequeña como para completarse en una sola ejecución breve |
| La exploración en paralelo puede reducir el tiempo total transcurrido | Los agentes competirían por el mismo recurso mutable |
| Comparar hallazgos independientes mejora la cobertura | Necesitas un grafo de ejecución fijo y determinista |
Inicio rápido
Los ejemplos de Python y JavaScript usan el SDK beta de Responses. Para las solicitudes HTTP,
usa client.beta.responses y pasa responses_multi_agent=v1 en
el argumento betas. Para las solicitudes HTTP directas y las conexiones WebSocket, pasa
OpenAI-Beta: responses_multi_agent=v1 en los encabezados de la solicitud o de la conexión.
Los esquemas de los elementos pueden cambiar mientras Multiagente esté en beta.
Habilita Multiagente en tu solicitud a la API Responses con multi_agent.enabled. Cuando multi_agent.enabled es true, el agente raíz puede crear un árbol de subagentes. Los subagentes comparten el modelo y las herramientas disponibles de la solicitud, mientras que los agentes se coordinan mediante primitivas de colaboración como la creación de agentes, la mensajería y la espera (consulta Cómo funciona Multiagente). El agente raíz se encarga de sintetizar las respuestas de los subagentes y proporcionar la respuesta final.
from openai import OpenAI
client = OpenAI()
def review_pull_request(diff: str) -> str:
response = client.beta.responses.create(
model="gpt-5.6-sol",
input=(
"Review the pull-request diff below with three agents: one for "
"correctness, one for security, and one for missing tests. "
"Reconcile duplicate or conflicting findings, then return a "
"prioritized review with file and line references.\n\n"
f"<diff>\n{diff}\n</diff>"
),
multi_agent={
"enabled": True,
"max_concurrent_subagents": 3,
},
betas=["responses_multi_agent=v1"],
)
return "".join(
part.text
for item in response.output
if (
item.type == "message"
and item.agent is not None
and item.agent.agent_name == "/root"
and item.phase == "final_answer"
)
for part in item.content
if part.type == "output_text"
)max_concurrent_subagents establece el número máximo de subagentes que pueden estar activos simultáneamente en todo el árbol de agentes. Incluye a todos los descendientes (hijos, nietos y subagentes de niveles más profundos), pero excluye al agente raíz.
La API no impone un límite superior fijo para esta configuración. El valor predeterminado es 3, que se recomienda para la mayoría de las cargas de trabajo. Las ejecuciones multiagente tampoco tienen un límite fijo para la profundidad del árbol ni para el número total de subagentes creados durante una ejecución.
Agrega un mensaje de desarrollador para ajustar cuándo debe crear subagentes el modelo raíz. Este mensaje de desarrollador se suma a las instrucciones que se inyectan para el agente raíz y los subagentes.
Estos son algunos ejemplos de mensajes de desarrollador:
- “No crees subagentes a menos que el usuario solicite explícitamente subagentes, delegación o trabajo de agentes en paralelo”.
- “La delegación multiagente proactiva está activa. Usa subagentes cuando el trabajo en paralelo mejore sustancialmente la velocidad o la calidad”.
Cómo funciona Multiagente
La API Responses proporciona a los modelos del agente raíz y de los subagentes acciones de orquestación alojadas e instrucciones para usarlas. El agente raíz se llama /root. Los subagentes creados usan rutas jerárquicas como:
/root
├── /root/researcher
├── /root/reviewer
└── /root/reviewer/tester
Multiagente no impone un límite fijo para el número total de subagentes ni para la profundidad del árbol. Para la mayoría de las tareas, usa el valor predeterminado de max_concurrent_subagents, que es 3. Esta configuración limita el número de turnos activos de subagentes en todo el árbol, incluidos los hijos y los descendientes de niveles más profundos.
Cuando el modo multiagente está habilitado, la API Responses proporciona seis acciones de colaboración alojadas. Estas pueden aparecer como elementos multi_agent_call. Tu aplicación no debe ejecutarlas ni enviar resultados para ellas.
| Acción | Propósito |
|---|---|
spawn_agent | Crear un subagente y asignarle su tarea inicial. |
send_message | Poner en cola un mensaje para un agente existente sin iniciar un nuevo turno. |
followup_task | Asignar más trabajo a un agente existente que no sea el agente raíz e iniciar o reanudar su turno. |
wait_agent | Esperar una actualización en el buzón del agente que realiza la llamada. |
interrupt_agent | Interrumpir el turno activo de otro agente sin eliminar su contexto. |
list_agents | Devolver el árbol de agentes actual, los estados y el valor de last_task_message de cada agente. |
La gestión de las llamadas a herramientas definidas por el desarrollador funciona igual que cuando Multiagente no está habilitado. Cualquier agente del árbol puede emitir un function_call. Tu aplicación debe ejecutar la llamada y enviar el function_call_output correspondiente.
Ten en cuenta que todos los agentes del árbol tienen acceso a las herramientas configuradas en la llamada al modelo de la solicitud a la API.
Usar Multiagente en la API Responses
Comparación de rendimiento entre HTTP y WebSocket
HTTP y WebSocket admiten las mismas capacidades de Multiagente, pero se recomienda WebSocket para flujos de trabajo que usan muchas herramientas o son de larga duración. Su conexión persistente permite que tu aplicación devuelva los resultados de las funciones a medida que estén disponibles, lo que reduce la sobrecarga de las continuaciones y permite que los agentes pasen menos tiempo esperando.
Con HTTP, la respuesta se completa una vez que todos los agentes activos hayan terminado o se hayan pausado para esperar una llamada a una función ejecutada por el cliente. Tu aplicación ejecuta entonces todas las llamadas a funciones pendientes y envía sus resultados en una nueva solicitud a la API Responses, lo que permite que los agentes pausados reanuden su trabajo.
Con WebSocket, tu aplicación puede inyectar el resultado de cada función en la respuesta en cuanto esté disponible, sin esperar a que se complete la respuesta activa. El agente que está esperando puede reanudar su trabajo de inmediato mientras los demás agentes siguen trabajando. Esto reduce las demoras de coordinación y evita intercambios adicionales de solicitudes y respuestas cuando los agentes terminan o solicitan herramientas en distintos momentos.
HTTP puede ser suficiente para flujos de trabajo que requieren llamar a varias herramientas alojadas, como búsquedas web en paralelo, o para flujos de trabajo de una sola solicitud con pocas llamadas a funciones. Para la mayoría de los flujos de trabajo multiagente, es probable que WebSocket ofrezca menor latencia y mejor rendimiento de principio a fin.
Ejecución de llamadas a funciones mediante HTTP

Ejecución de llamadas a funciones mediante WebSocket

HTTP
Estos ejemplos requieren versiones beta del SDK que expongan la API Responses beta. Para usar streaming por HTTP, llama a client.beta.responses.create y pasa responses_multi_agent=v1 mediante el argumento betas; esto habilita los tipos beta y el autocompletado. En Python, importa los tipos de elementos de respuesta beta desde openai.types.beta al agregar anotaciones de tipo.
Ejemplo de código del lado del cliente:
from __future__ import annotations
import json
import sys
from openai import OpenAI
from openai.types.beta import BetaResponseOutputItem
client = OpenAI()
ROOT = "/root"
PROPOSALS = {
"alpha": {"estimated_weeks": 6, "risk": "medium"},
"beta": {"estimated_weeks": 8, "risk": "low"},
}
tools = [
{
"type": "function",
"name": "get_proposal",
"description": "Return details for a proposal that the agents should compare.",
"parameters": {
"type": "object",
"properties": {
"proposal": {
"type": "string",
"enum": ["alpha", "beta"],
}
},
"required": ["proposal"],
"additionalProperties": False,
},
"strict": True,
}
]
history = [
{
"role": "user",
"content": "Compare proposal alpha and proposal beta.",
}
]
def agent_name(item: BetaResponseOutputItem) -> str:
return item.agent.agent_name if item.agent else ROOT
def render_to_user(delta: str) -> None:
print(delta, end="", flush=True)
def log_subagent_text(agent: str, delta: str) -> None:
print(f"[{agent}] {delta}", end="", file=sys.stderr, flush=True)
def process_tool_call(name: str, arguments: str) -> str:
if name != "get_proposal":
raise ValueError(f"Unknown tool: {name}")
parsed_arguments = json.loads(arguments)
return json.dumps(PROPOSALS[parsed_arguments["proposal"]])
while True:
output_items = []
pending_calls = []
item_agents: dict[int, str] = {}
stream = client.beta.responses.create(
model="gpt-5.6-sol",
input=history,
tools=tools,
store=False,
multi_agent={
"enabled": True,
"max_concurrent_subagents": 3,
},
stream=True,
betas=["responses_multi_agent=v1"],
)
for event in stream:
if event.type == "response.output_item.added":
item_agents[event.output_index] = agent_name(event.item)
elif event.type == "response.output_text.delta":
agent = item_agents.get(event.output_index, ROOT)
if agent == ROOT:
render_to_user(event.delta)
else:
log_subagent_text(agent, event.delta)
elif event.type == "response.output_item.done":
output_items.append(event.item)
if event.item.type == "function_call":
# Handle function calls from both the root agent and subagents.
pending_calls.append(event.item)
elif event.type == "response.completed":
print(f"\nUsage: {event.response.usage}", file=sys.stderr)
break
elif event.type in {
"error",
"response.failed",
"response.incomplete",
}:
raise RuntimeError(event)
history.extend(output_items)
for call in pending_calls:
history.append(
{
"type": "function_call_output",
"call_id": call.call_id,
"output": process_tool_call(call.name, call.arguments),
}
)
if not pending_calls:
breakSi uno o más agentes llaman a funciones definidas por el desarrollador, ejecuta todas las llamadas pendientes y crea una solicitud de continuación que contenga sus resultados.
WebSocket
En el modo WebSocket, cuando un agente llama a una función definida por el desarrollador, ejecuta la función en tu aplicación y envía su resultado a la respuesta activa mediante un evento response.inject. Así, el agente en espera puede reanudar su trabajo sin esperar a que se complete toda la respuesta de Multiagente.
{
"type": "response.inject",
"response_id": "resp_123",
"input": [
{
"type": "function_call_output",
"call_id": "call_123",
"output": "{\"temperature\":72}"
}
]
}
Ante una solicitud response.inject válida, el servidor responde con uno de estos dos eventos:
response.inject.created: la entrada se validó y se aceptó para su inyecciónresponse.inject.failed: la entrada no se inyectó; revisaerror.code
{
"type": "response.inject.created",
"sequence_number": 42,
"response_id": "resp_123"
}
{
"type": "response.inject.failed",
"sequence_number": 43,
"response_id": "resp_123",
"input": [
{
"type": "function_call_output",
"call_id": "call_123",
"output": "{\"temperature\":72}"
}
],
"error": {
"code": "response_already_completed",
"message": "Response 'resp_123' has already completed."
}
}
Si una solicitud no cumple con el esquema de response.inject, el servidor envía un error genérico con el estado 400 y cierra la conexión WebSocket. Corrige la solicitud y abre una nueva conexión WebSocket antes de enviar otro evento.
El SDK beta de Python ofrece el modo WebSocket mediante client.beta.responses.connect. El SDK beta de TypeScript lo ofrece mediante ResponsesWS. Pasa OpenAI-Beta: responses_multi_agent=v1 en los encabezados de la conexión; a diferencia del streaming por HTTP, los conectores WebSocket todavía no aceptan el argumento betas.
Guarda el ID de respuesta del evento response.created e inclúyelo en cada evento response.inject que envíes para esa respuesta. Después de enviar un elemento de inyección, continúa leyendo del WebSocket hasta que la respuesta se haya completado y cada inyección haya producido un evento response.inject.created o response.inject.failed.
from __future__ import annotations
import json
from openai import OpenAI
client = OpenAI()
PROPOSALS = {
"alpha": {"estimated_weeks": 6, "risk": "medium"},
"beta": {"estimated_weeks": 8, "risk": "low"},
}
tools = [
{
"type": "function",
"name": "get_proposal",
"description": "Return details for a proposal that the agents should compare.",
"parameters": {
"type": "object",
"properties": {
"proposal": {
"type": "string",
"enum": ["alpha", "beta"],
}
},
"required": ["proposal"],
"additionalProperties": False,
},
"strict": True,
}
]
def process_tool_call(name: str, arguments: str) -> str:
if name != "get_proposal":
raise ValueError(f"Unknown tool: {name}")
parsed_arguments = json.loads(arguments)
return json.dumps(PROPOSALS[parsed_arguments["proposal"]])
def run_multi_agent(connection):
previous_response_id: str | None = None
pending_input: list[dict[str, object]] = [{"role": "user", "content": input()}]
while pending_input:
request = {
"type": "response.create",
"model": "gpt-5.6-sol",
"store": True,
"multi_agent": {"enabled": True},
"tools": tools,
"input": pending_input,
}
if previous_response_id is not None:
request["previous_response_id"] = previous_response_id
connection.send(request)
next_input: list[dict[str, object]] = []
completed_response = None
response_id: str | None = None
pending_injections = 0
for event in connection:
event_type = event.type
if event_type == "response.created":
response_id = event.response.id
elif event_type == "response.output_item.done":
item = event.item
if item.type == "function_call":
if response_id is None:
raise RuntimeError(
"Received a function call before response.created"
)
output = {
"type": "function_call_output",
"call_id": item.call_id,
"output": process_tool_call(item.name, item.arguments),
}
pending_injections += 1
connection.send(
{
"type": "response.inject",
"response_id": response_id,
"input": [output],
}
)
elif event_type == "response.inject.created":
pending_injections -= 1
elif event_type == "response.inject.failed":
pending_injections -= 1
if event.error.code != "response_already_completed":
raise RuntimeError(event.error)
next_input.extend(item.model_dump(mode="json") for item in event.input)
elif event_type == "response.completed":
completed_response = event.response
elif event_type in {
"error",
"response.failed",
"response.incomplete",
}:
raise RuntimeError(event)
if completed_response is not None and pending_injections == 0:
break
if completed_response is None:
raise RuntimeError("Connection ended before response.completed")
if not next_input:
return completed_response
previous_response_id = completed_response.id
pending_input = next_input
with client.beta.responses.connect(
extra_headers={"OpenAI-Beta": "responses_multi_agent=v1"},
) as connection:
run_multi_agent(connection)Después de enviar un evento response.inject, continúa leyendo del WebSocket y procesa el acuse de recibo:
response.inject.created: el resultado de la función se agregó a la respuesta activa. Continúa leyendo los eventos de esa respuesta.response.inject.failedconresponse_already_completed: la respuesta se completó antes de que se pudiera agregar el resultado de la función. Toma el valor deinputdevuelto en el evento de error y envíalo en una nueva solicitudresponse.createque continúe a partir de la respuesta completada.response.inject.failedconresponse_not_found: el servidor no pudo encontrar la respuesta identificada porresponse_id. Verifica que estés usando el ID recibido enresponse.created.
Una sola ejecución de Multiagente puede abarcar varias solicitudes a la API Responses. Por HTTP, cuando un agente llama a una función definida por el desarrollador, tu aplicación ejecuta la función y envía su resultado en una nueva llamada a response.create. Por WebSocket, tu aplicación inyecta el resultado de la función directamente en la respuesta activa.
Nuevos elementos de salida de Multiagente
Las respuestas de Multiagente pueden incluir tres tipos adicionales de elementos de salida:
multi_agent_call: registra una acción alojada de Multiagente, comospawn_agent.multi_agent_call_output: contiene el resultado de la ejecución de una acción alojada.agent_message: transporta un mensaje cifrado de un agente a otro.
El campo call_id vincula cada multi_agent_call con su multi_agent_call_output correspondiente.
Cada elemento también incluye un atributo agent. En un agent_message, agent.agent_name identifica al agente destinatario. Usa author y recipient para rastrear la dirección del mensaje.
Cuando tu aplicación reciba un multi_agent_call, no lo ejecutes como una llamada a función ni devuelvas un resultado. La API Responses ejecuta la acción alojada y devuelve el multi_agent_call_output correspondiente. Conserva ambos elementos si tu aplicación los necesita para reproducir la ejecución o rastrearla.
[
{
"type": "multi_agent_call",
"id": "mac_123",
"call_id": "call_spawn_a",
"action": "spawn_agent",
"arguments": "{\"task_name\":\"agent_a\",\"fork_turns\":\"all\",\"message\":\"enc_...\"}",
"agent": { "agent_name": "/root" }
},
{
"type": "multi_agent_call_output",
"id": "maco_123",
"call_id": "call_spawn_a",
"action": "spawn_agent",
"output": [
{
"type": "output_text",
"text": "{\"task_name\":\"/root/agent_a\"}",
"annotations": [],
"logprobs": []
}
],
"agent": { "agent_name": "/root" }
},
{
"type": "agent_message",
"id": "amsg_123",
"author": "/root/agent_a",
"recipient": "/root",
"content": [
{
"type": "encrypted_content",
"encrypted_content": "enc_..."
}
],
"agent": { "agent_name": "/root" }
}
]
Los eventos SSE atribuidos a agentes incluyen un atributo agent de nivel superior. En un evento agent_message, agent.agent_name identifica al agente destinatario. Los eventos del ciclo de vida de la respuesta, como response.created y response.completed, describen la respuesta en su conjunto en lugar de un agente individual, por lo que no incluyen un atributo agent.
{
"type": "response.output_item.done",
"agent": { "agent_name": "/root" },
"item": {
"type": "agent_message",
"id": "amsg_123",
"author": "/root/agent_a",
"recipient": "/root",
"content": [
{
"type": "encrypted_content",
"encrypted_content": "enc_..."
}
],
"agent": { "agent_name": "/root" }
}
}
Limitaciones
- Compactación:
- El punto de acceso
/responses/compactno es compatible con Multiagente habilitado. - Cuando
multi_agent.enabledse establece entrue, la compactación automática del lado del servidor se habilita de forma implícita, incluso si la solicitud no configuracontext_management. La compactación se aplica de forma independiente al agente raíz y a cada subagente, manteniendo sus contextos separados. Los usuarios pueden modificar el valor decompact_thresholdestableciendo un valor explícito decontext_management.compact_thresholden la solicitud.
- El punto de acceso
reasoning.summaryno es compatible con Multiagente habilitado.max_tool_callsno es compatible con Multiagente habilitado.- El valor predeterminado de
max_concurrent_subagentses3, que es la configuración recomendada.
Guía para prompts
Cuando Multiagente está habilitado, nuestros sistemas agregan automáticamente estas instrucciones al agente raíz y a los subagentes como un nuevo mensaje de desarrollador. No puedes editar ni eliminar estas instrucciones, pero debes formular tus instrucciones de desarrollador como un complemento de las que se inyectan automáticamente.
Agente raíz
You are `/root`, the primary agent in a team of agents collaborating to fulfill the user's goals.
At the start of your turn, you are the active agent.
You can spawn sub-agents to handle subtasks, and those sub-agents can spawn their own sub-agents.
All agents in the team, including the agents that you can assign tasks to, are equally intelligent and capable, and have access to the same set of tools.
You can use `spawn_agent` to create a new agent, `followup_task` to give an existing agent a new task and trigger a turn, and `send_message` to pass a message to a running agent without triggering a turn.
Child agents can also spawn their own sub-agents.
You can decide how much context you want to propagate to your sub-agents with the `fork_turns` parameter.
You will receive messages in the form:
```
Message Type: MESSAGE | FINAL_ANSWER
Task name: <recipient>
Sender: <author>
Payload:
<payload text>
```
They may be addressed as to=/root
There are {max_concurrent_subagents + 1} available concurrency slots, meaning that up to {max_concurrent_subagents + 1} agents can be active at once, including you.
Subagente
You are an agent in a team of agents collaborating to complete a task.
You can spawn sub-agents to handle subtasks, and those sub-agents can spawn their own sub-agents. All agents in the team, including the agents that you can assign tasks to, are equally intelligent and capable, and have access to the same set of tools.
You can use `spawn_agent` to create a new agent, `followup_task` to give an existing agent a new task and trigger a turn, and `send_message` to pass a message to a running agent.
Child agents can also spawn their own sub-agents.
When you provide a response in the final channel, that content is immediately delivered back to your parent agent.
You will receive messages in the form:
```
Message Type: NEW_TASK | MESSAGE | FINAL_ANSWER
Task name: <recipient>
Sender: <author>
Payload:
<payload text>
```
You may also see them addressed as to=/root/..., which indicates your identity is /root/...
There are {max_concurrent_subagents + 1} available concurrency slots, meaning that up to {max_concurrent_subagents + 1} agents can be active at once, including you.