
# Neuron Macchina a stati della sessione

Questo schema è utile quando ciò che state sviluppando si comporta più come una sessione che come un’esecuzione singola.

Le macchine a stati Queuety gestiscono il ciclo di vita della sessione, i workflow Queuety svolgono il lavoro in background che beneficia di nuovi tentativi, modalità di completamento per ogni elemento e aggregazione, mentre Neuron gestisce le chiamate effettive agli agenti e la memoria della conversazione.

Questa suddivisione è adatta agli assistenti per l’assistenza clienti, agli assistenti di ricerca interni, agli agenti editoriali che possono fermarsi in attesa di una revisione umana e alle conversazioni in chat che passano tra le fasi di pianificazione, attesa e risposta.

## Struttura del ciclo di vita

In questo esempio, una sessione di assistenza attraversa gli stati `awaiting_user`, `planning`, `waiting_on_research` e `responding`. La macchina rende esplicito questo ciclo di vita, mentre un workflow in background raccoglie le informazioni e segnala alla sessione quando ha terminato.

## La macchina a stati

```php
use Queuety\Queuety;

$session_id = Queuety::machine( 'support_session' )
    ->version( 'support-session.v1' )
    ->state( 'awaiting_user' )
    ->on( 'user_message', 'planning' )
    ->state( 'planning' )
    ->action( DispatchResearchWorkflowAction::class )
    ->on( 'research_dispatched', 'waiting_on_research' )
    ->state( 'waiting_on_research' )
    ->on( 'research_completed', 'responding' )
    ->state( 'responding' )
    ->action( RespondWithNeuronAction::class )
    ->on( 'response_ready', 'awaiting_user' )
    ->dispatch( [
        'thread_id' => 'support:customer-42',
    ] );
```

Quando un utente invia un messaggio:

```php
Queuety::machine_event(
    $session_id,
    'user_message',
    [
        'session_machine_id' => $session_id,
        'message' => 'Can you compare our pricing to the main competitors?',
    ]
);
```

La macchina passa a `planning`, mette in coda la sua azione e avvia il workflow di ricerca.

## Azione di pianificazione: avviare il workflow

```php
namespace App\StateMachines\Actions;

use Queuety\Contracts\StateAction;
use Queuety\Enums\WaitMode;
use Queuety\Queuety;

final class DispatchResearchWorkflowAction implements StateAction
{
    public function handle( array $state, ?string $event = null, array $event_payload = [], array $payload = [] ): array|string
    {
        $message = trim( (string) ( $event_payload['message'] ?? '' ) );

        $agent_workflow = Queuety::workflow( 'support_research_agent' )
            ->then( ResearchTopicStep::class );

        $research_workflow = Queuety::workflow( 'support_research_packet' )
            ->then( PlanResearchTasksStep::class )
            ->start_agents( 'agent_tasks', $agent_workflow )
            ->wait_for_agents( mode: WaitMode::All, result_key: 'agent_results' )
            ->then( SynthesizeResearchPacketStep::class )
            ->then( NotifySessionResearchReadyStep::class );

        $workflow_id = $research_workflow->dispatch( [
            'machine_id'      => $state['session_machine_id'],
            'thread_id'       => $state['thread_id'],
            'customer_prompt' => $message,
        ] );

        return [
            'latest_user_message'  => $message,
            'research_workflow_id' => $workflow_id,
            '_event'               => 'research_dispatched',
        ];
    }
}
```

Questa azione di stato non esegue direttamente la ricerca. Avvia un workflow e registra il suo ID nello stato della macchina.

## Passaggio del workflow: segnalare alla macchina quando la ricerca è pronta

```php
namespace App\Workflow\Steps;

use Queuety\Queuety;
use Queuety\Step;

final class NotifySessionResearchReadyStep implements Step
{
    public function handle( array $state ): array
    {
        Queuety::machine_event(
            $state['machine_id'],
            'research_completed',
            [
                'research_packet' => $state['research_packet'],
            ]
        );

        return [];
    }

    public function config(): array
    {
        return [];
    }
}
```

Al termine, il workflow invia `research_completed` alla macchina e include il pacchetto sintetizzato nel payload dell’evento.

## Azione di risposta: chiamare Neuron con la memoria della sessione

```php
namespace App\StateMachines\Actions;

use App\Neuron\SupportAgent;
use NeuronAI\Chat\Messages\UserMessage;
use Queuety\Contracts\StateAction;

final class RespondWithNeuronAction implements StateAction
{
    public function handle( array $state, ?string $event = null, array $event_payload = [], array $payload = [] ): array|string
    {
        // Queuety creates actions with `new RespondWithNeuronAction()`, so build dependencies here.
        $pdo = new \PDO( $_ENV['NEURON_DB_DSN'], $_ENV['NEURON_DB_USER'], $_ENV['NEURON_DB_PASSWORD'] );

        $agent = new SupportAgent(
            threadId: $state['thread_id'],
            pdo: $pdo,
        );

        $message = $agent->chat(
            new UserMessage(
                sprintf(
                    "Answer the user message '%s' using this research packet:\n\n%s",
                    $state['latest_user_message'],
                    json_encode( $state['research_packet'] ?? [], JSON_PRETTY_PRINT )
                )
            )
        )->getMessage();

        return [
            'assistant_reply' => $message->getContent(),
            '_event'          => 'response_ready',
        ];
    }
}
```

Dopo la generazione della risposta, la macchina torna a `awaiting_user` con la risposta aggiornata nello stato pubblico. La stessa sessione può quindi accettare un altro evento `user_message` e proseguire.

## Perché è più semplice di un unico workflow di grandi dimensioni

Il lavoro più impegnativo continua a essere strutturato come workflow, perché la ricerca richiede pianificazione, esecuzioni specialistiche, aggregazione e sintesi. La conversazione di assistenza di lunga durata è strutturata come macchina a stati, perché la sessione deve tenere traccia del fatto che sia in attesa dell’intervento dell’utente, della ricerca o dell’autorizzazione a inviare una risposta.

Questa suddivisione mantiene il runtime leggibile e il modello della sessione esplicito.

## Documentazione correlata

- [Macchine a stati](https://queuety.inline0.dev/it/docs/state-machines)
- [Orchestrazione degli agenti](https://queuety.inline0.dev/it/docs/workflows/agent-orchestration)
- [Passaggi asincroni](https://queuety.inline0.dev/it/docs/workflows/async-handoffs)
- [Dipendenze dei workflow](https://queuety.inline0.dev/it/docs/workflows/dependencies)
