Skip to content
Menu

Admin Settings

View .md

Admin settings (/beacon/admin-settings) holds the base URL Beacon puts in outgoing links and the LLM provider connection. A save applies to the running process at once, without a restart. Every change is recorded in a change history that also covers MCP settings and migration-write-target changes.

The page is open to Admins and to two functional permissions: an Auditor reads it, a SecurityAdmin reads and changes it. The LLM connection, the LLM concurrency and per-minute limits, and the base URL stay an Admin’s.

ActionRouteAdminSecurityAdminAuditor
Read the settings (secrets shown only as set or not set) and the change historyGET /beacon/api/admin-settings✓✓✓
List the LLM providers this host installedGET /beacon/api/admin-settings/llm-providers✓✓✓
Change the models and the monthly budgetPUT /beacon/api/admin-settings✓✓–
Change Max concurrent requests, Tokens per minute, Requests per minute or Enforce requests/tokens per minutePUT /beacon/api/admin-settings✓– (403)–
Change the Base URLPUT /beacon/api/admin-settings✓– (403)–
Change the LLM provider, endpoint, region, Bedrock authentication mode or any credentialPUT /beacon/api/admin-settings✓– (403)–
Test the stored LLM connectionPOST /beacon/api/admin-settings/test-llm✓✓–
Test with another provider, endpoint, region, authentication mode or credentialPOST /beacon/api/admin-settings/test-llm✓– (403)–

The provider, endpoint, region and authentication mode decide where Beacon sends its LLM requests with the stored credentials, the base URL is the address of every link Beacon sends out, and the concurrency and per-minute limits decide how much LLM traffic runs at all, so only an Admin changes them. For anyone else the page shows those fields disabled with a note, and a request that changes any of them answers 403 and saves nothing. An Auditor sees the page read-only. API keys never reach these routes.

While the approval workflow covers the LLM connection (CoversLlmConnection), an Admin’s change of the provider, endpoint, region or authentication mode, or a first stored provider, is not applied on save: it waits for a second live Admin’s approval, and the stored connection and models stay in use until then. The other values of the same save apply at once; a change of credentials or models alone, and testing the connection, are not reviewed.

FieldWhat it does
Base URLThe address Beacon puts in notification links ({BaseUrl}/notifications/{id} in Teams, Slack and webhook messages). The UI is served under /beacon, so include it: https://beacon.example.com/beacon. A saved value is an absolute https URL without user information or a fragment (plain http only for localhost or a loopback address while the host runs in Development); anything else answers 400. A stored value that is not usable leaves the link out of messages.

Pick the provider; the page shows only the fields it needs.

Provider (UI)AiProvider value (API llmProvider, Beacon:LLM:Provider)Fields
OpenAIOpenAI (0)API key, Model, Fast model
AnthropicClaude (1)API key, Model, Fast model
Azure OpenAIAzureOpenAI (2)Endpoint, API key, Deployment (model), Fast deployment
AWS BedrockBedrock (3)Region, Credentials, Model, Fast model

AWS Bedrock is installed only when the host references Moberg.Beacon.AI.Bedrock and calls AddBeaconBedrock(). The page offers only the providers the host installed (a stored provider that is not installed shows as Package not installed); picking another one is refused with 400.

Bedrock credentials. The authentication mode under Credentials decides which credentials the client uses. IAM role (the default) uses the default AWS credential chain (instance role, environment). Access key uses the AWS access key id and secret access key, and Temporary credentials uses them with a session token. Both of these modes need both keys: one without the other fails instead of falling back to the default chain. On PUT /beacon/api/admin-settings the fields are llmBedrockAuthMode, llmAwsAccessKeyId, llmAwsSecretAccessKey and llmSessionToken; in configuration they are Beacon:LLM:BedrockAuthMode, AwsAccessKeyId, AwsSecretAccessKey and SessionToken (see Configuration → LLM). The role or keys need the bedrock:InvokeModel permission for the chosen model.

An install that stored the key pair as accessKey:secretKey in the API key field keeps working. With both key fields empty, the access key and temporary credential modes use that pair. The IAM role mode uses it as well, but logs a warning (without the keys) that static keys from the API key field are in use instead of the default chain; clear the API key field to use the IAM role, or move the keys to the access key mode. When a saved configuration cannot build a provider, no provider is active until the configuration is fixed: AI features answer that the LLM provider is not configured, and the previous provider is never kept. The log names the failure’s type only.

Test connection sends a tiny request (at most 16 output tokens) with the stored connection and the models on the form, without saving.

Credentials and the Azure endpoint are encrypted at rest with Beacon:EncryptionKey and never returned: the page shows only whether each is set. Over the API, null for a credential or the endpoint keeps the stored value. The stored API key (or, for Bedrock, the AWS secret access key) is never sent to a different provider or endpoint: a save or a test that changes the provider or endpoint must carry the key again, or it answers 400 and nothing is saved or sent. The REST API sends enums as integers; configuration takes the names.

Max concurrent requests (default 50) applies to the LLM request queue as soon as it is saved: a higher limit lets waiting calls run at once, a lower one takes effect as running calls finish (none is cancelled), and background work keeps at most half the slots.

Tokens per minute and Requests per minute (defaults 80,000 and 1,000) apply only while Enforce requests/tokens per minute is on; it is off by default, and while it is off the two fields are recorded but not applied. When it is on, each call reserves one request and an estimate of its tokens (prompt characters divided by four, plus the call’s maximum answer tokens) before it is sent, and the tokens are settled with the usage the provider reports. The reservation is taken before the call waits for a concurrency slot and held while it waits; a call that is never sent (refused, cancelled or timed out) gives it back. The tokens are settled only when the response reports its input tokens; otherwise the estimate stands. Calls the limits cannot admit at once wait in arrival order, so a large call is never overtaken by smaller ones; an interactive call may pass waiting background work, and background work leaves a quarter of each per-minute allowance for interactive calls. A call that cannot get its share within its queue wait fails with The LLM is busy. Try again later. 0 means unlimited for that dimension.

