
# Workflowrandvoorwaarden

Workflows in agentstijl zijn flexibel, maar maken het ook makkelijker om dubbele uitvoeringen te maken of een planner meer werk te laten opleveren dan bedoeld. Queuety biedt lichte randvoorwaarden op workflowniveau, zodat je die flexibiliteit behoudt zonder de controle te verliezen.

Zie [Resourcebeheer](https://queuety.inline0.dev/nl/docs/features/resource-management) voor het bredere resourcemodel rond toelating van workers en kostmetagegevens per taak.

## Een workflowdefinitie versiebeheer geven

Gebruik `version()` om een versielabel op applicatieniveau aan een workflowdefinitie toe te voegen:

```php
Queuety::workflow( 'research_run' )
    ->version( 'research.v2' )
    ->then( PlanResearchStep::class )
    ->then( DraftResearchSummaryStep::class )
    ->dispatch();
```

De versie wordt met de workflowstatus opgeslagen, beschikbaar gemaakt via `workflow_status()`, afgedrukt door `wp queuety workflow status` en opgenomen in workflowexports.

Queuety slaat ook een deterministische `definition_hash` op voor elke workflowuitvoering. De hash wordt afgeleid van de geserialiseerde workflowdefinitie en is handig wanneer je na een implementatie precies wilt vaststellen welke workflowvorm een actieve uitvoering gebruikt.

## Verzending idempotent maken

Gebruik `idempotency_key()` wanneer aanroepers hetzelfde verzoek opnieuw kunnen proberen:

```php
Queuety::workflow( 'research_run' )
    ->idempotency_key( 'brief:42:research' )
    ->then( PlanResearchStep::class )
    ->dispatch( [ 'brief_id' => 42 ] );
```

Als een workflow opnieuw wordt verzonden met een sleutel die al is gebruikt, retourneert Queuety de oorspronkelijke workflow-ID in plaats van een dubbele uitvoering aan te maken. Sleutels zijn globaal voor alle workflownamen; neem daarom de workflownaam op in de sleutel wanneer verschillende workflows dezelfde sleutel kunnen gebruiken.

Dit is vooral handig voor:

- API-eindpunten waarop clients of gateways opnieuw een verzoek kunnen doen
- webhookverwerkers die dubbele leveringen kunnen ontvangen
- plannerstappen die per externe entiteit slechts één orkestratie-uitvoering mogen aanmaken

Idempotentiesleutels worden opgeslagen in de tabel `queuety_workflow_dispatch_keys`.

## Workflowbudgetten instellen

Gebruik workflowbudgetten om uitvoeringen te laten mislukken zodra ze de geplande grenzen overschrijden:

```php
Queuety::workflow( 'research_run' )
    ->max_transitions( 20 )
    ->max_for_each_items( 12 )
    ->max_state_bytes( 32768 )
    ->max_cost_units( 40 )
    ->max_started_workflows( 8 )
    ->then( PlanResearchStep::class )
    ->for_each( 'tasks', ExecuteResearchTask::class, 'results' )
    ->dispatch();
```

### `max_transitions()`

Beperkt hoeveel workflowstappen mogen worden voltooid voordat de uitvoering mislukt. Dit is handig om workflows te beschermen die dynamisch vertakken of via `_next_step` hetzelfde gebied opnieuw kunnen doorlopen.

### `max_for_each_items()`

Beperkt hoeveel tijdens runtime ontdekte items één `for_each()`-stap mag uitbreiden. Dit is handig voor planner-/uitvoerdersystemen waarin een agent veel meer vertakkingswerk kan ontdekken dan bedoeld.

### `max_state_bytes()`

Beperkt de gecodeerde omvang van de openbare workflowstatus. Zo voorkom je dat langlopende workflows uitgroeien tot grote blobs die traag te inspecteren, exporteren of opnieuw uit te voeren zijn.

### `max_cost_units()`

Beperkt het totale aantal kosteenheden dat door voltooide stappen wordt verbruikt. Kosteenheden komen uit de metadata van de stap of taak die Queuety ophaalt wanneer er werk in de wachtrij wordt geplaatst. Gewoon gebruikerswerk gebruikt standaard `1`, orkestratieplaatshouders zoals vertragingen en wachttijden gebruiken `0`, en handlers kunnen via `config()` of taakeigenschappen een hogere positieve waarde instellen. Alleen `cost_units` van een stapdefinitie kan een waarde van `0` instellen.

Dit is handig wanneer een workflow hetzelfde gebied opnieuw kan doorlopen of items omzet in werk dat duur is op manieren die niet alleen aan het aantal stappen te zien zijn. Een planner die telkens opnieuw een dure modelaanroep doet, kan binnen `max_transitions()` blijven en toch het beoogde kostenbudget overschrijden.

### `max_started_workflows()`

Beperkt hoeveel workflows op het hoogste niveau een uitvoering mag starten via `start_workflows()` of `start_agents()`. De limiet wordt gecontroleerd voordat de onderliggende workflows worden verzonden, zodat de bovenliggende workflow mislukt zonder gedeeltelijk een groep aan te maken die het budget al overschrijdt.

Wanneer een budget wordt overschreden, Queuety beëindigt de workflow onmiddellijk in plaats van de stap opnieuw te proberen. Eén uitzondering: wanneer `Queuety::signal()` een wachttijd beëindigt en de resulterende overgang een budget overschrijdt, wordt de uitzondering doorgegeven aan de aanroeper van `signal()`, wordt het invoegen van het signaal teruggedraaid en blijft de workflow wachten.

## Beveiligingslimieten observeren

De workflowstatus geeft het volgende weer:

- `definition_version`
- `definition_hash`
- `idempotency_key`
- `budget`

De payload van `budget` bevat de ingestelde limieten en het huidige gebruik, waaronder de huidige grootte van de openbare status in bytes.

Voorbeeld:

```php
$state = Queuety::workflow_status( $workflow_id );

$state->definition_version; // 'research.v2'
$state->definition_hash;    // '4c7a...'
$state->idempotency_key;    // 'brief:42:research'
$state->budget;             // [ 'max_transitions' => 20, ... ]
```
