PHPackages                             neuron-core/router - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. neuron-core/router

ActiveLibrary[API Development](/categories/api)

neuron-core/router
==================

Route inference calls to different underlying providers based on a routing strategy you define.

1.1.0(2w ago)23MITPHPPHP ^8.1CI passing

Since May 22Pushed 2w ago1 watchersCompare

[ Source](https://github.com/neuron-core/router)[ Packagist](https://packagist.org/packages/neuron-core/router)[ RSS](/packages/neuron-core-router/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (2)Dependencies (6)Versions (3)Used By (0)

Neuron AI Router
================

[](#neuron-ai-router)

This package provides you with a `RouterProvider` component. It is a proxy that implements `AIProviderInterface` and routes inference calls (`chat`, `stream`, `structured`) to different underlying providers based on a routing strategy you define. The agent doesn't know it's talking to a router, it's a drop-in replacement for any Neuron AI provider.

This is possible thanks to the Unified Messaging Layer that Neuron AI provides, with full support for multi-modality. Documentation here:

[![](/assets/neuron-router.png)](/assets/neuron-router.png)

When to Use It
--------------

[](#when-to-use-it)

- Route `structured()` calls to a provider with better structured output support (e.g., OpenAI) while using another provider for `chat()`
- Use different providers depending on the content of the messages (e.g., route image-heavy requests to Gemini)
- Switch providers based on whether tools are present in the request
- Implement cost-based or latency-based routing logic

Installation
------------

[](#installation)

Install the composer package:

```
composer require neuron-ai/router

```

Quick Start
-----------

[](#quick-start)

```
use NeuronAI\Router\RouterProvider;
use NeuronAI\Router\Rules\MethodRule;
use NeuronAI\Providers\Anthropic\Anthropic;
use NeuronAI\Providers\OpenAI\OpenAI;

class MyAgent extens Agent
{
    protected function provider(): AIProviderInterface
    {
        return RouterProvider::make()
            ->addProvider('anthropic', new Anthropic(
                key: 'ANTHROPIC_API_KEY',
                model: 'claude-sonnet-4-20250514',
            ))
            ->addProvider('openai', new OpenAI(
                key: 'OPENAI_API_KEY',
                model: 'gpt-4o',
            ))
            ->setRule(
                new RoundRobinRule(['anthropic', 'openai'])
            );
    }

    protected function instructions(): string
    {...}

    protected function tools(): array
    {...}
}
```

Default Provider
----------------

[](#default-provider)

The router delegates `messageMapper()` and `toolPayloadMapper()` to an underlying provider. After each inference call, these delegate to whichever provider the routing rule selected. If you need the mappers available before any inference call (e.g., during agent bootstrapping), set a default:

```
RouterProvider::make()
    ->addProvider('anthropic', new Anthropic(...))
    ->addProvider('openai', new OpenAI(...))
    ->setDefaultProvider('anthropic')
    ->setRule(new RoundRobinRule(['anthropic', 'openai']));
```

The default is overwritten each time the routing rule resolves a provider, so it only acts as the initial fallback.

Routing Rules
-------------

[](#routing-rules)

Routing logic is defined via the `RoutingRuleInterface`. The router calls `resolveProvider()` on the rule, passing context about the current request:

```
interface RoutingRuleInterface
{
    public function resolveProvider(string $method, array $messages, array $tools): string;
}
```

ParameterTypeDescription`$method``string`The inference method: `'chat'`, `'stream'`, or `'structured'``$messages``array`The messages being sent to the provider`$tools``array`The tools configured for this requestThe method must return the name of a registered provider (as a string).

### Built-in Rules

[](#built-in-rules)

#### MethodRule

[](#methodrule)

Routes based on the inference method. Set a default provider and optionally override specific methods:

```
use NeuronAI\Router\Rules\MethodRule;

$router = RouterProvider::make()->addProvider(...);

// Use Anthropic for everything, except structured output which goes to OpenAI
$router->setRule(
    new MethodRule('anthropic')->structured('openai')
)

// Override each method individually
$router->setRule(
    new MethodRule('openai')
        ->chat('anthropic')
        ->stream('anthropic')
        ->structured('openai')
)
```

#### CallbackRule

[](#callbackrule)

Wraps a callable for maximum flexibility. Use this when you need to inspect messages or tools:

```
use NeuronAI\Router\Rules\CallbackRule;

// Route based on tools presence
$router->setRule(new CallbackRule(function (string $method, array $messages, array $tools): string {
    if (count($tools) > 0) {
        return 'anthropic';
    }
    return 'openai';
}))
```

#### RoundRobinRule

[](#roundrobinrule)

Distributes requests evenly across providers in sequence. Each call cycles to the next provider:

```
use NeuronAI\Router\Rules\RoundRobinRule;

// Alternate between Anthropic and OpenAI for each request
$router->setRule(
    new RoundRobinRule(['anthropic', 'openai'])
)
```

#### ContentRule

[](#contentrule)

Routes based on the content blocks inside messages (images, files, audio, video). When a message contains a content type that not all providers support, you can route it to one that does:

```
use NeuronAI\Router\Rules\ContentRule;

// Use Anthropic by default, route images and video to Gemini, files to OpenAI
$router->setRule(
    new ContentRule('anthropic')
        ->image('gemini')
        ->video('gemini')
        ->file('openai')
)
```

When multiple content types are present in the same request, precedence is: **video → audio → image → file → default**. Content types without a configured provider are ignored and fall through to the next type in the precedence order.

### Custom Rules

[](#custom-rules)

Implement `RoutingRuleInterface` to create your own routing logic:

```
use NeuronAI\Router\Rules\RoutingRuleInterface;

class ImageAwareRule implements RoutingRuleInterface
{
    public function __construct(
        private string $defaultProvider,
        private string $imageProvider,
    ) {}

    public function resolveProvider(string $method, array $messages, array $tools): string
    {
        foreach ($messages as $message) {
            foreach ($message->getContents() as $content) {
                if ($content instanceof ImageContent) {
                    return $this->imageProvider;
                }
            }
        }
        return $this->defaultProvider;
    }
}
```

Then use it:

```
$router->setRule(
    new ImageAwareRule(
        defaultProvider: 'anthropic',
        imageProvider: 'gemini',
    )
)
```

Using with an Agent
-------------------

[](#using-with-an-agent)

Inject the router just like any other provider — either via `setAiProvider()` or by overriding the `provider()` method:

```
class MyAgent extends Agent
{
    protected function provider(): AIProviderInterface
    {
        return RouterProvider::make()
            ->addProvider('anthropic', new Anthropic(
                key: 'ANTHROPIC_API_KEY',
                model: 'claude-sonnet-4-20250514',
            ))
            ->addProvider('openai', new OpenAI(
                key: 'OPENAI_API_KEY',
                model: 'gpt-4o',
            ))
            ->setRule(
                new RoundRobinRule(['anthropic', 'openai'])
            );
    }
}
```

Error Handling
--------------

[](#error-handling)

The router throws `ProviderException` with clear messages for misconfiguration:

ScenarioError MessageNo routing rule set`no routing strategy configured. Call setRule() to set one.`No providers registered`no providers registered. Call addProvider() to add one.`Rule returns unknown name`unknown provider 'name'. Available: ...`Unknown default provider`unknown provider 'name'. Available: ...`Mapper called with no default or prior call`no provider available for delegation. Call setDefaultProvider() or make an inference call first.`Limitations
-----------

[](#limitations)

- `messageMapper()` and `toolPayloadMapper()` delegate to the last-resolved provider (or the default). These are internal to each concrete provider and are never called by the agent directly.
- `setHttpClient()` is forwarded to **all** registered providers.
- The routing rule is called on every inference request, so keep it fast.

###  Health Score

40

—

FairBetter than 86% of packages

Maintenance97

Actively maintained with recent releases

Popularity7

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity43

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~4 days

Total

2

Last Release

14d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/320345fbe48c7cff2b3a25992c8207e959ae7817fb2fb97bb176dc6e559aacf5?d=identicon)[valerione](/maintainers/valerione)

---

Top Contributors

[![ilvalerione](https://avatars.githubusercontent.com/u/13559278?v=4)](https://github.com/ilvalerione "ilvalerione (17 commits)")

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan, Rector

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/neuron-core-router/health.svg)

```
[![Health](https://phpackages.com/badges/neuron-core-router/health.svg)](https://phpackages.com/packages/neuron-core-router)
```

###  Alternatives

[facebook/php-business-sdk

PHP SDK for Facebook Business

90923.5M35](/packages/facebook-php-business-sdk)[hubspot/api-client

Hubspot API client

24015.5M18](/packages/hubspot-api-client)[neuron-core/neuron-laravel

Official Neuron AI Laravel SDK.

11025.7k](/packages/neuron-core-neuron-laravel)[botman/driver-telegram

Telegram driver for BotMan

93452.6k6](/packages/botman-driver-telegram)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
