
# Orquestación de agentes

Queuety es una buena opción para sistemas de agentes cuando necesita un trabajo adaptable con estado duradero, reintentos, inspección y semántica de espera explícita.

No necesita un motor DAG editable en tiempo de ejecución para la mayoría de los flujos de agentes. En la práctica, la mayoría de los sistemas se pueden modelar con un pequeño conjunto de operaciones de orquestación duraderas. `for_each()` amplía el trabajo dentro de una ejecución de flujo de trabajo. `start_agents()` y `wait_for_agents()` transfieren el trabajo descubierto en tiempo de ejecución a flujos de trabajo independientes de nivel superior. `wait_for_decision()` y `wait_for_input()` pausan la ejecución para permitir la intervención humana. `wait_for_workflow()`, `wait_for_workflows()` y `wait_for_agent_group()` permiten que una ejecución de nivel superior espere a otra o a que se inicie un grupo mínimo.

## Un modelo mental útil

La orquestación de agentes es más fácil de entender por capas. Un planificador decide qué trabajo hay que hacer. Queuety convierte ese trabajo en tareas o flujos de trabajo duraderos. Las ejecuciones especializadas producen resultados y guardan artefactos. Una etapa de supervisión reúne esos resultados y decide qué sucede después. En cualquier momento, una persona puede aprobar, rechazar o corregir la ejecución antes de que continúe.

