IModelProvider
AgentPrism.Abstractions.dllA model provider. Each provider is implemented in its own package (for
example, AgentPrism.OpenAI) and registered with DI.
public interface IModelProviderRemarks
Section titled “Remarks”This abstraction ensures that adding a new provider is not a breaking change. This is the main reason for the modular packaging decision.
Properties
Section titled “Properties”Models
Section titled “ Models”The models this provider offers.
IReadOnlyList<ModelDescriptor> Models { get; }Property Value
Section titled “Property Value”IReadOnlyList<ModelDescriptor>
The provider name. ModelBinding.Provider matches this value. Comparison is case-insensitive.
string Name { get; }Property Value
Section titled “Property Value”Methods
Section titled “Methods”CreateChatClient(ModelBinding, ModelProviderCredential?)
Section titled “ CreateChatClient(ModelBinding, ModelProviderCredential?)”Produces a raw chat client for the given binding.
IChatClient CreateChatClient(ModelBinding binding, ModelProviderCredential? credential = null)Parameters
Section titled “Parameters”binding ModelBinding
The model binding.
credential ModelProviderCredential?
A resolved per-tenant credential (BYOK). When null, the provider’s own setup-time credential is used and behavior is identical to a setup without per-tenant credentials. When given, the provider builds (or reuses a cached) client using ModelProviderCredential.ApiKey and, if present, ModelProviderCredential.Endpoint, instead of its setup-time credential.
Returns
Section titled “Returns”IChatClient
The provider-specific client. Decorators specific to the provider (example: Anthropic’s settings decorator) may be added here.
Remarks
Section titled “Remarks”Do not build the common pipeline here.
UseFunctionInvocation, UseOpenTelemetry, the content
guard, the circuit breaker, and extra resolution are added by
ModelProviderRegistry.CreateChatClient. Before that shared pipeline, every
provider package built the tool-call loop inside itself; the result
was that no ring the registry wraps around could see the loop’s turns
— a tool result entered the model uninspected.
If the loop is also built here, two nested FunctionInvokingChatClient
instances form: the inner one resolves tools, the outer one never sees
any call. The damage is not functional but measurable (double
wrapping, a misleading span tree).