PHP code example of errogaht / neuron-ai-bundle

1. Go to this page and download the library: Download errogaht/neuron-ai-bundle library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

errogaht / neuron-ai-bundle example snippets




return [
    // ...
    Errogaht\NeuronAiBundle\NeuronAiBundle::class => ['all' => true],
];



namespace App\Service;

use NeuronAI\Agent\AgentInterface;
use NeuronAI\Chat\Messages\UserMessage;

final class AnswerQuestion
{
    public function __construct(private AgentInterface $agent)
    {
    }

    public function __invoke(string $question): ?string
    {
        return $this->agent->chat(new UserMessage($question))->getMessage()->getContent();
    }
}

use Errogaht\NeuronAiBundle\Agent\AgentRunner;

$result = $runner->chat('assistant', 'Summarize this order.', threadId: 'order-42');
$text = $result->content();

use NeuronAI\Chat\Messages\Stream\Chunks\TextChunk;

$stream = $runner->stream('assistant', 'Summarize this order.', threadId: 'order-42');
foreach ($stream as $chunk) {
    // Expose only chunk types appropriate for the client boundary. Tool and
    // reasoning chunks may contain implementation details or sensitive data.
    if ($chunk instanceof TextChunk) {
        echo $chunk->content;
    }
}

$result = $stream->getReturn();

use NeuronAI\Agent\AgentInterface;
use NeuronAI\Providers\AIProviderInterface;

final class ControllerService
{
    public function __construct(
        private AgentInterface $supportAgent,
        private AgentInterface $orderManagerAgent,
        private AIProviderInterface $mainProvider,
    ) {
    }
}



namespace App\Ai\Tool;

use App\Repository\OrderRepository;
use NeuronAI\Tools\Tool;

final class FindOrderTool extends Tool
{
    public function __construct(private readonly OrderRepository $orders)
    {
        parent::__construct('find_order', 'Find an order visible to the current user.');
    }

    public function __invoke(string $number): array
    {
        // Authorization belongs in the application service/repository boundary.
        return $this->orders->findVisibleSummary($number);
    }
}



namespace App\Ai\Tool;

use App\Repository\OrderRepository;
use Errogaht\NeuronAiBundle\Tool\AbstractToolGroup;
use Errogaht\NeuronAiBundle\Tool\Attribute\Tool;
use Errogaht\NeuronAiBundle\Tool\Attribute\ToolParameter;

final class OrderTools extends AbstractToolGroup
{
    public function __construct(private readonly OrderRepository $orders)
    {
    }

    #[Tool(description: 'Find an order visible to the current user.')]
    public function findOrder(
        #[ToolParameter(description: 'Public order number')] string $number,
        #[ToolParameter(enum: ['short', 'full'])] string $format = 'short',
    ): array {
        return $this->orders->findVisibleSummary($number, $format);
    }

    #[Tool(name: 'change_delivery_address', description: 'Change delivery before dispatch.', maxRuns: 1)]
    public function changeDeliveryAddress(string $number, string $address): array
    {
        return $this->orders->changeVisibleOrderAddress($number, $address);
    }

    public function guidelines(): ?string
    {
        return 'Always find the order before attempting a change.';
    }
}



namespace App\Ai\Agent;

use App\Ai\Tool\FindOrderTool;
use App\Ai\Tool\OrderTools;
use Errogaht\NeuronAiBundle\Agent\Attribute\AsNeuronAgent;
use NeuronAI\Agent\Agent;
use NeuronAI\Providers\AIProviderInterface;
use NeuronAI\Tools\ToolInterface;
use NeuronAI\Tools\Toolkits\ToolkitInterface;

#[AsNeuronAgent('order_manager')]
final class OrderManagerAgent extends Agent
{
    public function __construct(
        AIProviderInterface $mainProvider,
        private readonly FindOrderTool $findOrder,
        private readonly OrderTools $orders,
    ) {
        // Required whenever a subclass declares its own constructor: Neuron initializes workflow state here.
        parent::__construct();
        $this->setAiProvider($mainProvider);
    }

    protected function instructions(): string
    {
        return <<<'PROMPT'
            You manage orders for the authenticated customer.
            Read the order before proposing a change and never bypass tool authorization.
            PROMPT;
    }

    /** @return list<ToolInterface|ToolkitInterface> */
    protected function tools(): array
    {
        return [$this->findOrder, $this->orders];
    }
}

final class OrderAssistant
{
    public function __construct(private OrderManagerAgent $agent)
    {
    }
}

$result = $runner->chat('order_manager', 'Move my order to tomorrow.');



