Neuron 플래너 / 실행기
이 예제에서는 오케스트레이션에 Queuety을, 실제 에이전트 실행에 Neuron을 사용합니다.
패턴은 간단합니다. Queuety 플래너 단계가 수행할 작업을 정하고, start_agents()이 해당 작업을 독립적인 최상위 워크플로로 만들며, 각 하위 워크플로는 Neuron 에이전트를 실행하고, wait_for_agents()이 결과를 상위 워크플로로 모읍니다.
이 분리가 효과적인 이유
Neuron은 최소한의 코드 변경으로 제공자를 전환하고 전문 에이전트의 프롬프트, 도구 및 메모리를 캡슐화하는 데 적합합니다. Queuety은 지속 가능한 for-each 및 완료 모드, 재시도, 재개 기능과 실행 주변의 검사 및 사람 검토 인터페이스를 제공하는 데 적합합니다.
1단계: 제공자를 바꿀 수 있는 Neuron 에이전트 만들기
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 에이전트 실행하기
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단계: 플래너가 에이전트 실행을 시작하게 하기
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이 다음을 반환하면:
[
'agent_tasks' => [
['topic' => 'pricing'],
['topic' => 'customer reviews'],
['topic' => 'recent launches'],
],
]
Queuety은 작업마다 최상위 워크플로 하나를 만들고, 모든 워크플로가 완료될 때까지 기다린 다음 완료된 하위 워크플로 상태를 $state['agent_results'] 아래에 전달합니다.
반복문에서 Neuron을 호출하면 안 되나요?
그렇게 할 수 있지만 오케스트레이션의 이점을 잃게 됩니다.
각 에이전트 실행을 개별적으로 검사할 수 없고, 일부가 충돌하면 전체 배치가 다시 시작될 가능성이 높으며, 후속 단계가 명확히 완료되는 시점도 없어집니다.
이 패턴은 에이전트 코드를 단순하게 유지하면서 Queuety이 지속적인 오케스트레이션을 담당하게 합니다.
플래너가 장기 실행 에이전트 세션의 일부라면 이 워크플로 패턴을 실행 계층에 사용하고, 상태 머신이 전체 수명 주기를 담당하게 하세요.