
# Neuron Paměť + stavový automat kontroly

Tento vzor se hodí, když má agent zachovávat konverzační kontext napříč opakovanými koly lidské kontroly, ale celkovou orchestraci životního cyklu má stále zajišťovat Queuety.

Queuety řídí stavový automat kontroly, zatímco Neuron spravuje paměť agenta pro konverzaci, ve které vzniká návrh.

## Proč se zde hodí paměť Neuron

Pokud kontrolující návrh zamítne a požádá o úpravy, agent by při dalším volání neměl rekonstruovat celý kontext od začátku.

Neuron`SQLChatHistory` se k tomu dobře hodí, protože agent může pokračovat ve stejné konverzační relaci, zatímco Queuety zpracovává rozhodnutí kontrolujícího a kola úprav.

## Agent Neuron s historií uloženou v SQL

```php
namespace App\Neuron;

use NeuronAI\Agent\Agent;
use NeuronAI\Chat\History\ChatHistoryInterface;
use NeuronAI\Chat\History\SQLChatHistory;
use NeuronAI\Providers\AIProviderInterface;
use NeuronAI\Providers\Anthropic\Anthropic;
use NeuronAI\SystemPrompt;

final class EditorAgent extends Agent
{
    public function __construct(
        private readonly string $threadId,
        private readonly \PDO $pdo,
    ) {}

    protected function provider(): AIProviderInterface
    {
        return new Anthropic(
            key: $_ENV['ANTHROPIC_API_KEY'],
            model: $_ENV['ANTHROPIC_MODEL'],
        );
    }

    protected function chatHistory(): ChatHistoryInterface
    {
        return new SQLChatHistory(
            thread_id: $this->threadId,
            pdo: $this->pdo,
            table: 'neuron_chat_history',
            contextWindow: 50000,
        );
    }

    public function instructions(): string
    {
        return (string) new SystemPrompt(
            background: [
                'You are an editorial agent for long-form product briefs.',
                'Apply reviewer notes without losing the original intent.',
            ],
        );
    }
}
```

## Nejprve vytvořte návrh, pak jej upravujte se stejnou pamětí konverzace

```php
namespace App\StateMachines\Actions;

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

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

        $threadId = $state['neuron_thread_id'] ?? sprintf(
            'brief:%d:editor',
            $state['brief_id'],
        );

        $prompt = "Write the first draft for brief {$state['brief_id']}.";

        if ('reject' === $event) {
            $prompt = sprintf(
                'Revise the draft using these review notes: %s',
                $event_payload['reason'] ?? 'Tighten the draft and address reviewer concerns.',
            );
        }

        $agent = new EditorAgent($threadId, $pdo);
        $message = $agent->chat(
            new UserMessage($prompt)
        )->getMessage();

        return [
            'neuron_thread_id' => $threadId,
            'draft_markdown' => $message->getContent(),
            'review_round' => (int) ($state['review_round'] ?? 0) + 1,
            '_event' => 'draft_ready',
        ];
    }
}
```

## Stavový automat Queuety

```php
use Queuety\Enums\StateMachineStatus;
use Queuety\Queuety;

$machine_id = Queuety::machine('brief_review_session')
    ->version('brief-review-session.v1')
    ->state('drafting')
    ->action(DraftBriefAction::class)
    ->on('draft_ready', 'awaiting_review')
    ->state('awaiting_review')
    ->on('approve', 'completed')
    ->on('reject', 'drafting')
    ->state('completed', StateMachineStatus::Completed)
    ->dispatch([
        'brief_id' => 42,
    ]);

// Later, once the draft action has finished and the machine waits in `awaiting_review`:
Queuety::machine_event(
    $machine_id,
    'reject',
    [ 'reason' => 'Tighten the introduction and add pricing context.' ]
);

Queuety::machine_event(
    $machine_id,
    'approve',
    [ 'reviewer' => 'editor@example.com' ]
);
```

První průchod přejde do stavu `drafting`, provede zařazenou akci a přejde do stavu `awaiting_review`.

Pokud kontrolující návrh zamítne, automat se vrátí do stavu `drafting`. Protože se payload události `reject` předává do `DraftBriefAction`, může další návrh využít poznámky kontrolujícího, aniž by ztratil původní historii konverzace Neuron.

## Proč je to přehlednější než opakování pracovního postupu

Tento problém se týká životního cyklu. Návrh čeká na lidskou kontrolu, kontrolující jej může schválit nebo zamítnout, po zamítnutí se relace vrátí k přípravě návrhu a po schválení skončí. Tomu odpovídá stavový automat lépe než lineární pracovní postup se zpětnou vazbou.

Stav pracovního postupu se stále skvěle hodí pro fakta související s orchestrací, jako je počet kol kontroly, ID artefaktů a pracovních postupů nebo rozhodnutí o směrování. Paměť Neuron lépe uchovává konverzační kontext, například předchozí výzvy, průběžné úpravy a odpovědi modelu, které mají zůstat součástí konverzace, v níž vzniká návrh.

Když použijete oba systémy, každý může plnit úlohu, pro kterou se nejlépe hodí.

## Kdy raději použít pracovní postup

Zvolte workflow, pokud je cesta kontroly jasně ohraničená a zaměřená na provedení, například:

Vytvořte jeden návrh, počkejte na jedno schválení a publikujte ho.

Zvolte stavový automat, pokud se relace může několikrát vracet do stejných stavů a její životní cyklus řídí vnější události.

## Související dokumentace

- [Stavové automaty](https://queuety.inline0.dev/cs/docs/state-machines)
- [Signály workflow](https://queuety.inline0.dev/cs/docs/workflows/signals)
- [Orchestrace agentů](https://queuety.inline0.dev/cs/docs/workflows/agent-orchestration)
