
# Neuron 플래너 / 실행기

이 예제에서는 오케스트레이션에 Queuety을, 실제 에이전트 실행에 Neuron을 사용합니다.

패턴은 간단합니다. Queuety 플래너 단계가 수행할 작업을 정하고, `start_agents()`이 해당 작업을 독립적인 최상위 워크플로로 만들며, 각 하위 워크플로는 Neuron 에이전트를 실행하고, `wait_for_agents()`이 결과를 상위 워크플로로 모읍니다.

## 이 분리가 효과적인 이유

Neuron은 최소한의 코드 변경으로 제공자를 전환하고 전문 에이전트의 프롬프트, 도구 및 메모리를 캡슐화하는 데 적합합니다. Queuety은 지속 가능한 for-each 및 완료 모드, 재시도, 재개 기능과 실행 주변의 검사 및 사람 검토 인터페이스를 제공하는 데 적합합니다.

## 1단계: 제공자를 바꿀 수 있는 Neuron 에이전트 만들기

```php
namespace App\Neuron;

use NeuronAI\Agent\Agent;
use NeuronAI\Providers\AIProviderInterface;
use NeuronAI\Providers\Anthropic\Anthropic;
use NeuronAI\Providers\Gemini\Gemini;
use NeuronAI\Providers\OpenAI\Responses\OpenAIResponses;
use NeuronAI\SystemPrompt;

final class ResearchAgent extends Agent
{
    public function __construct(
        private readonly string $providerName = 'openai',
    ) {}

    protected function provider(): AIProviderInterface
    {
        return match ($this->providerName) {
            'anthropic' => new Anthropic(
                key: $_ENV['ANTHROPIC_API_KEY'],
                model: $_ENV['ANTHROPIC_MODEL'],
            ),
            'gemini' => new Gemini(
                key: $_ENV['GEMINI_API_KEY'],
                model: $_ENV['GEMINI_MODEL'],
            ),
            default => new OpenAIResponses(
                key: $_ENV['OPENAI_API_KEY'],
                model: $_ENV['OPENAI_MODEL'],
            ),
        };
    }

    public function instructions(): string
    {
        return (string) new SystemPrompt(
            background: [
                'You are a research agent.',
                'Return concise, source-aware summaries for the assigned topic.',
            ],
        );
    }
}
```

여기서 유용한 점은 워크플로 상태에서 `provider`을 전달해 런타임에 제공자를 선택할 수 있다는 것입니다.

## 2단계: Queuety 단계에서 Neuron 에이전트 실행하기

```php
namespace App\Workflow\Steps;

use App\Neuron\ResearchAgent;
use NeuronAI\Chat\Messages\UserMessage;
use Queuety\Step;

final class ResearchTopicStep implements Step
{
    public function handle(array $state): array
    {
        $agent = new ResearchAgent(
            providerName: $state['provider'] ?? 'openai',
        );

        $message = $agent->chat(
            new UserMessage(sprintf(
                "Research the topic '%s' for brief %d. Return a compact bullet summary.",
                $state['topic'],
                $state['brief_id'],
            ))
        )->getMessage();

        return [
            'summary' => $message->getContent(),
        ];
    }

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

이것이 핵심 통합 지점입니다. Neuron은 LLM 호출을 처리하지만, 단계 경계와 영구 저장되는 워크플로 상태는 여전히 Queuety이 담당합니다.

## 3단계: 플래너가 에이전트 실행을 시작하게 하기

```php
use Queuety\Enums\WaitMode;
use Queuety\Queuety;

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

Queuety::workflow('brief_research')
    ->version('brief-research.v1')
    ->then(PlanResearchTasksStep::class) // writes $state['agent_tasks']
    ->start_agents('agent_tasks', $agent_workflow)
    ->wait_for_agents(mode: WaitMode::All, result_key: 'agent_results')
    ->then(SynthesizeBriefStep::class)
    ->dispatch([
        'brief_id' => 42,
        'provider' => 'anthropic',
    ]);
```

`PlanResearchTasksStep`이 다음을 반환하면:

```php
[
    'agent_tasks' => [
        ['topic' => 'pricing'],
        ['topic' => 'customer reviews'],
        ['topic' => 'recent launches'],
    ],
]
```

Queuety은 작업마다 최상위 워크플로 하나를 만들고, 모든 워크플로가 완료될 때까지 기다린 다음 완료된 하위 워크플로 상태를 `$state['agent_results']` 아래에 전달합니다.

## 반복문에서 Neuron을 호출하면 안 되나요?

그렇게 할 수 있지만 오케스트레이션의 이점을 잃게 됩니다.

각 에이전트 실행을 개별적으로 검사할 수 없고, 일부가 충돌하면 전체 배치가 다시 시작될 가능성이 높으며, 후속 단계가 명확히 완료되는 시점도 없어집니다.

이 패턴은 에이전트 코드를 단순하게 유지하면서 Queuety이 지속적인 오케스트레이션을 담당하게 합니다.

플래너가 장기 실행 에이전트 세션의 일부라면 이 워크플로 패턴을 실행 계층에 사용하고, [상태 머신](https://queuety.inline0.dev/ko/docs/state-machines)이 전체 수명 주기를 담당하게 하세요.

## 관련 문서

- [비동기 핸드오프](https://queuety.inline0.dev/ko/docs/workflows/async-handoffs)
- [에이전트 오케스트레이션](https://queuety.inline0.dev/ko/docs/workflows/agent-orchestration)
- [상태 머신](https://queuety.inline0.dev/ko/docs/state-machines)
