---
title: "Provider middleware"
manual: "LLM Foundation"
version: "main"
permalink: "https://docs.typo3.org/permalink/netresearch/nr-llm:api-middleware@main"
source: "Api/Middleware.rst"
rendered: "2026-11-12T15:41:35+00:00"
---

# Provider middleware {#api-middleware}

Implement `Netresearch\NrLlm\Provider\Middleware\ProviderMiddlewareInterface`
for a provider-call concern. Its method is
`handle(ProviderCallContext $context, callable $next): mixed`. The current
configuration is on `$context->configuration`; when replacing it, derive a
new context with `withConfiguration()`. Pass that context to `$next`.

**Transparent middleware extension**

```php
<?php

declare(strict_types=1);

namespace MyVendor\MyExtension\Provider;

use Netresearch\NrLlm\Provider\Middleware\ProviderCallContext;
use Netresearch\NrLlm\Provider\Middleware\ProviderMiddlewareInterface;

final class ObserveCall implements ProviderMiddlewareInterface
{
    public static function getDefaultPriority(): int
    {
        return 80;
    }

    public function handle(ProviderCallContext $context, callable $next): mixed
    {
        return $next($context);
    }
}
```

The interface supplies the `nr_llm.provider_middleware` autoconfiguration
tag. Priority comes from the static `getDefaultPriority()` convention;
omitting it means priority 0. Do not rely on a duplicate tag's attribute
priority. Higher priority enters first and exits last.

| Middleware | Priority |
| --- | --- |
| Telemetry | 110 |
| Idempotency | 105 |
| Cache | 100 |
| Guardrail | 90 |
| Empty answer | 85 |
| Budget | 75 |
| Fallback | 50 |
| Usage | 25 |
| Circuit breaker | 20 |

This order explains short circuits: a cache hit does not become another paid
provider request. A retry or fallback changes which inner layers execute;
observe the actual context rather than inferring the serving model from a
stored fixed-model relation. Streaming has its own dispatcher lifecycle;
see [Streaming support](https://docs.typo3.org/permalink/netresearch/nr-llm:developer-streaming@main). The historical design is [ADR-026: Provider Middleware Pipeline](https://docs.typo3.org/permalink/netresearch/nr-llm:adr-026@main) and
its context change is [ADR-096: The pipeline configuration lives on the call context](https://docs.typo3.org/permalink/netresearch/nr-llm:adr-096@main).
