
# Neuron Minnes- och gransknings-tillståndsmaskin

Det här mönstret är användbart när en agent ska behålla samtalskontext genom upprepade granskningsrundor med människor, samtidigt som den övergripande livscykeln fortfarande orkestreras av Queuety.

Queuety hanterar tillståndsmaskinen för granskning, medan Neuron hanterar agentens minne för skrivtråden.

## Därför hjälper Neuron-minne här

Om en granskare underkänner ett utkast och ber om ändringar ska nästa agentanrop inte behöva återskapa hela kontexten från grunden.

Neurons `SQLChatHistory` passar bra för detta eftersom agenten kan fortsätta arbeta i samma konversationstråd medan Queuety hanterar granskarens beslut och ändringsrundor.

## Neuron-agenten med historik som hanteras av 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.',
            ],
        );
    }
}
```

## Skriv ett utkast och revidera med samma minnestråd

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

## Queuety-tillståndsmaskinen

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

Första genomgången går in i `drafting`, kör den köade åtgärden och övergår sedan till `awaiting_review`.

Om granskaren underkänner utkastet går maskinen tillbaka till `drafting`. Eftersom händelsenyttolasten `reject` skickas till `DraftBriefAction` kan nästa utkast använda granskarens anteckningar utan att förlora den ursprungliga Neuron-trådens historik.

## Därför är detta renare än att upprepa ett arbetsflöde

Problemet handlar om livscykeln. Ett utkast väntar på mänsklig granskning, en granskare kan godkänna eller underkänna det, ett underkännande skickar sessionen tillbaka till skrivfasen och ett godkännande avslutar sessionen. Det motsvarar en tillståndsmaskin bättre än ett linjärt arbetsflöde med en bakåtriktad koppling.

Arbetsflödestillstånd passar fortfarande utmärkt för orkestreringsuppgifter som antal granskningsrundor, artefakt-ID:n, arbetsflödes-ID:n och routningsbeslut. Neuron-minne passar bättre för samtalskontext som tidigare instruktioner, iterativa revideringar och modellsvar som ska ingå i skrivtråden.

Genom att använda båda får varje system den uppgift det passar bäst för.

## När du i stället bör behålla detta som ett arbetsflöde

Välj ett arbetsflöde när granskningsvägen är tydligt avgränsad och inriktad på körning, till exempel:

Skapa ett utkast, vänta på ett godkännande och publicera.

Välj en tillståndsmaskin när sessionen kan återvända till samma tillstånd flera gånger och externa händelser styr livscykeln.

## Relaterad dokumentation

- [Tillståndsmaskiner](https://queuety.inline0.dev/sv/docs/state-machines)
- [Arbetsflödessignaler](https://queuety.inline0.dev/sv/docs/workflows/signals)
- [Agentorkestrering](https://queuety.inline0.dev/sv/docs/workflows/agent-orchestration)
