
# Asynkroniset siirrot

Käytä `start_workflows()`-toimintoa, kun työnkulun pitää siirtää löydetty työ riippumattomiin ylätason työnkulkuihin sen sijaan, että kaikki pidettäisiin yhdessä suorituksessa.

Jos mallinnat nimenomaan agenttien suorituksia, `start_agents()` ja `wait_for_agents()` ovat semanttisia aliaksia, joissa on agenteille sopivat oletukset.

Laajemmat päästä päähän -esimerkit ovat sivulla [Agenttien orkestrointi](https://queuety.inline0.dev/fi/docs/workflows/agent-orchestration).

Tästä on hyötyä agenttityyppisessä orkestroinnissa:

- suunnittelijan työnkulku löytää tehtäviä suorituksen aikana
- jokaisesta tehtävästä tulee oma pysyvä työnkulku
- ylätason työnkulku tallentaa näiden työnkulkujen tunnisteet tilaansa
- ylätason työnkulku voi myöhemmin odottaa tunnisteita `all`, `any`, `quorum` tai nimetyn aloitettujen ryhmän valmistumista

## `->start_workflows()`-menetelmä

```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 ] );
```

Tässä esimerkissä:

1. `PlanTopicsStep` kirjoittaa aihetietosisältöjen taulukon kohteeseen `$state['topics']`
2. `start_workflows()` käynnistää yhden `agent_task`-työnkulun aihetta kohden
3. Aloitettujen työnkulkujen tunnisteet kirjoitetaan kohteeseen `$state['child_workflow_ids']`
4. `wait_for_workflow_group()` keskeyttää suorituksen, kunnes aloitettu ryhmä täyttää valitun valmistumisehdon
5. `SynthesizeBriefStep` saa valmiiden alityönkulkujen tilat kohteesta `$state['child_results']`

## Alityönkulkujen tietosisällöt

Jokaisesta kohteen `items_key` kohteesta tulee yhden aloitetun työnkulun alkutietosisältö.

Jos kohde on taulukko, sen julkiset avaimet yhdistetään alityönkulun tietosisältöön:

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

Jos kohde on skalaarinen arvo, Queuety tallentaa sen kohteeseen `payload_key`:

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

## Ylätason tilan periminen

Oletusarvoisesti `start_workflows()` yhdistää ylätason työnkulun julkisen tilan jokaisen alityönkulun tietosisältöön.

Tämä tarkoittaa, että yhteinen asiayhteys, kuten `brief_id`, `account_id` tai `campaign`, on automaattisesti käytettävissä jokaisessa aloitetussa työnkulussa.

Lähde `items_key` ja `result_key` jätetään perimisen ulkopuolelle, jotta kukin alityönkulku ei saa koko tehtäväluetteloa tai työnkulun lopullisten tunnisteiden taulukkoa.

Aseta `inherit_state: false`, kun kunkin alityönkulun pitäisi saada vain oman kohteensa tietosisältö.

## Miksi ei `run_workflow()`?

`run_workflow()` luo ylätason työnkulun ja alityönkulun välisen suhteen, jossa ylätason työnkulku jää kyseiseen vaiheeseen, kunnes alityönkulku valmistuu.

`start_workflows()` on väljempi vaihtoehto:

- Aloitetut työnkulut ovat itsenäisiä ylätason työnkulkuja
- Jokaisen aloitetun työnkulun voi tarkastella, yrittää uudelleen tai viedä erikseen
- Ylätason työnkulku päättää myöhemmin, odottaako se niitä ja miten

Siksi `start_workflows()` sopii paremmin agenttitehtävien asynkroniseen siirtämiseen, kun taas `run_workflow()` sopii paremmin sisäkkäiseen koostamiseen yhdessä orkestrointipuussa.

## Odottaminen myöhemmin

`start_workflows()` on suunniteltu toimimaan yhdessä [Työnkulkujen riippuvuuksien](https://queuety.inline0.dev/fi/docs/workflows/dependencies) kanssa:

```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` kerää kaikkien valmiiden alityönkulkujen tilat
- `WaitMode::Any` jatkaa ensimmäisen onnistuneen alityönkulun valmistuessa

Tämän avulla voit toteuttaa suunnittelija-suorittaja-orkestroinnin ilman kokonaan suorituksen aikana muokattavaa DAG-moottoria.

## Agenteille sopivat aliakset

`start_agents()` on `start_workflows()`-toiminnon alias, jonka oletukset on mukautettu suunnittelija-suorittaja-työnkulkuihin:

- `result_key`-oletusarvona on `agent_workflow_ids`
- `payload_key`-oletusarvona on `agent_task`
- `name`-oletusarvona on `start_agents`

`wait_for_agents()` on `wait_for_workflows()`-toiminnon alias, jonka oletukset on mukautettu agenttitulosten keräämiseen:

- `workflows`-oletusarvona on `agent_workflow_ids`
- `result_key`-oletusarvona on `agent_results`
- `name`-oletusarvona on `wait_for_agents`

`wait_for_agent_group()` on `wait_for_workflow_group()`-toiminnon alias, jonka oletukset on mukautettu agenttien eräajoihin.

```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 ] );
```
