# ModelProviderSettingsContract

> Tracon documentation. Tracon is a .NET package family that adds a control
> plane on Microsoft Agent Framework, published as NuGet packages that run
> inside your own ASP.NET Core application.
>
> Page: https://tracon.dev/api/tracon.testing.contracts.providers.modelprovidersettingscontract/
> Summary: ModelProviderSettingsContract: Behavior tests for how a provider handles ModelBinding.ProviderSettings.

<div class="api-provenance">Namespace Tracon.Testing.Contracts.Providers · Assembly <code>Tracon.Testing.Contracts.Xunit.dll</code></div>

Behavior tests for how a provider handles
[ModelBinding.ProviderSettings](/api/tracon.modelbinding/#Tracon_ModelBinding_ProviderSettings).

```csharp
public abstract class ModelProviderSettingsContract : ModelProviderContract, IAsyncLifetime, IAsyncDisposable
```

<dl class="api-relations"><dt>Inheritance</dt><dd><a href="https://learn.microsoft.com/dotnet/api/system.object">object</a> ← <a href="/api/tracon.testing.contracts.providers.modelprovidercontract/">ModelProviderContract</a> ← <a href="/api/tracon.testing.contracts.providers.modelprovidersettingscontract/">ModelProviderSettingsContract</a></dd><dt>Implements</dt><dd>IAsyncLifetime, <a href="https://learn.microsoft.com/dotnet/api/system.iasyncdisposable">IAsyncDisposable</a></dd><dt>Inherited Members</dt><dd><a href="/api/tracon.testing.contracts.providers.modelprovidercontract/#Tracon_Testing_Contracts_Providers_ModelProviderContract_CreateProviderAsync">ModelProviderContract.CreateProviderAsync()</a>, <a href="/api/tracon.testing.contracts.providers.modelprovidercontract/#Tracon_Testing_Contracts_Providers_ModelProviderContract_InitializeAsync">ModelProviderContract.InitializeAsync()</a>, <a href="/api/tracon.testing.contracts.providers.modelprovidercontract/#Tracon_Testing_Contracts_Providers_ModelProviderContract_DisposeAsync">ModelProviderContract.DisposeAsync()</a>, <a href="/api/tracon.testing.contracts.providers.modelprovidercontract/#Tracon_Testing_Contracts_Providers_ModelProviderContract_OnDisposeAsync">ModelProviderContract.OnDisposeAsync()</a>, <a href="/api/tracon.testing.contracts.providers.modelprovidercontract/#Tracon_Testing_Contracts_Providers_ModelProviderContract_Binding_System_String_System_String_">ModelProviderContract.Binding(string?, string?)</a>, <a href="/api/tracon.testing.contracts.providers.modelprovidercontract/#Tracon_Testing_Contracts_Providers_ModelProviderContract_Provider_name_is_not_empty">ModelProviderContract.Provider_name_is_not_empty()</a>, <a href="/api/tracon.testing.contracts.providers.modelprovidercontract/#Tracon_Testing_Contracts_Providers_ModelProviderContract_Catalog_model_names_are_unique_and_not_empty">ModelProviderContract.Catalog_model_names_are_unique_and_not_empty()</a>, <a href="/api/tracon.testing.contracts.providers.modelprovidercontract/#Tracon_Testing_Contracts_Providers_ModelProviderContract_Create_chat_client_returns_a_client_for_the_setup_time_credential">ModelProviderContract.Create_chat_client_returns_a_client_for_the_setup_time_credential()</a>, <a href="/api/tracon.testing.contracts.providers.modelprovidercontract/#Tracon_Testing_Contracts_Providers_ModelProviderContract_Create_chat_client_returns_a_raw_client_that_builds_no_tool_call_loop">ModelProviderContract.Create_chat_client_returns_a_raw_client_that_builds_no_tool_call_loop()</a>, <a href="/api/tracon.testing.contracts.providers.modelprovidercontract/#Tracon_Testing_Contracts_Providers_ModelProviderContract_Create_chat_client_accepts_a_binding_whose_provider_name_differs_in_case">ModelProviderContract.Create_chat_client_accepts_a_binding_whose_provider_name_differs_in_case()</a>, <a href="/api/tracon.testing.contracts.providers.modelprovidercontract/#Tracon_Testing_Contracts_Providers_ModelProviderContract_A_model_the_catalog_does_not_list_is_not_rejected">ModelProviderContract.A_model_the_catalog_does_not_list_is_not_rejected()</a>, <a href="/api/tracon.testing.contracts.providers.modelprovidercontract/#Tracon_Testing_Contracts_Providers_ModelProviderContract_Concurrent_create_chat_client_calls_all_return_a_client">ModelProviderContract.Concurrent_create_chat_client_calls_all_return_a_client()</a>, <a href="/api/tracon.testing.contracts.providers.modelprovidercontract/#Tracon_Testing_Contracts_Providers_ModelProviderContract_A_client_that_is_never_disposed_does_not_stop_the_provider">ModelProviderContract.A_client_that_is_never_disposed_does_not_stop_the_provider()</a>, <a href="/api/tracon.testing.contracts.providers.modelprovidercontract/#Tracon_Testing_Contracts_Providers_ModelProviderContract_Provider">ModelProviderContract.Provider</a>, <a href="/api/tracon.testing.contracts.providers.modelprovidercontract/#Tracon_Testing_Contracts_Providers_ModelProviderContract_UnknownModelName">ModelProviderContract.UnknownModelName</a>, <a href="https://learn.microsoft.com/dotnet/api/system.object.gettype">object.GetType()</a>, <a href="https://learn.microsoft.com/dotnet/api/system.object.memberwiseclone">object.MemberwiseClone()</a>, <a href="https://learn.microsoft.com/dotnet/api/system.object.tostring">object.ToString()</a>, <a href="https://learn.microsoft.com/dotnet/api/system.object.equals#system-object-equals(system-object)">object.Equals(object?)</a>, <a href="https://learn.microsoft.com/dotnet/api/system.object.equals#system-object-equals(system-object-system-object)">object.Equals(object?, object?)</a>, <a href="https://learn.microsoft.com/dotnet/api/system.object.referenceequals">object.ReferenceEquals(object?, object?)</a>, <a href="https://learn.microsoft.com/dotnet/api/system.object.gethashcode">object.GetHashCode()</a></dd></dl>

## Remarks

Every provider owes the one rule Tracon fixes for all of them: an unknown
key is *not ignored silently*. This holds for a provider that
offers no tunable of its own as well — it rejects every key. A setting
that quietly does nothing makes the host author miss the behavior they
configured without ever seeing why, which is the same reasoning that makes
an unparsable [ModelBinding.ReasoningEffort](/api/tracon.modelbinding/#Tracon_ModelBinding_ReasoningEffort) stop compilation
instead of falling back to a default.

Derive this class for every provider. A provider that supports at least
one key overrides [ModelProviderSettingsContract.SupportedSetting](/api/tracon.testing.contracts.providers.modelprovidersettingscontract/#Tracon_Testing_Contracts_Providers_ModelProviderSettingsContract_SupportedSetting) with it; a provider that
supports none leaves it [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null), and the scenarios that need
a supported key are reported as skipped.

`ModelProviderSettings.Validate` in `Tracon.Abstractions`
implements this rule, including the prefix convention (`anthropic.*`,
`google.*`) that keeps one provider from silently accepting another's
keys. Pass an empty list of supported keys when the provider supports none.
Use it rather than a hand-rolled check: the model provider registry passes
its exception through with the offending key named, but masks the message
of any other exception a provider throws while it builds a client. These
scenarios call the provider directly, below the registry, so they cannot
see that difference.

## Constructors

### <a id="Tracon_Testing_Contracts_Providers_ModelProviderSettingsContract__ctor"></a> ModelProviderSettingsContract\(\)

```csharp
protected ModelProviderSettingsContract()
```

## Properties

### <a id="Tracon_Testing_Contracts_Providers_ModelProviderSettingsContract_InvalidSettingValue"></a> InvalidSettingValue

A setting key this provider supports, with a value it must reject, or
[null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null) when no supported key has a closed set of values.

```csharp
protected virtual KeyValuePair<string, JsonElement>? InvalidSettingValue { get; }
```

#### Property Value

 [KeyValuePair](https://learn.microsoft.com/dotnet/api/system.collections.generic.keyvaluepair\-2)<[string](https://learn.microsoft.com/dotnet/api/system.string), [JsonElement](https://learn.microsoft.com/dotnet/api/system.text.json.jsonelement)\>?

#### Remarks

A known key with a wrong value is the same mistake as an unknown key — a
typo the host author cannot see — so it fails the same way, naming the
key and never repeating the value. Choose a value of the right JSON type
that is outside the accepted set (for example an effort level the provider
does not define), so the case proves value validation and not only type
checking; a text value also proves the message does not echo it. The
default is [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null), which reports the scenario as skipped.

### <a id="Tracon_Testing_Contracts_Providers_ModelProviderSettingsContract_SupportedSetting"></a> SupportedSetting

A provider setting key this provider supports, with a value it accepts,
or [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null) when the provider supports no key.

```csharp
protected virtual KeyValuePair<string, JsonElement>? SupportedSetting { get; }
```

#### Property Value

 [KeyValuePair](https://learn.microsoft.com/dotnet/api/system.collections.generic.keyvaluepair\-2)<[string](https://learn.microsoft.com/dotnet/api/system.string), [JsonElement](https://learn.microsoft.com/dotnet/api/system.text.json.jsonelement)\>?

#### Remarks

When given, it proves the rejection below is about the key being
unknown, not about settings being rejected wholesale. The default is
[null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null).

### <a id="Tracon_Testing_Contracts_Providers_ModelProviderSettingsContract_UnsupportedSettingKey"></a> UnsupportedSettingKey

A setting key this provider does not support. Defaults to a key under
this provider's own prefix that no provider could plausibly define.

```csharp
protected virtual string UnsupportedSettingKey { get; }
```

#### Property Value

 [string](https://learn.microsoft.com/dotnet/api/system.string)

## Methods

### <a id="Tracon_Testing_Contracts_Providers_ModelProviderSettingsContract_A_supported_provider_setting_is_accepted"></a> A\_supported\_provider\_setting\_is\_accepted\(\)

```csharp
[Fact]
public void A_supported_provider_setting_is_accepted()
```

### <a id="Tracon_Testing_Contracts_Providers_ModelProviderSettingsContract_A_supported_setting_is_matched_regardless_of_key_casing"></a> A\_supported\_setting\_is\_matched\_regardless\_of\_key\_casing\(\)

```csharp
[Fact]
public void A_supported_setting_is_matched_regardless_of_key_casing()
```

#### Remarks

Keys arrive with the default (ordinal) comparer when the binding is
read back from a `jsonb` column, so a provider must not rely on
the dictionary's own comparer to match its keys case-insensitively.

### <a id="Tracon_Testing_Contracts_Providers_ModelProviderSettingsContract_A_supported_setting_with_an_invalid_value_is_rejected"></a> A\_supported\_setting\_with\_an\_invalid\_value\_is\_rejected\(\)

```csharp
[Fact]
public void A_supported_setting_with_an_invalid_value_is_rejected()
```

### <a id="Tracon_Testing_Contracts_Providers_ModelProviderSettingsContract_An_unsupported_provider_setting_is_rejected"></a> An\_unsupported\_provider\_setting\_is\_rejected\(\)

```csharp
[Fact]
public void An_unsupported_provider_setting_is_rejected()
```
