
# Ügynökök összehangolása

A(z) Queuety jól illik az ügynökrendszerekhez, ha alkalmazkodó munkát szeretne, de meg akarja tartani a tartós állapotot, az újrapróbálkozásokat, a vizsgálhatóságot és a kifejezett várakozási szemantikát.

A legtöbb ügynökfolyamathoz nincs szüksége futás közben szerkeszthető DAG-motorra. A gyakorlatban a legtöbb rendszer modellezhető néhány tartós összehangolási művelettel. A(z) `for_each()` egy munkafolyamat-futáson belül bontja ki a munkát. A(z) `start_agents()` és `wait_for_agents()` a futás közben felfedezett feladatokat önálló, legfelső szintű munkafolyamatoknak adja át. A(z) `wait_for_decision()` és `wait_for_input()` emberi beavatkozásig szüneteltet. A(z) `wait_for_workflow()`, `wait_for_workflows()` és `wait_for_agent_group()` lehetővé teszi, hogy egy legfelső szintű futás megvárjon egy másikat vagy egy elindított kvórumot.

## Hasznos gondolkodási modell

Az ügynökök összehangolása rétegekben átlátható a legkönnyebben. A tervező meghatározza, milyen munka van. A(z) Queuety ezt a munkát tartós feladatokká vagy munkafolyamatokká alakítja. A specializált futások eredményeket hoznak létre, és műtermékeket tárolnak. Egy felügyelő szakasz összesíti ezeket az eredményeket, és eldönti, mi történjen ezután. A futás bármely pontján egy ember jóváhagyhatja, elutasíthatja vagy korrigálhatja a folytatás előtt.

