
# Neuron Pomnilnik + stroj stanj za pregled

Ta vzorec je uporaben, kadar mora agent ohraniti kontekst pogovora skozi več krogov človeškega pregleda, celotno upravljanje življenjskega cikla pa naj še vedno prevzema Queuety.

Queuety upravlja stroj stanj za pregled, Neuron pa pomnilnik agenta za nit priprave osnutka.

## Zakaj je pomnilnik Neuron tu uporaben

Če recenzent zavrne osnutek in zahteva popravke, agentu pri naslednjem klicu ne bi smelo biti treba znova sestaviti celotnega konteksta od začetka.

Neuron's `SQLChatHistory` je za to primeren, saj lahko agent nadaljuje delo v isti niti pogovora, medtem ko Queuety usmerja odločitve recenzenta in kroge popravkov.

## Agent Neuron z zgodovino, ki jo zagotavlja 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.',
            ],
        );
    }
}
```

## Pripravite osnutek, nato ga popravite v isti niti pomnilnika

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

## Stroj stanj 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' ]
);
```

Prvi prehod vstopi v `drafting`, izvede čakajoče dejanje in preide v `awaiting_review`.

Če recenzent osnutek zavrne, se stroj vrne v `drafting`. Ker se podatki dogodka `reject` posredujejo v `DraftBriefAction`, je mogoče pri naslednjem osnutku uporabiti opombe recenzenta, ne da bi izgubili prvotno zgodovino niti Neuron.

## Zakaj je to bolje kot ponavljanje poteka dela

Ta težava zadeva življenjski cikel. Osnutek čaka na človeški pregled, recenzent ga lahko odobri ali zavrne, zavrnitev vrne sejo v pripravo osnutka, odobritev pa sejo konča. To se bolje ujema s strojem stanj kot z linearnim potekom dela s povratno povezavo.

Stanje poteka dela je še vedno odlično za dejstva, povezana z orkestracijo, kot so število krogov pregleda, ID-ji artefaktov, ID-ji potekov dela in odločitve o usmerjanju. Pomnilnik Neuron je primernejši za kontekst pogovora, na primer prejšnje pozive, ponavljajoče se popravke in odgovore modela, ki naj ostanejo del niti za pripravo osnutka.

Če uporabite oba, vsakemu sistemu dodelite nalogo, za katero je najprimernejši.

## Kdaj raje uporabiti potek dela

Potek dela izberite, kadar je pot pregleda strogo omejena in usmerjena v izvajanje, na primer:

Ustvarite en osnutek, počakajte na eno odobritev in ga objavite.

Stroj stanj izberite, kadar se lahko seja večkrat vrne v ista stanja, njen življenjski cikel pa usmerjajo zunanji dogodki.

## Povezana dokumentacija

- [Stroji stanj](https://queuety.inline0.dev/sl/docs/state-machines)
- [Signali poteka dela](https://queuety.inline0.dev/sl/docs/workflows/signals)
- [Orkestracija agentov](https://queuety.inline0.dev/sl/docs/workflows/agent-orchestration)
