Neuron Pianificatore / esecutore
Questo esempio usa Queuety per l'orchestrazione e Neuron per l'esecuzione effettiva dell'agente.
Lo schema è semplice. Un passaggio di pianificazione Queuety decide quali attività svolgere, start_agents() le trasforma in workflow di livello superiore indipendenti, ogni workflow secondario esegue un agente Neuron e wait_for_agents() raccoglie i risultati nel workflow principale.
Perché questa suddivisione funziona bene
Neuron consente di cambiare provider con modifiche minime al codice e di racchiudere prompt, strumenti e memoria di un agente specializzato. Queuety gestisce efficacemente l'esecuzione duratura di cicli for-each e le modalità di completamento, i tentativi, la ripresa e le interfacce per esaminare l'esecuzione o sottoporla alla revisione umana.
Passaggio 1: crea un agente Neuron compatibile con più provider
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.',
],
);
}
}
L'aspetto utile è che il workflow può scegliere il provider durante l'esecuzione passando provider nello stato del workflow.
Passaggio 2: esegui l'agente Neuron all'interno di un passaggio Queuety
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 [];
}
}
Questo è il punto chiave dell’integrazione: Neuron gestisce la chiamata LLM, ma Queuety mantiene il controllo sui confini dei passaggi e sullo stato persistente del workflow.
Passaggio 3: permettere al planner di avviare le esecuzioni degli agenti
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 restituisce:
[
'agent_tasks' => [
['topic' => 'pricing'],
['topic' => 'customer reviews'],
['topic' => 'recent launches'],
],
]
Queuety creerà un workflow di primo livello per ogni attività, attenderà il completamento di tutti e poi passerà lo stato finale dei workflow figli sotto $state['agent_results'].
Perché non chiamare semplicemente Neuron in un ciclo?
Si potrebbe fare, ma si perderebbero i vantaggi dell’orchestrazione:
Ogni esecuzione dell’agente non sarebbe più ispezionabile singolarmente, un arresto anomalo parziale probabilmente riavvierebbe l’intero batch e non ci sarebbe un punto di completamento chiaro per le fasi successive.
Questo schema mantiene semplice il codice dell’agente e lascia a Queuety il compito di gestire l’orchestrazione persistente.
Se il planner appartiene a una sessione dell'agente di durata maggiore, mantenete questo schema di flusso di lavoro per il livello di esecuzione e lasciate che una macchina a stati gestisca il ciclo di vita esterno.