Monthly budget (USD) (default 100) is recorded, not enforced: Beacon keeps no record of spend, so calls continue past it. Use the provider’s own spend limits for a hard cap.

Over the API, llmRateLimitsEnabled left out or null keeps the stored switch. Only an Admin changes these four values (403 otherwise): a SecurityAdmin sees them and sends the displayed ones back, and a SecurityAdmin’s save neither stores nor applies them, so the host-configured limits, or the ones an Admin saved, stay in force. Once an Admin saves them, the stored limits replace the host-configured ones (Beacon:LLM:Limits), also after a restart, and the first time they differ from the configured ones the host logs it at Information (numbers only).

Saving the settings records each changed value, the enforcement switch included (LLM.RateLimitsEnabled), in the change history and the security audit.

The page lists the latest changes from the settings history: when, which key, and who.

  1. The page sends PUT /beacon/api/admin-settings.
  2. AppSettingsService writes the values to app_settings (sensitive ones encrypted), records each changed key in app_setting_history, and clears its cache.
  3. The base URL in the running process (BeaconConfiguration.BaseUrl) is replaced.
  4. ILlmConfigurationUpdater.UpdateConfiguration hands the settings to LlmProviderManager, which builds a new provider and swaps it in atomically. A save by anyone but an Admin writes no LLM limit and keeps the limits in force. DelegatingLlmProvider, the proxy every feature holds, uses the new provider for the next request.

At startup the LLM provider is built from Beacon:LLM and the base URL comes from the host’s code (options.BaseUrl; the sample host reads Beacon:BaseUrl). Saving Admin settings swaps them immediately. After a restart the stored settings replace the configured ones once they are read: a stored base URL, the stored LLM configuration when a provider was stored, and the LLM limits (concurrency, per-minute limits and their enforcement) only when an Admin stored them, also when no provider was stored. A save that stores no provider keeps the provider from Beacon:LLM in force, as a restart would: it applies the limits (an Admin’s save) and the budget only. See Configuration → AI / LLM.

Settings are cached in memory for one hour; a save clears the cache.

app_setting_history records one row per changed value: setting_key, old_value, new_value (*** for sensitive values), changed_at and changed_by_user_id. It is returned with GET /beacon/api/admin-settings (the latest 200 rows), so Auditors, SecurityAdmins and Admins read it. Three families of keys are written:

KeysWritten when
General.BaseUrl, LLM.* (for example LLM.Provider, LLM.ApiKey, LLM.Model)Admin settings are saved
Mcp.{Setting}, Mcp.Project.{projectId}.{Setting}an MCP setting changes, globally or for a project
DataSource.{id}.AllowMigrationWritesan Admin marks or unmarks a data source as a migration write target

Every save that changes settings is also recorded in the security audit trail (settings.admin_settings_changed, settings.mcp_settings_changed, settings.mcp_project_settings_changed), naming the keys that changed and the history rows that hold their values, with a keyed digest of each value before and after; the values themselves stay in the history. Security-relevant actions outside settings (sign-ins, role changes, membership changes and the rest) are recorded in the security audit trail, not as history rows; see Security model.

public sealed class MyService(IAppSettingsService settingsService)
{
public async Task UseAsync(CancellationToken ct)
{
var settings = await settingsService.GetSettingsAsync(ct); // BaseUrl, LlmProvider, LlmModel, …
settings.LlmModel = "<model-id>";
await settingsService.SaveSettingsAsync(settings, userId: "<the caller's external id>", ct);
var llmHistory = await settingsService.GetHistoryAsync(key: "LLM.Model", ct);
}
}

SaveSettingsAsync applies no permission check: the REST route does. Code that calls it directly is responsible for who may.

ILlmConfigurationUpdater (void UpdateConfiguration(AppSettingsData settings)) lives in Beacon.Core so AppSettingsService can call it without referencing Beacon.AI; LlmProviderManager implements it.

MCP behaviour has its own page, MCP settings (/beacon/mcp-settings): an Auditor or a SecurityAdmin reads it, a SecurityAdmin changes it, Admins do both. Turning read-only enforcement or PII detection off, globally or for a project, is an Admin’s alone (403 otherwise). Its tabs are Pre-prompt, Tool descriptions, Guardrails and Context preview; a scope selector switches between the global defaults and a project’s overrides.

The deployment can pin settings no one can change at runtime, through Beacon:Mcp:

LockDefaultPins
ForceReadOnlytrueread-only enforcement on, globally and for every project
ForcePiiDetectiontruePII detection on
ForceNoContentRetentionfalsecontent retention off (questions, SQL and free-text errors never persisted)
ForbidRowDataToLlmfalsesample-value collection, value grounding and the eval judge off

On the global settings a locked switch is shown disabled with a lock and a note naming the configuration key; in a project’s scope locked fields are not offered and a banner names them. A write that contradicts a lock answers 409, an Admin’s included; GET /beacon/api/mcp/settings/locks lists the pinned settings. Beacon:Mcp:Ceilings clamp numeric settings downward: MaxRowLimit caps the row limit the MCP tools apply, MaxSqlChars and MaxQuestionChars are always-on length limits, AskTimeoutSeconds and AskMaxLlmCalls are the always-on time and LLM-call budgets of one ask call, and AskSchemaContextChars bounds the schema context one ask sends to the LLM; the other ceilings clamp the setting of the same name shown on this page. Every MCP settings change is recorded in the history above. See Configuration → Deployment locks and MCP server.