Administrator control
Under Administration → Users, use Edit providers to manage a user’s endpoints, encrypted headers, models, default model, and connection tests. Turn off a user’s Provider settings switch to hide their provider page and block provider and model changes through the user API. The user can still chat with their configured models, but cannot retrieve stored headers or run connection tests. Administrators retain access through the admin console and API. Disable provider settings for all users applies the restriction to all current non-admin accounts, including disabled accounts. Turning it off restores access for those accounts. Administrators retain provider access. New accounts have provider settings enabled by default; this bulk action does not change that default. The managed edition continues to use one administrator-managed installation catalogue instead of these per-user controls.Add a provider
A provider is any endpoint implementing the OpenAI API surface.1
Enter the base URL
Use the URL that has
/chat/completions and /models beneath it, usually
ending in /v1.2
Add the API key
The key is encrypted with
SETTINGS_ENCRYPTION_KEY before storage. It is
write-only: the API returns a hasApiKey flag and never the value itself.3
Add custom headers if needed
Some gateways require extra headers, such as OpenRouter’s
HTTP-Referer and
X-Title.4
Test the connection
Test connection requests
<base URL>/models through the outbound guard.
This validates the URL, the key, and network reachability in one step.Conversation identification
Chat LLM requests automatically includex-session-id: <chat UUID>. This is the
persisted conversation ID, not a login session, user ID, message ID, or request
ID. It stays the same across turns, resumes, fresh context, tool steps, retries,
and model switches, including when collaborators contribute to the same chat.
Different conversations have different IDs.
The generated header replaces any configured x-session-id header regardless
of casing, so a static provider setting cannot group unrelated chats together.
Other custom headers and authentication are unchanged. Delegated web research
also receives this ID in its model headers (x-awr-llm-headers). It is not added
to model discovery/connection tests, MCP requests, ordinary web search/read
requests, or bounded inference calls that have no conversation.
This is a correlation hint for upstream providers that support it; it does not
replace the conversation history sent with each request. No provider-specific
body metadata or additional conversation-header aliases are added automatically.
Model history and reasoning
A response can take several model calls, one per tool step. The conversation stores each call separately, so later turns send the model the same sequence of assistant messages and tool results it saw while working. The unchanged prefix lets providers with prompt caching reuse it. Reasoning text that a model returns without provider state, such asreasoning_content, is shown in the transcript but not sent back as context.
Claude through unified-llm-proxy
unified-llm-proxy reports the original content of each Claude response, including signed, empty and redacted thinking, as aclaude_replay extension of its Chat Completions API. r5d-chat
stores that state with the model call it belongs to and returns it unchanged on
that call’s assistant message, both within a tool loop and on later turns. This
keeps Claude’s thinking intact across tool calls and its prompt cache warm.
- Use a provider whose base URL is the proxy’s OpenAI-compatible
/v1endpoint, running a proxy version withclaude_replaysupport. - The state is only returned to the provider that produced it. It is never shown in the transcript or sent to browsers, and it is not part of published snapshots or context estimates.
- Other providers are unaffected. Conversations from before this support have no stored state to return.
Images from tools
The agent sees images through its tools:readfile returns an image file
itself, and MCP tools can return images such as screenshots. The Chat
Completions API accepts images only in user messages, not in tool results, so
r5d-chat sends each tool result as text and the images it contained in a user
message directly after that step’s tool results, as image_url content with a
data: URL:
image_url parts into that API’s image
input; one that drops them leaves the model with only the text.
Turn off Image input for a text-only model. Its readfile then returns OCR
text for images, and images from other tools are replaced by a short note.
Add models
A provider holds any number of models. Each needs:string
required
The exact identifier the provider expects, such as
gpt-4o-mini or
anthropic/claude-sonnet-4.string
required
The label shown in the model picker.
positive integer ID
required
Choose one of the catalogue’s configured tiers. Administrators manage shared
managed-edition tiers; community users with provider access manage their own.
Multiple models can share a tier. This does not change pricing or reasoning
settings.
Configure tiers
A catalogue starts with Low (1), Medium (2), High (3), and Maximum (4), but these are defaults, not a fixed scale. Rename, reorder, add, or remove tiers in provider settings. The configured order controls the picker; numeric IDs remain stable when labels or order change. Community administrators can also edit a user’s tiers through Edit providers. Each catalogue has 1–32 tiers. IDs are unique positive integers up to 2147483647; labels are trimmed, nonempty, at most 40 characters, and unique ignoring case. Every model must reference a configured ID, including disabled models. Removing a tier still referenced by any model returns409: reassign
or delete those models first. Disabling them is not enough.
Existing assignments survive upgrades. New models, including provisioning-
manifest models, require an explicit configured tier. Provisioning accepts
modelTiers at the root for managed installations or on each users[] entry
for community catalogues; omitting it retains the existing definitions.
integer
required
Total token limit for the model. Used to decide when to trim context.
integer
required
Upper bound on a single response. Setting this above the provider’s real limit
causes request errors.
boolean
default:"on"
Whether the model accepts images. On by default; turn it off for a text-only
model, which would otherwise reject requests that contain an image. See
Images from tools.
Default model rules
Exactly one model per user is the default, enforced by themodels_one_default_per_user partial unique index.
- Make default releases the current holder before setting the new one, because the index rejects the opposite order.
- Deleting or disabling the default model, or the provider that owns it, automatically promotes the oldest remaining enabled model.
- A user therefore always has a usable default as long as one enabled model exists.
Which model a conversation uses
A conversation follows the default. Each new message, and each resumed response, runs on whichever model is the default at that moment, not the one that was the default when the conversation started. Changing the default therefore moves every existing conversation on its next message. Picking another model in the composer pins it to that conversation, and later messages keep using it. The pin ends when the default is chosen again, or when the picked model or its provider is disabled or deleted; the conversation then follows the default again. The compact model selector sits beside the send button and shows the current capability level. Click it to open a popover above the composer, with the model name and a slider following your configured tier order. Drag the slider or use the arrow keys. Empty tiers are skipped. Escape or clicking outside closes the popover. Click the model name to choose an exact model; returning to a tier remembers that choice for the current page session. Otherwise it selects that tier’s default model, then the first model alphabetically. In the community edition, click the star to make the selected model your default for new chats and chats following your default. A filled star marks the current default. Every response names the model that wrote it, with the time, beside its copy button; hover the name for the provider’s model ID, which is what an upstream gateway reports.The outbound request guard
Every outbound call is checked before it is made. By default the guard rejects:- Non-HTTPS URLs
- URLs containing embedded credentials
- Private, loopback, and link-local addresses
- Cloud metadata endpoints
- Redirects to any of the above
- Public providers
- In-cluster or LAN endpoints
- Plain HTTP endpoints
No configuration needed. Public HTTPS endpoints pass the guard.
Troubleshooting
Test connection fails with a blocked destination
Test connection fails with a blocked destination
The guard rejected the URL. Confirm it is HTTPS and publicly resolvable, or
enable
ALLOW_PRIVATE_EGRESS for an internal endpoint.401 or 403 from the provider
401 or 403 from the provider
The stored key is wrong or lacks access to the requested model. Keys are
write-only, so re-enter it rather than trying to read it back.
404 on a model that exists
404 on a model that exists
The base URL is probably missing or duplicating its version segment. The
application appends
/chat/completions, so the base URL should end at /v1.Requests fail once conversations get long
Requests fail once conversations get long
The configured context window exceeds the model’s real limit. Lower it to the
provider’s documented value.
Everything broke after a key rotation
Everything broke after a key rotation
If
SETTINGS_ENCRYPTION_KEY changed, stored credentials cannot be
decrypted. Restore the original key or have users re-enter their
credentials.Backup implications
Provider credentials are encrypted in the database with the installation key. The database andSETTINGS_ENCRYPTION_KEY form a single recovery unit; a
database restore without the matching key yields unreadable credentials.
Backup and restore
What to back up and how to validate a restore.
Usage and budget
In the community edition, the sidebar shows Spent (or Used), Budget, and Remaining for each provider that reports usage. Click a card to open Settings → Usage for the monthly report, reporting dates, and optional technical token details. Other providers retain their own reporting periods; the app does not assume every balance is monthly. The conversation context popup only describes the current conversation’s context window.Link to a provider’s full report
Any supported usage response can include this optional top-level extension:/api/usage result exposes it as dashboardUrl.
Without the field, the app still displays the usage report and omits the link.
The URL must be absolute HTTP(S) with no embedded username or password. It
should identify a normal signed-in dashboard, without API keys or access tokens
in the URL. View full usage opens it in a new tab using the user’s browser
session; r5d-chat never fetches it or sends provider headers to it. A separate
provider login may be required.
Providers own the accounting: amounts, currency or unit, account/key scope,
reporting boundaries and timezone, balance adjustments, and actual reset times.
The chat app owns readable labels, currency and date formatting, and the budget
layout. A period’s exclusive end is not automatically a balance reset, and an
explicit remaining balance is preserved even if it differs from budget minus
spend. Missing values appear as Not reported, never zero or unlimited.