Vai al contenuto

Orchestrazione degli agenti

Queuety è adatto ai sistemi di agenti quando volete gestire attività adattive senza rinunciare a stato persistente, nuovi tentativi, ispezione e semantica di attesa esplicita.

Per la maggior parte dei flussi degli agenti non serve un motore DAG modificabile durante l'esecuzione. In pratica, molti sistemi si possono modellare con un insieme ridotto di operazioni di orchestrazione persistenti. for_each() espande il lavoro all'interno di un'esecuzione del workflow. start_agents() e wait_for_agents() affidano il lavoro individuato durante l'esecuzione a workflow indipendenti di primo livello. wait_for_decision() e wait_for_input() mettono in pausa l'esecuzione per consentire l'intervento umano. wait_for_workflow(), wait_for_workflows() e wait_for_agent_group() permettono a un'esecuzione di primo livello di attendere un'altra esecuzione o il raggiungimento di un quorum avviato.

Un modello mentale utile

L'orchestrazione degli agenti è più facile da comprendere se suddivisa in livelli. Un planner decide quale lavoro svolgere. Queuety trasforma quel lavoro in job o workflow persistenti. Le esecuzioni specializzate producono risultati e salvano artefatti. Una fase di supervisione aggrega i risultati e decide cosa succede dopo. In qualsiasi momento, una persona può approvare, rifiutare o correggere l'esecuzione prima che prosegua.

La distinzione fondamentale è che l'agente decide quale lavoro svolgere, ma Queuety continua a decidere come quel lavoro viene salvato, ripetuto, ripreso e aggregato. Se l'obiettivo dell'orchestrazione è una sessione di lunga durata anziché un'esecuzione circoscritta, abbinatela a Macchine a stati.

Schema 1: pianificazione ed esecuzione con esecuzioni di agenti indipendenti

Usate start_agents() quando un passaggio di pianificazione individua attività durante l'esecuzione e ciascuna deve diventare un workflow di primo livello.

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

In questo schema, PlanResearchTasksStep scrive gli elementi individuati durante l'esecuzione in $state['agent_tasks'], start_agents() avvia un workflow persistente per ogni attività e wait_for_agent_group() mette in pausa il processo padre finché non viene soddisfatta la condizione di completamento scelta. SynthesizeBriefStep riceve quindi gli stati completati dei processi figli in $state['agent_results'].

È il punto di partenza più semplice per i sistemi di pianificazione ed esecuzione, perché ogni esecuzione di un agente resta ispezionabile e può essere ripetuta in modo indipendente.

Schema 2: revisione umana prima che l'esecuzione prosegua

Usate wait_for_decision() quando il workflow deve fermarsi per una decisione effettiva di sì o no e wait_for_input() quando l'operatore deve inviare un feedback strutturato all'esecuzione.

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

Se il revisore approva:

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

Se il revisore rifiuta:

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

Dopo wait_for_decision(), il workflow riceve un payload strutturato con l'esito finale, il segnale che ha ripreso l'esecuzione e tutti i dati del revisore inclusi. In questo modo ottenete un vero punto di controllo con intervento umano, senza lasciare aperto un processo PHP mentre l'esecuzione è in attesa.

Schema 3: un workflow di primo livello attende un altro workflow

A volte il modello più semplice non consiste in un unico workflow enorme. Un workflow può completare la ricerca e un altro può attenderlo prima di avviare la fase successiva.

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

In questo modo si ottiene un confine persistente tra la fase di ricerca e quella di pubblicazione. Ogni esecuzione ha un proprio ciclo di vita operativo, ma il secondo workflow riprende comunque automaticamente al completamento della dipendenza.

Scegliere la primitiva giusta

for_each() è lo strumento giusto quando il lavoro deve rimanere all'interno di una singola esecuzione del workflow e le diramazioni sono semplicemente esecuzioni parallele a livello di passaggio che condividono lo stesso contenitore di stato.

start_agents() è preferibile quando ogni attività individuata deve diventare un'esecuzione persistente di primo livello e volete ispezionare, ripetere o esportare le esecuzioni separatamente.

wait_for_workflow() e wait_for_workflows() sono adatti quando un workflow di primo livello dipende da un altro workflow di primo livello e volete un coordinamento asincrono persistente tra i due livelli di orchestrazione.

wait_for_decision() e wait_for_input() sono adatti nei punti in cui una persona deve approvare, rifiutare o indirizzare l'esecuzione, mentre il workflow resta in pausa senza consumare capacità dei worker.

Convenzioni di stato consigliate

I sistemi di agenti sono più facili da correggere quando le chiavi di stato sono prevedibili. In pratica, agent_tasks è adatto all'output del planner, agent_workflow_ids alle esecuzioni di primo livello avviate, agent_results allo stato completato dei workflow figli e review o decision ai payload di approvazione o rifiuto. Gli output più grandi, come bozze, citazioni o manifesti di ricerca, di solito vanno nel sistema di archiviazione degli artefatti anziché nel contenitore dello stato principale del workflow.

I workflow degli agenti traggono vantaggio dalle misure di protezione più di quasi ogni altro caso d'uso, perché sono dinamici per natura.

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

Questi controlli rispondono alle domande pratiche che contano in produzione: quale versione della definizione ha prodotto un'esecuzione, se richieste esterne duplicate possono avviarla due volte, se un planner può creare troppe diramazioni e se lo stato del workflow può crescere senza limiti. Per la maggior parte dei sistemi di agenti, iniziate da queste misure prima di regolare il numero di worker o la topologia delle code.

Vedi anche