Collaboration & Multi-User
Details
A single AI Optimizer API Server can serve many clients at once โ multiple people using the GUI, several IDE or MCP sessions, and external applications. This page explains how those clients are kept apart, which configuration they share, and how to protect shared configuration with a password.
Client IDs
Every request to the API Server carries a client ID that identifies the session it belongs to. The server keeps a separate set of settings and conversation history for each distinct ID.
- The AI Optimizer GUI client generates a fresh, random ID (a UUID) for each browser session. You can see the current value under โฐ โ About in the GUI.
- IDE and MCP clients connect as the
serverclient by default. See IDE Integration for how to push your GUI settings to that client. - External applications choose their own ID โ passed as the
clientheader on chat requests, or theclientquery parameter on settings requests.
A client ID may be 1โ255 printable ASCII characters. Path separators (/, \) and the bare components . and .. are rejected. When a request arrives with an ID the server has not seen before, a new session is created automatically by forking the configured defaults (see below).
Reserved client IDs
| Client ID | Purpose |
|---|---|
CONFIGURED | The default settings template. New clients are forked from this, and settings requests that omit ?client=... operate on it directly. |
server | The session used for chat requests that omit the client header โ the default identity for external and IDE clients. |
FACTORY | Built-in factory defaults. |
These three are protected โ they are never evicted from the in-memory store.
Note
The default differs by endpoint. Chat and history requests (which read the client header) default to server. Settings requests (which read the client query parameter) default to CONFIGURED โ so a settings call that omits ?client=... reads or mutates the shared defaults template, not your external-client session. Always send an explicit client when configuring a specific session.
Session capacity
The server caches client sessions in memory up to AIO_MAX_CLIENTS (default 64). Beyond that limit, the least-recently-used session is evicted (protected clients are never evicted). An evicted client is not lost permanently โ its next request simply re-creates a session from the configured defaults. Raise AIO_MAX_CLIENTS if you expect many simultaneous users. See Configuration.
What Is Shared vs. Isolated
The distinction is between the catalog of available resources (shared) and a client’s selection from that catalog (isolated).
Shared across all clients
These are configured once at the server and are common to every client:
- Database connections (aliases, DSNs, vector stores)
- Model configurations (which models exist, their endpoints and API keys)
- OCI profiles
- Prompt configurations
- The API Server key (
AIO_API_KEY)
When one user adds a database or enables a model, that resource becomes part of the catalog for everyone.
Isolated per client
Each client keeps its own working selection and runtime state:
- Selected language model and its parameters (temperature, max tokens, top-p, penalties)
- Selected database alias
- Selected OCI profile
- Enabled tools (Vector Search, NL2SQL)
- Vector Search settings (selected store, search type, top-k, thresholds)
- Testbed model selections
- Conversation history
So two users share the same list of databases and models, but each chooses which database and which model their own session uses, and each session keeps its own chat history under its own client ID.
Warning
Client IDs partition state; they are not an access boundary. The client value is caller-supplied and is not authenticated or bound to a user โ it only selects which session a request reads or writes. In a deployment where several callers share one AIO_API_KEY, any caller that knows or guesses another ID (including server) can address that session and fetch its /v1/chat/history. Do not rely on client IDs for privacy or tenant isolation between mutually untrusted users. To separate untrusted tenants, run separate deployments with distinct API keys, and put network/identity controls in front of the server โ see TLS.
Note
New sessions are forked from the CONFIGURED client. In an “All-in-One” deployment you can seed external clients with your current GUI selections using Copy Client Settings on the API Server page.
Example: the Racing Championship use-case
The Racing Championship use-case is designed to be run by a group at the same time, and it illustrates this split directly:
- Each participant opens their own GUI session โ a distinct client ID โ and plays a different driver. Their
I am Driver <N>turn, conversation history, and tool selections are partitioned by that ID, so under normal use one person’s context does not bleed into another’s answers. (As noted above, this is state separation, not an enforced access boundary.) - Everyone draws on the shared catalog: the same database (the
drivers,race_results, and standings tables), the same enabled chat and embedding models, and a common vector store. As the use-case notes, when several people run it together they “embed all the relevant driver docs into the same store in one pass” โ one shared corpus, many isolated sessions querying it.
Protecting Shared Configuration with a Password
Because the catalog is shared, any GUI user can, by default, change configuration that affects everyone โ adding or deleting databases, editing models, resetting settings, or exporting configuration that contains secrets. For shared or multi-user deployments, set a shared password to gate those controls.
Set AIO_CLIENT_PASSWORD to enable the gate:
| Variable | Description | Default |
|---|---|---|
AIO_CLIENT_PASSWORD | Shared password that gates configuration and shared-state controls in the GUI client. When unset, the gate is disabled and all controls are accessible. | (unset โ gate off) |
Note
This is a GUI-only access check. It does not replace or affect API Server authentication โ external clients still authenticate with AIO_API_KEY. See Configuration.
What the gate covers
When a password is configured, the following remain read-only until a user signs in:
- Configuration tabs โ Databases, Models, OCI, MCP, and Settings
- The API Server page (including the server key)
- Stored connection fields (passwords and keys render as a redacted
โขโขโขโขโขโขโขโขplaceholder rather than editable inputs) - Reset / Delete actions and configuration import/export
- Prompt Engineering edits
Pages that act as personal workspaces โ ChatBot, Tools, and Testbed โ stay usable while signed out. Only the controls on those pages that would change shared state for other users are gated.
Signing in and out
When the gate is active, a ๐ Sign-in entry appears in the sidebar. Selecting it (or the inline “Sign in” link shown next to a locked control) opens a dialog with a single password field โ enter the shared password and press Enter.
Authentication is per browser session: signing in unlocks the gated controls for that session only, and other users’ sessions are unaffected. Once signed in, the entry becomes ๐ Sign-out, which clears the session’s authenticated state.
Tip
The password is shared โ a single secret distributed to the people allowed to change configuration. It is an access gate over shared controls, not per-user identity. For TLS and network-level hardening of a multi-user deployment, see TLS.
Related
- Racing Championship โ a multi-user use-case
- API Server
- IDE Integration
- Configuration
- TLS
- API Examples