namespace App\Ai\Rag;

use App\Entity\Article;
use App\Repository\ArticleRepository;
use NeuronAI\RAG\DataLoader\DataLoaderInterface;
use NeuronAI\RAG\Document;

final class DocumentationLoader implements DataLoaderInterface
{
    public function __construct(private ArticleRepository $articles)
    {
    }

    public function getDocuments(): array
    {
        return array_map(static function (Article $article): Document {
            $document = new Document($article->getSearchableText());
            $document->sourceType = 'article';
            $document->sourceName = (string) $article->getId();
            $document->metadata = ['tenant' => $article->getTenantId()];

            return $document;
        }, $this->articles->findPublished());
    }
}

public function __construct(
    EmbeddingsProviderInterface $knowledgeEmbeddings,
    VectorStoreInterface $knowledgeVectorStore,
) {
}

#[AsNeuronAgent('knowledge')]
final class KnowledgeAgent extends RAG
{
    public function __construct(
        AIProviderInterface $mainProvider,
        EmbeddingsProviderInterface $knowledgeEmbeddings,
        VectorStoreInterface $knowledgeVectorStore,
    ) {
        parent::__construct();
        $this->setAiProvider($mainProvider);
        $this->setEmbeddingsProvider($knowledgeEmbeddings);
        $this->setVectorStore($knowledgeVectorStore);
    }

    protected function instructions(): string
    {
        return 'Answer only from retrieved tenant-visible documents.';
    }
}

use NeuronAI\Workflow\WorkflowInterface;

final class OrderController
{
    public function __construct(private WorkflowInterface $orderProcessingWorkflow)
    {
    }
}



namespace App\Ai\Workflow;

use Errogaht\NeuronAiBundle\Workflow\Attribute\AsNeuronWorkflow;
use NeuronAI\Workflow\Workflow;

#[AsNeuronWorkflow('order_processing', persistence: 'workflow_files')]
final class OrderProcessingWorkflow extends Workflow
{
    public function __construct(
        private readonly Node\ReceiveOrder $receive,
        private readonly Node\ApproveOrder $approve,
        private readonly Node\CompleteOrder $complete,
    ) {
        parent::__construct();
    }

    protected function nodes(): array
    {
        return [$this->receive, $this->approve, $this->complete];
    }
}

use Errogaht\NeuronAiBundle\Workflow\WorkflowRunner;
use NeuronAI\Workflow\WorkflowState;

$result = $runner->run(
    'order_processing',
    new WorkflowState(['order_id' => 'order-42']),
);

if ($result->isInterrupted()) {
    // Store workflow + workflowId against an authenticated application record.
    $request = $result->interrupt;
}

$stream = $runner->stream('order_processing', new WorkflowState(['order_id' => 'order-42']));
foreach ($stream as $event) {
    // Forward to Mercure, SSE, WebSocket, or a StreamedResponse.
}
$result = $stream->getReturn();

$request = ApprovalRequest::fromArray($validatedPayload);
$result = $runner->resume('order_processing', $workflowId, $request);

// Streaming
foreach ($analystAgent->stream(new UserMessage($prompt)) as $chunk) {
    // send $chunk to a Symfony StreamedResponse, Mercure, etc.
}

// Structured output
$dto = $analystAgent->structured(new UserMessage($prompt), InvoiceDraft::class);



namespace App\Ai;

use Errogaht\NeuronAiBundle\Agent\AgentConfiguratorInterface;
use Errogaht\NeuronAiBundle\Agent\AgentContext;
use NeuronAI\Agent\AgentInterface;

final class TenantAgentConfigurator implements AgentConfiguratorInterface
{
    public function configure(AgentInterface $agent, AgentContext $context): void
    {
        // Resolve and attach tenant-scoped history/tools here. Never trust model output as authorization.
    }
}

use Errogaht\NeuronAiBundle\Async\AsyncAgentDispatcher;

$jobId = $dispatcher->dispatch('assistant', 'Prepare the report', threadId: 'report-42');

// AsyncWorkflowDispatcher uses the same bus/cache configuration.
$workflowJobId = $workflowDispatcher->dispatch('order_processing', ['order_id' => 'order-42']);
bash
php bin/console neuron-ai:rag:index application_docs
php bin/console neuron-ai:rag:index application_docs --reindex
bash
php bin/console neuron-ai:workflow:run order_processing --state='{"order_id":"order-42"}'
php bin/console neuron-ai:workflow:run order_processing --state='{"order_id":"order-42"}' --async
php bin/console neuron-ai:workflow:status "$JOB_ID"