A fontos különbség az, hogy az ügynök dönti el, milyen munkát végezzen, de a(z) Queuety továbbra is azt szabályozza, hogyan történik a munka mentése, újrapróbálása, folytatása és összesítése. Ha az összehangolás célja egy hosszú életű munkamenet, nem pedig egy behatárolt futás, párosítsa ezt az [Állapotgépek](https://queuety.inline0.dev/hu/docs/state-machines) megoldással.

## 1. minta: Tervező/végrehajtó önálló ügynökfutásokkal

Használja a(z) `start_agents()` megoldást, ha egy tervezőlépés futás közben fedez fel feladatokat, és mindegyikből önálló, legfelső szintű munkafolyamatnak kell lennie.

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

Ebben a mintában a(z) `PlanResearchTasksStep` a futás közben felfedezett elemeket a(z) `$state['agent_tasks']` helyre írja, a(z) `start_agents()` feladatonként egy tartós munkafolyamatot indít el, a(z) `wait_for_agent_group()` pedig parkolópályára teszi a szülőt a választott befejezési feltétel teljesüléséig. Ezután a(z) `SynthesizeBriefStep` a befejezett gyermekállapotokat a(z) `$state['agent_results']` alatt kapja meg.

Ez a legjobb kiindulópont a tervező/végrehajtó rendszerekhez, mert minden ügynökfutás önállóan megvizsgálható és újrapróbálható marad.

## 2. minta: Emberi felülvizsgálat a futás folytatása előtt

Akkor használja a(z) `wait_for_decision()` megoldást, ha a munkafolyamatnak meg kell állnia egy tényleges igen/nem döntéshez, a(z) `wait_for_input()` megoldást pedig akkor, ha a kezelő strukturált visszajelzést szeretne küldeni a futásba.

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

Ha a felülvizsgáló jóváhagyja:

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

Ha a felülvizsgáló elutasítja:

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

A(z) `wait_for_decision()` után a munkafolyamat strukturált adattartalmat kap, amely tartalmazza a végső eredményt, a futást folytató jelzést és a felülvizsgáló által mellékelt adatokat. Ez valódi emberi ellenőrzési pontot biztosít anélkül, hogy a futás várakozása alatt nyitva kellene tartani egy PHP folyamatot.

## 3. minta: Egy legfelső szintű munkafolyamat megvár egy másikat

Néha nem egyetlen óriási munkafolyamat a legtisztább modell. Az egyik munkafolyamat befejezheti a kutatást, egy másik pedig megvárhatja ezt, mielőtt elindítaná a következő szakaszt.

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

Így tartós határ jön létre a kutatási és a publikálási szakasz között. Minden futásnak saját működési életciklusa van, a második munkafolyamat mégis automatikusan folytatódik, amikor a függőség teljesül.

## A megfelelő alapvető építőelem kiválasztása

A(z) `for_each()` a megfelelő eszköz, ha a munka egy munkafolyamat-futáson belül marad, az elágazások pedig valójában csak lépésszintű párhuzamos végrehajtást jelentenek egy közös állapottárolón.

A(z) `start_agents()` jobb választás, ha minden felfedezett feladatból önálló, tartós, legfelső szintű futásnak kell lennie, és ezeket külön szeretné megvizsgálni, újrapróbálni vagy exportálni.

A(z) `wait_for_workflow()` és `wait_for_workflows()` akkor illik a feladathoz, ha az egyik legfelső szintű munkafolyamat egy másiktól függ, és tartós, aszinkron összehangolást szeretne az összehangolási rétegek között.

A(z) `wait_for_decision()` és `wait_for_input()` ott hasznos, ahol egy embernek jóvá kell hagynia, el kell utasítania vagy irányítania kell a futást, miközben a munkafolyamat szünetel, de nem foglal feldolgozói kapacitást.

## Javasolt állapotkonvenciók

Az ügynökrendszerek hibakeresése könnyebb, ha az állapotkulcsok kiszámíthatók. A gyakorlatban a(z) `agent_tasks` jól használható a tervező kimenetéhez, a(z) `agent_workflow_ids` az elindított legfelső szintű futásokhoz, a(z) `agent_results` a befejezett gyermek-munkafolyamat állapotához, a(z) `review` vagy `decision` pedig a jóváhagyási vagy elutasítási adattartalomhoz. A nagyobb kimenetek, például a vázlatok, hivatkozások vagy kutatási jegyzékek általában inkább a műterméktárolóba valók, nem a fő munkafolyamat állapottárolójába.

## Ajánlott védőkorlátok az ügynökfutásokhoz

Az ügynökmunkafolyamatoknak szinte minden más felhasználási esetnél nagyobb szükségük van védőkorlátokra, mivel természetüknél fogva dinamikusak.

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

Ezek a vezérlők a gyakorlatban fontos éles üzemi kérdésekre adnak választ: melyik definícióverzió hozott létre egy futást, előfordulhat-e, hogy ismétlődő külső kérések kétszer indítják el, létrehozhat-e a tervező túl sok elágazást, illetve korlátlanul növekedhet-e a munkafolyamat állapota. A legtöbb ügynökrendszernél ezeket a védőkorlátokat érdemes beállítani, mielőtt a feldolgozók számát vagy a sorok topológiáját hangolná.

## Lásd még

- [Példák](https://queuety.inline0.dev/hu/docs/examples)
- [Műveletindítók](https://queuety.inline0.dev/hu/docs/features/action-triggers)
- [Dinamikus ciklus minden elemre](https://queuety.inline0.dev/hu/docs/workflows/for-each)
- [Aszinkron átadások](https://queuety.inline0.dev/hu/docs/workflows/async-handoffs)
- [Munkafolyamat-függőségek](https://queuety.inline0.dev/hu/docs/workflows/dependencies)
- [Műtermékek](https://queuety.inline0.dev/hu/docs/features/artifacts)
- [Munkafolyamat-jelzések](https://queuety.inline0.dev/hu/docs/workflows/signals)
- [Munkafolyamat-védőkorlátok](https://queuety.inline0.dev/hu/docs/workflows/guardrails)
