
# Transferências assíncronas

Use `start_workflows()` quando um workflow precisar encaminhar o trabalho descoberto para workflows independentes de nível superior, em vez de manter tudo em uma única execução.

Se você estiver modelando explicitamente execuções de agentes, `start_agents()` e `wait_for_agents()` são aliases semânticos com padrões orientados a agentes.

Para exemplos mais completos, de ponta a ponta, consulte [Orquestração de agentes](https://queuety.inline0.dev/pt/docs/workflows/agent-orchestration).

Isso é útil para orquestração no estilo de agentes:

- um workflow planejador descobre tarefas em tempo de execução
- cada tarefa se torna seu próprio workflow duradouro
- o processo pai armazena os IDs desses workflows no estado
- mais tarde, o processo pai pode aguardar `all`, `any`, `quorum` ou um grupo iniciado identificado por nome

## O método `->start_workflows()`

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

$agent_task = Queuety::workflow( 'agent_task' )
    ->then( ResearchTopicStep::class )
    ->then( SummarizeTopicStep::class );

Queuety::workflow( 'brief_research' )
    ->then( PlanTopicsStep::class )
    ->start_workflows(
        items_key: 'topics',
        workflow_builder: $agent_task,
        result_key: 'child_workflow_ids',
        group_key: 'researchers',
    )
    ->wait_for_workflow_group( 'researchers', WaitMode::All, result_key: 'child_results' )
    ->then( SynthesizeBriefStep::class )
    ->dispatch( [ 'brief_id' => 42 ] );
```

Nesse exemplo:

1. `PlanTopicsStep` grava uma matriz de payloads de tópicos em `$state['topics']`
2. `start_workflows()` despacha um workflow `agent_task` duradouro por tópico
3. Os IDs dos workflows iniciados são gravados em `$state['child_workflow_ids']`
4. `wait_for_workflow_group()` pausa até que o grupo iniciado satisfaça a condição de conclusão escolhida
5. `SynthesizeBriefStep` recebe os estados dos filhos concluídos em `$state['child_results']`

## Payloads dos filhos

Cada item em `items_key` se torna o payload inicial de um workflow iniciado.

Se o item for uma matriz, suas chaves públicas serão mescladas ao payload do filho:

```php
[
    [ 'topic' => 'pricing', 'source' => 'competitors' ],
    [ 'topic' => 'reviews', 'source' => 'customers' ],
]
```

Se o item for escalar, Queuety o armazena em `payload_key`:

```php
->start_workflows(
    items_key: 'topic_names',
    workflow_builder: $agent_task,
    payload_key: 'topic',
)
```

## Herança do estado do processo pai

Por padrão, `start_workflows()` mescla o estado público do workflow pai ao payload de cada filho.

Isso significa que contexto compartilhado, como `brief_id`, `account_id` ou `campaign`, fica automaticamente disponível em cada workflow iniciado.

A origem `items_key` e o `result_key` são excluídos da herança para que cada filho não receba a lista completa de tarefas nem a matriz final de IDs de workflow.

Defina `inherit_state: false` quando cada filho deve receber apenas o payload do próprio item.

## Por que não usar `run_workflow()`?

`run_workflow()` cria uma relação entre pai e filho, na qual o processo pai fica parado nessa etapa até a conclusão do filho.

`start_workflows()` é mais flexível:

- os workflows iniciados são workflows independentes de nível superior
- cada workflow iniciado pode ser inspecionado, repetido ou exportado por conta própria
- o processo pai decide mais tarde se vai aguardar por eles e como

Isso torna `start_workflows()` mais adequado para transferir tarefas de agentes de forma assíncrona, enquanto `run_workflow()` continua sendo mais adequado para composição aninhada dentro de uma única árvore de orquestração.

## Aguardar mais tarde

`start_workflows()` foi desenvolvido para ser combinado com [Dependências de workflow](https://queuety.inline0.dev/pt/docs/workflows/dependencies):

```php
use Queuety\Enums\WaitMode;

Queuety::workflow( 'review_board' )
    ->start_workflows( 'review_tasks', $review_task_workflow, 'review_workflow_ids' )
    ->wait_for_workflows( 'review_workflow_ids', WaitMode::Any, 'winner' )
    ->then( FinalizeDecisionStep::class )
    ->dispatch( $payload );
```

- `WaitMode::All` reúne todos os estados dos filhos concluídos
- `WaitMode::Any` retoma na primeira execução de workflow filha bem-sucedida

Isso permite orquestrar planejador e executor sem precisar de um mecanismo DAG totalmente editável em tempo de execução.

## Aliases para agentes

`start_agents()` é um alias de `start_workflows()` com padrões ajustados para fluxos de planejador e executor:

- `result_key` assume `agent_workflow_ids` por padrão
- `payload_key` assume `agent_task` por padrão
- `name` assume `start_agents` por padrão

`wait_for_agents()` é um alias de `wait_for_workflows()` com padrões ajustados para coletar resultados de agentes:

- `workflows` assume `agent_workflow_ids` por padrão
- `result_key` assume `agent_results` por padrão
- `name` assume `wait_for_agents` por padrão

`wait_for_agent_group()` é um alias de `wait_for_workflow_group()` com padrões ajustados para lotes de agentes.

```php
use Queuety\Enums\WaitMode;

$agent_run = Queuety::workflow( 'agent_run' )
    ->then( ResearchTopicStep::class )
    ->then( SummarizeTopicStep::class );

Queuety::workflow( 'brief_research' )
    ->then( PlanTopicsStep::class )
    ->start_agents( 'agent_tasks', $agent_run, group_key: 'researchers' )
    ->wait_for_agent_group( 'researchers', WaitMode::Quorum, 2 )
    ->then( SynthesizeBriefStep::class )
    ->dispatch( [ 'brief_id' => 42 ] );
```
