> For the complete documentation index, see [llms.txt](https://docs.umbraco.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.umbraco.com/ai-in-umbraco/17.latest/extending/providers/provider-settings.md).

# Provider Settings

Provider settings define the configuration properties needed to connect to an AI service. Use the `[AIField]` attribute to control how settings appear in the backoffice UI.

## AIFieldAttribute

The `[AIField]` attribute decorates setting properties with UI metadata:

{% code title="AIFieldAttribute Properties" %}

```csharp
[AIField(
    Label = "Display Label",           // Shown in the UI
    Description = "Help text",         // Description below the field
    EditorUiAlias = "Umb.PropertyEditorUi.TextBox",  // Umbraco editor
    SortOrder = 1                       // Display order
)]
public string? MyProperty { get; set; } = "default";  // Set defaults on the property itself
```

{% endcode %}

## Properties

| Property        | Type     | Description                                       |
| --------------- | -------- | ------------------------------------------------- |
| `Label`         | `string` | Display label in the UI                           |
| `Description`   | `string` | Help text shown below the field                   |
| `EditorUiAlias` | `string` | Umbraco property editor UI alias                  |
| `EditorConfig`  | `string` | Configuration for the editor UI                   |
| `SortOrder`     | `int`    | Order in which settings are displayed             |
| `IsSensitive`   | `bool`   | Marks the field as sensitive (value masked in UI) |
| `Group`         | `string` | Groups settings under a collapsible heading       |

## Automatic Type Inference

If `EditorUiAlias` is not specified, the editor is inferred from the property type:

| C# Type                      | Inferred Editor                |
| ---------------------------- | ------------------------------ |
| `string`                     | `Umb.PropertyEditorUi.TextBox` |
| `int`                        | `Umb.PropertyEditorUi.Integer` |
| `bool`                       | `Umb.PropertyEditorUi.Toggle`  |
| `decimal`, `float`, `double` | `Umb.PropertyEditorUi.Decimal` |

## Example Settings Class

{% code title="MyProviderSettings.cs" %}

```csharp
using System.ComponentModel.DataAnnotations;
using Umbraco.AI.Core.EditableModels;

public class MyProviderSettings
{
    [AIField(
        Label = "API Key",
        Description = "Your API key. Supports config references like $Umbraco:AI:Secrets:MyProviderApiKey",
        SortOrder = 1)]
    [Required]
    public required string ApiKey { get; set; }

    [AIField(
        Label = "Base URL",
        Description = "Override the default API endpoint",
        SortOrder = 2)]
    public string? BaseUrl { get; set; } = "https://api.myprovider.com";

    [AIField(
        Label = "Max Retries",
        Description = "Number of retry attempts for failed requests",
        SortOrder = 3)]
    public int MaxRetries { get; set; } = 3;

    [AIField(
        Label = "Enable Logging",
        Description = "Log all requests and responses",
        SortOrder = 4)]
    public bool EnableLogging { get; set; }

    [AIField(
        Label = "Timeout (seconds)",
        Description = "Request timeout in seconds",
        SortOrder = 5)]
    public double TimeoutSeconds { get; set; } = 30.0;
}
```

{% endcode %}

## Validation Attributes

Use standard .NET validation attributes alongside `[AIField]`:

{% code title="Validation Example" %}

```csharp
public class ValidatedSettings
{
    [AIField(Label = "API Key")]
    [Required(ErrorMessage = "API Key is required")]
    public required string ApiKey { get; set; }

    [AIField(Label = "Max Tokens")]
    [Range(1, 100000, ErrorMessage = "Max tokens must be between 1 and 100000")]
    public int? MaxTokens { get; set; }

    [AIField(Label = "Email")]
    [EmailAddress(ErrorMessage = "Invalid email address")]
    public string? NotificationEmail { get; set; }

    [AIField(Label = "Endpoint URL")]
    [Url(ErrorMessage = "Must be a valid URL")]
    public string? CustomEndpoint { get; set; }
}
```

{% endcode %}

{% hint style="info" %}
Non-nullable properties without `[Required]` automatically have a required validation added.
{% endhint %}

## Configuration References

Settings values starting with `$` are resolved from configuration. References resolve from the `Umbraco:AI:Secrets` section (sensitive values) and `Umbraco:AI:Variables` section (non-sensitive values) by default.

**In the UI:** Enter `$Umbraco:AI:Secrets:MyProviderApiKey`

**In appsettings.json:**

{% code title="appsettings.json" %}

```json
{
    "Umbraco": {
        "AI": {
            "Secrets": {
                "MyProviderApiKey": "sk-actual-key-here"
            }
        }
    }
}
```

{% endcode %}

This keeps secrets out of the database and supports environment-specific values.

{% hint style="info" %}
Values under `Umbraco:AI:Secrets` may only be referenced from fields marked `IsSensitive = true` (see [Sensitive Settings](#sensitive-settings)). Mark any field that should accept a secret reference as sensitive. To reference values from other configuration sections, add their prefix to `Umbraco:AI:AllowedConfigurationKeyPrefixes` - see [AIOptions](/ai-in-umbraco/17.latest/reference/configuration/ai-options.md#configuration-references).
{% endhint %}

## Sensitive Settings

Mark API keys and secrets with `IsSensitive = true`. The value is masked when displayed back in the UI.

{% code title="Sensitive Settings" %}

```csharp
[AIField(IsSensitive = true)]
[Required]
public string? ApiKey { get; set; }

[AIField(IsSensitive = true)]
public string? SecretToken { get; set; }
```

{% endcode %}

{% hint style="info" %}
Sensitive values are encrypted at rest using [ASP.NET Core Data Protection](https://learn.microsoft.com/aspnet/core/security/data-protection/configuration/overview). If the Data Protection keyring isn't persisted across restarts, decryption will fail. This occurs when Windows IIS app pools lack profiles or containers with persistent volumes. The value will appear as `ENC:...` in the UI, and the log will show `The key {guid} was not found in the key ring`. Configure Data Protection to persist keys to a stable store. Alternatively, use configuration references to store secrets in appsettings.json instead of the database.
{% endhint %}

## Custom Editors

Use Umbraco property editor UI aliases for specialized input:

{% code title="Custom Editors" %}

```csharp
// Textarea for longer text
[AIField(
    Label = "System Prompt",
    EditorUiAlias = "Umb.PropertyEditorUi.TextArea")]
public string? SystemPrompt { get; set; }

// Integer with spinner
[AIField(
    Label = "Max Tokens",
    EditorUiAlias = "Umb.PropertyEditorUi.Integer")]
public int? MaxTokens { get; set; }
```

{% endcode %}

## Accessing Settings in Capabilities

Settings are passed to capability methods after being resolved:

{% code title="Using Settings" %}

```csharp
public class MyChatCapability : AIChatCapabilityBase<MyProviderSettings>
{
    public MyChatCapability(IAIProvider provider) : base(provider) { }

    protected override IChatClient CreateClient(MyProviderSettings settings, string? modelId)
    {
        // Settings are fully resolved - config references replaced with actual values
        var client = new HttpClient
        {
            BaseAddress = new Uri(settings.BaseUrl ?? "https://api.default.com"),
            Timeout = TimeSpan.FromSeconds(settings.TimeoutSeconds)
        };

        client.DefaultRequestHeaders.Add("Authorization", $"Bearer {settings.ApiKey}");

        return new MyHttpChatClient(client, modelId);
    }
}
```

{% endcode %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.umbraco.com/ai-in-umbraco/17.latest/extending/providers/provider-settings.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
