Registering a provider
Two mechanisms pick up your provider class. Use the attribute when you can.
Preferred: the #[AsLlmProvider] attribute
Add the attribute to any provider class that lives under the
Netresearch\NrLlm\ namespace. The compiler pass auto-tags the
service, sets it public (so backend diagnostics can resolve it by
class name), and registers it with
Llm in priority order:
use Netresearch\NrLlm\Attribute\AsLlmProvider;
use Netresearch\NrLlm\Provider\AbstractProvider;
#[AsLlmProvider(priority: 85)]
final class MyProvider extends AbstractProvider
{
public function getIdentifier(): string
{
return 'my-provider';
}
public function getName(): string
{
return 'My LLM Service';
}
// ... chatCompletion(), embeddings(), supportsFeature()
}
Priority is an ordering hint only. Providers are still resolved by
their getIdentifier() at runtime. Higher priority wins when two
providers otherwise tie.
Note
The attribute scan is scoped to the Netresearch\NrLlm\
namespace to keep container-build reflection bounded.
Third-party extensions shipping providers outside that namespace
must continue to use the yaml-tagging path described below.
Third-party fallback: yaml tagging
Extensions that sit outside the Netresearch\NrLlm\ namespace
still work via the original mechanism — declare a service with the
nr_llm.provider tag:
services:
Acme\MyExt\Provider\AcmeProvider:
public: true
tags:
- name: nr_llm.provider
priority: 85
When both yaml tagging AND the attribute are present on the same service, the yaml wins (the attribute pass skips already-tagged services). Treat this as an override hook rather than an additive mechanism.
Capability interfaces
Priority governs registration order only; it says nothing about
what a provider can do. Capabilities are advertised by implementing
the relevant interface from Netresearch:
Vision— image analysisCapable Interface Streaming— SSE streamingCapable Interface Tool— function / tool callingCapable Interface Document— PDF / structured document inputCapable Interface
Llm dispatches to a provider only when the
caller's requested operation matches a capability the provider
actually advertises. A provider that doesn't implement
Vision can never be asked to describe an
image, regardless of priority. See ADR-022: Attribute-Based Provider Registration for the
attribute-discovery design decision and the Symfony
registerAttributeForAutoconfiguration alternative we evaluated.