
# Neuron Sesijos būsenų mašina

Šis šablonas naudingas, kai kuriama sistema labiau primena sesiją nei vienkartinį vykdymą.

Queuety būsenų mašinos valdo sesijos gyvavimo ciklą, Queuety darbo eigos atlieka foninius darbus, kuriems naudingi pakartotiniai bandymai, ciklinio vykdymo užbaigimo režimai ir rezultatų apibendrinimas, o Neuron tvarko pačius agento iškvietimus ir pokalbio atmintį.

Toks atskyrimas tinka pagalbos tarnybos kopilotams, vidiniams tyrimų asistentams, redagavimo agentams, kurie gali pristabdyti darbą žmogaus peržiūrai, ir pokalbiams, pereinantiems planavimo, laukimo bei atsakymo etapus.

## Gyvavimo ciklo struktūra

Šiame pavyzdyje viena pagalbos sesija pereina per `awaiting_user`, `planning`, `waiting_on_research` ir `responding` būsenas. Mašina aiškiai valdo šį gyvavimo ciklą, o foninė darbo eiga surenka tyrimo medžiagą ir praneša sesijai, kai darbas baigtas.

## Būsenų mašina

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

Kai naudotojas siunčia pranešimą:

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

Mašina pereina į `planning`, įtraukia veiksmą į eilę ir paleidžia tyrimo darbo eigą.

## Planavimo veiksmas: paleiskite darbo eigą

```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',
        ];
    }
}
```

Šis būsenos veiksmas pats tyrimo neatlieka. Jis paleidžia darbo eigą ir įrašo jos ID į mašinos būseną.

## Darbo eigos žingsnis: praneškite mašinai, kai tyrimas paruoštas

```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 [];
    }
}
```

Pasibaigusi darbo eiga grąžina į mašiną `research_completed` ir perduoda apibendrintą medžiagos paketą kaip įvykio duomenis.

## Atsakymo veiksmas: iškvieskite Neuron su sesijos atmintimi

```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',
        ];
    }
}
```

Sugeneravus atsakymą, mašina grįžta į `awaiting_user` ir į viešąją būseną įrašo atnaujintą atsakymą. Tada ta pati sesija gali priimti kitą `user_message` įvykį ir tęsti darbą.

## Kodėl tai paprasčiau nei viena didelė darbo eiga

Sudėtingą darbą vis dar geriausia atlikti darbo eigoje, nes tyrimo daliai reikia planavimo, specialistų vykdymo, rezultatų apibendrinimo ir sintezės. Ilgai veikiantį pagalbos pokalbį geriau valdyti būsenų mašina, nes sesija turi sekti, ar laukia naudotojo pranešimo, tyrimo rezultatų, ar gali pateikti atsakymą.

Taip vykdymo logika išlieka suprantama, o sesijos modelis – aiškus.

## Susijusi dokumentacija

- [Būsenų mašinos](https://queuety.inline0.dev/lt/docs/state-machines)
- [Agentų orkestravimas](https://queuety.inline0.dev/lt/docs/workflows/agent-orchestration)
- [Asinchroniniai perdavimai](https://queuety.inline0.dev/lt/docs/workflows/async-handoffs)
- [Darbo eigos priklausomybės](https://queuety.inline0.dev/lt/docs/workflows/dependencies)