La distinción importante es que el agente decide qué trabajo realizar, pero Queuety sigue decidiendo cómo se persiste, se reintenta, se reanuda y se agregan los resultados de ese trabajo. Cuando el objetivo de la orquestación es una sesión de larga duración en lugar de una ejecución acotada, combínelo con [Máquinas de estado](https://queuety.inline0.dev/es/docs/state-machines).

## Patrón 1: planificador y ejecutor con ejecuciones de agentes independientes

Use `start_agents()` cuando un paso del planificador descubra tareas en tiempo de ejecución y cada tarea deba convertirse en su propio flujo de trabajo de nivel superior.

```php
use Queuety\Enums\WaitMode;
use Queuety\Queuety;

$agent_run = Queuety::workflow( 'agent_run' )
    ->then( FetchSourcesStep::class )
    ->then( DraftFindingStep::class );

Queuety::workflow( 'brief_research' )
    ->version( 'brief-research.v1' )
    ->idempotency_key( 'brief:42:research' )
    ->max_transitions( 20 )
    ->then( PlanResearchTasksStep::class )
    ->start_agents( 'agent_tasks', $agent_run, group_key: 'researchers' )
    ->wait_for_agent_group( 'researchers', WaitMode::Quorum, 2, 'agent_results' )
    ->then( SynthesizeBriefStep::class )
    ->dispatch( [ 'brief_id' => 42 ] );
```

En este patrón, `PlanResearchTasksStep` escribe los elementos descubiertos en tiempo de ejecución en `$state['agent_tasks']`, `start_agents()` inicia un flujo de trabajo duradero por tarea y `wait_for_agent_group()` deja en espera al flujo principal hasta que se cumpla la condición de finalización elegida. Luego, `SynthesizeBriefStep` recibe los estados de los procesos secundarios completados en `$state['agent_results']`.

Este es el punto de partida más claro para los sistemas de planificador y ejecutor, porque cada ejecución de agente se puede inspeccionar y reintentar de forma independiente.

## Patrón 2: revisión humana antes de continuar la ejecución

Use `wait_for_decision()` cuando el flujo de trabajo deba detenerse para recibir una decisión real de sí o no, y `wait_for_input()` cuando el operador necesite enviar comentarios estructurados a la ejecución.

```php
use Queuety\Queuety;

$workflow_id = Queuety::workflow( 'brief_review' )
    ->then( DraftBriefStep::class )
    ->wait_for_decision( result_key: 'review' )
    ->then( HandleReviewDecisionStep::class )
    ->wait_for_input( result_key: 'revision_notes' )
    ->then( ApplyRevisionNotesStep::class )
    ->dispatch( [ 'brief_id' => 42 ] );
```

Si la persona revisora aprueba:

```php
Queuety::approve_workflow(
    $workflow_id,
    [
        'reviewer' => 'editor@example.com',
        'notes' => 'Looks good, publish after legal check',
    ],
    'approved'
);
```

Si la persona revisora rechaza:

```php
Queuety::reject_workflow(
    $workflow_id,
    [
        'reviewer' => 'editor@example.com',
        'reason' => 'Needs citations and a stronger conclusion',
    ],
    'rejected'
);
```

Después de `wait_for_decision()`, el flujo de trabajo recibe una carga útil estructurada con el resultado final, la señal que reanudó la ejecución y los datos que haya enviado la persona revisora. Así se obtiene un punto de control con una persona en el proceso, sin mantener abierto un proceso PHP mientras la ejecución espera.

## Patrón 3: un flujo de trabajo de nivel superior espera a otro

A veces, el modelo más claro no es un único flujo de trabajo enorme. Un flujo puede terminar la investigación y otro puede esperar a que termine antes de iniciar la siguiente etapa.

```php
use Queuety\Enums\WaitMode;
use Queuety\Queuety;

$research_id = Queuety::workflow( 'research_brief' )
    ->then( PlanResearchTasksStep::class )
    ->start_agents( 'agent_tasks', $agent_run )
    ->wait_for_agents( mode: WaitMode::All, result_key: 'agent_results' )
    ->then( SynthesizeBriefStep::class )
    ->dispatch( [ 'brief_id' => 42 ] );

Queuety::workflow( 'publish_brief' )
    ->wait_for_workflow( $research_id, 'research' )
    ->wait_for_decision( result_key: 'editor_review' )
    ->then( PublishBriefStep::class )
    ->dispatch( [ 'brief_id' => 42 ] );
```

Así se crea un límite duradero entre la etapa de investigación y la de publicación. Cada ejecución tiene su propio ciclo de vida operativo, pero el segundo flujo de trabajo se reanuda automáticamente cuando se completa la dependencia.

## Cómo elegir la primitiva adecuada

`for_each()` es la herramienta adecuada cuando el trabajo pertenece a una sola ejecución de flujo de trabajo y las ramas son, en realidad, ejecución paralela a nivel de pasos sobre un mismo conjunto de estado compartido.

`start_agents()` es más adecuada cuando cada tarea descubierta debe ser su propia ejecución duradera de nivel superior y desea inspeccionar, reintentar o exportar cada ejecución por separado.

`wait_for_workflow()` y `wait_for_workflows()` son adecuadas cuando un flujo de trabajo de nivel superior depende de otro y desea una coordinación asíncrona duradera entre esas capas de orquestación.

`wait_for_decision()` y `wait_for_input()` corresponden a los puntos en los que una persona debe aprobar, rechazar o dirigir la ejecución, mientras el flujo de trabajo permanece en pausa sin consumir capacidad de los trabajadores.

## Convenciones de estado sugeridas

Los sistemas de agentes son más fáciles de depurar cuando las claves de estado siguen un patrón predecible. En la práctica, `agent_tasks` funciona bien para la salida del planificador, `agent_workflow_ids` para las ejecuciones de nivel superior iniciadas, `agent_results` para el estado de los flujos de trabajo secundarios completados y `review` o `decision` para las cargas útiles de aprobación o rechazo. Las salidas más grandes, como borradores, citas o manifiestos de investigación, suelen guardarse en el almacén de artefactos en lugar de en el conjunto de estado principal del flujo de trabajo.

## Medidas de protección recomendadas para las ejecuciones de agentes

Los flujos de trabajo de agentes se benefician de las medidas de protección más que casi cualquier otro caso de uso, porque son dinámicos por naturaleza.

```php
Queuety::workflow( 'agent_research' )
    ->version( 'agent-research.v2' )
    ->idempotency_key( 'brief:42:agent-research' )
    ->max_transitions( 20 )
    ->max_for_each_items( 12 )
    ->max_state_bytes( 32768 );
```

Estos controles responden a las preguntas prácticas que importan en producción: qué versión de la definición generó una ejecución, si solicitudes externas duplicadas pueden iniciarla dos veces, si un planificador puede crear demasiadas ramas y si el estado del flujo de trabajo puede crecer sin límite. Para la mayoría de los sistemas de agentes, empiece por esas medidas antes de ajustar la cantidad de trabajadores o la topología de las colas.

## Véase también

- [Ejemplos](https://queuety.inline0.dev/es/docs/examples)
- [Activadores de acciones](https://queuety.inline0.dev/es/docs/features/action-triggers)
- [Bucle dinámico For-Each](https://queuety.inline0.dev/es/docs/workflows/for-each)
- [Transferencias asíncronas](https://queuety.inline0.dev/es/docs/workflows/async-handoffs)
- [Dependencias entre flujos de trabajo](https://queuety.inline0.dev/es/docs/workflows/dependencies)
- [Artefactos](https://queuety.inline0.dev/es/docs/features/artifacts)
- [Señales de flujo de trabajo](https://queuety.inline0.dev/es/docs/workflows/signals)
- [Medidas de protección del flujo de trabajo](https://queuety.inline0.dev/es/docs/workflows/guardrails)
