
# Asynkrone overdragelser

Brug `start_workflows()`, når et workflow skal overdrage opdaget arbejde til uafhængige workflows på topniveau i stedet for at beholde alt i én kørsel.

Hvis du udtrykkeligt modellerer agentkørsler, er `start_agents()` og `wait_for_agents()` semantiske aliaser med standardindstillinger tilpasset agenter.

Se [Agentorkestrering](https://queuety.inline0.dev/da/docs/workflows/agent-orchestration) for større eksempler fra start til slut.

Dette er nyttigt til orkestrering i agentstil:

- et planlæggerworkflow finder opgaver under kørsel
- hver opgave bliver sit eget persistente workflow
- det overordnede workflow gemmer workflow-ID'erne i tilstanden
- det overordnede workflow kan senere vente på `all`, `any`, `quorum` eller en navngiven startet gruppe

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

I dette eksempel:

1. `PlanTopicsStep` skriver et array af emnepayloads til `$state['topics']`
2. `start_workflows()` sender ét `agent_task`-workflow af sted pr. emne
3. ID'erne for de startede workflows skrives til `$state['child_workflow_ids']`
4. `wait_for_workflow_group()` sætter kørslen på pause, indtil den startede gruppe opfylder den valgte fuldførelsesbetingelse
5. `SynthesizeBriefStep` modtager tilstandene for de færdige underordnede workflows under `$state['child_results']`

## Payloads for underordnede workflows

Hvert element i `items_key` bliver den indledende payload for ét startet workflow.

Hvis elementet er et array, flettes dets offentlige nøgler ind i payloaden for det underordnede workflow:

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

Hvis elementet er en skalarværdi, gemmer Queuety den under `payload_key`:

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

## Nedarvning af tilstanden fra det overordnede workflow

Som standard fletter `start_workflows()` det overordnede workflows offentlige tilstand ind i hver payload for underordnede workflows.

Det betyder, at delt kontekst som `brief_id`, `account_id` eller `campaign` automatisk er tilgængelig i hvert startet workflow.

Kilden `items_key` og `result_key` udelades fra nedarvningen, så hvert underordnet workflow ikke modtager hele opgavelisten eller det endelige array med workflow-ID'er.

Indstil `inherit_state: false`, når hvert underordnet workflow kun skal modtage sin egen elementpayload.

## Hvorfor ikke `run_workflow()`?

`run_workflow()` opretter en relation mellem overordnet og underordnet workflow, hvor det overordnede workflow sættes på pause ved dette trin, indtil det underordnede workflow er fuldført.

`start_workflows()` er mere fleksibelt:

- de startede workflows er uafhængige workflows på topniveau
- hvert startet workflow kan inspiceres, prøves igen eller eksporteres for sig
- det overordnede workflow afgør senere, om og hvordan det skal vente på dem

Det gør `start_workflows()` bedre egnet til asynkron overdragelse af agentopgaver, mens `run_workflow()` fortsat er bedst egnet til indlejret sammensætning i ét orkestreringstræ.

## Vent senere

`start_workflows()` er designet til at fungere sammen med [Workflow Dependencies](https://queuety.inline0.dev/da/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` indsamler alle færdige underordnede tilstande
- `WaitMode::Any` genoptager ved den første vellykkede underordnede arbejdsgang

Det giver dig orkestrering med planlægger og udfører uden behov for en fuld, dynamisk redigerbar DAG-motor.

## Aliaser til agenter

`start_agents()` er et alias for `start_workflows()` med standardindstillinger tilpasset forløb med planlægger og udfører:

- `result_key` er som standard `agent_workflow_ids`
- `payload_key` er som standard `agent_task`
- `name` er som standard `start_agents`

`wait_for_agents()` er et alias for `wait_for_workflows()` med standardindstillinger tilpasset indsamling af agentresultater:

- `workflows` er som standard `agent_workflow_ids`
- `result_key` er som standard `agent_results`
- `name` er som standard `wait_for_agents`

`wait_for_agent_group()` er et alias for `wait_for_workflow_group()` med standardindstillinger tilpasset agentgrupper.

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