Pular para o conteúdo

Neuron Planejador / Executor

Este exemplo usa Queuety para orquestração e Neuron para a execução propriamente dita do agente.

O padrão é simples. Uma etapa planejadora Queuety decide quais tarefas devem ser realizadas, start_agents() transforma essas tarefas em fluxos de trabalho independentes de nível superior, cada fluxo filho executa um agente Neuron e wait_for_agents() agrega os resultados de volta ao fluxo de trabalho pai.

Por que essa divisão funciona bem

Neuron é adequado para trocar de provedores com o mínimo de alterações no código e encapsular o prompt, as ferramentas e a memória de um agente especializado. Queuety é adequado para a execução durável de cada item e para modos de conclusão, novas tentativas, retomadas e interfaces de inspeção ou revisão humana durante a execução.

Etapa 1: criar um agente Neuron com troca de provedor

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

O aspecto útil aqui é que o fluxo de trabalho pode escolher o provedor em tempo de execução, passando provider no estado do fluxo de trabalho.

Etapa 2: executar o agente Neuron em uma etapa Queuety

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 [];
    }
}

Este é o principal ponto de integração: Neuron faz a chamada ao LLM, mas Queuety continua responsável pelos limites da etapa e pelo estado persistido do fluxo de trabalho.

Etapa 3: deixar o planejador iniciar as execuções do agente

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

Se PlanResearchTasksStep retornar:

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

Queuety criará um fluxo de trabalho de nível superior para cada tarefa, aguardará até que todos sejam concluídos e então passará o estado finalizado dos fluxos filhos sob $state['agent_results'].

Por que não chamar simplesmente Neuron em um loop?

Você poderia fazer isso, mas perderia as vantagens da orquestração:

Cada execução de agente deixaria de poder ser inspecionada individualmente, uma falha parcial provavelmente reiniciaria todo o lote e não haveria um ponto de conclusão claro para as etapas posteriores.

Esse padrão mantém o código do agente simples e permite que Queuety cuide da orquestração durável.

Se o planejador fizer parte de uma sessão de agente mais duradoura, mantenha esse padrão de fluxo de trabalho na camada de execução e deixe que uma máquina de estados cuide do ciclo de vida externo.