Skip to main content

Admin Console

The Dionysys admin console is a reusable package UI for inspecting and changing adaptive UI configuration at runtime. It is designed as an information and control center for deterministic mode, MCP mode, personalities, calculations, session summaries, resources, and adaptive API status.

The console does not write edits back into source files. It starts from file-seeded backend configuration, saves changes into the backend's in-memory runtime config, and lets you export the active configuration as JSON for future use.

Prototype vs Production​

The admin runtime config includes a presentation mode:

  • prototype: show the control room: admin controls, mode switch, debug panel, variants, personalities, scores, resources, and pending-decision notices.
  • production: hide experiment details from front-facing users and show only lightweight feedback controls.

It also includes a decision application mode:

  • immediate: apply the selected variant or MCP UI state as soon as the decision resolves.
  • next-refresh: store the resolved personality/decision now, keep the active workspace stable, and apply the UI change on the next refresh/provider mount.

For prototype testing, the admin console also shows the active persistence mode and includes a non-production session randomize tool. That reset clears the session id plus both queued and applied adaptive state for the current session before reloading.

The Excalidraw demo defaults to prototype plus next-refresh.

Enable / Disable​

Admin routes are disabled unless the backend opt-in flag is set:

ADMIN_CONSOLE_ENABLED=true npm run dev --workspace=@dionysys-demo/excalidraw-backend

To disable the backend admin API, omit ADMIN_CONSOLE_ENABLED or set it to anything other than true.

The admin API routes live under /api/admin:

GET /api/admin/config
PUT /api/admin/config
POST /api/admin/config/reset
GET /api/admin/config/export
GET /api/admin/overview?sessionId=session_123

The Excalidraw demo renders the admin console as an in-app overlay, not as a standalone browser route. The demo shows the Admin button in development or when the frontend flag is enabled:

VITE_ADMIN_CONSOLE_ENABLED=true npm run dev --workspace=@dionysys-demo/excalidraw-frontend

The backend remains the authority. If the frontend button is visible but ADMIN_CONSOLE_ENABLED is not set, the console will show that the admin API is disabled.

For hosted production builds, the frontend flag is build-time configuration because the demo uses Vite import.meta.env. For example, on Vercel set VITE_ADMIN_CONSOLE_ENABLED=true as a build environment variable, not only as a runtime variable.

To use the live console successfully, all of the following must agree:

  • the frontend build must point VITE_API_BASE_URL at the real backend origin
  • the backend must allow the deployed frontend origin through ALLOWED_ORIGIN
  • ADMIN_CONSOLE_ENABLED=true must be set on the backend
  • VITE_ADMIN_CONSOLE_ENABLED=true must be present when the frontend is built

Package Component​

@dionysys/react exports the reusable console:

import { AdminConsole } from '@dionysys/react';

export function ExperimentAdmin() {
return (
<AdminConsole
apiBaseUrl="http://localhost:3001"
sessionId="session_123"
onConfigSaved={(config) => {
console.log('Saved runtime config', config.mode.defaultMode);
}}
/>
);
}

Props:

PropTypePurpose
apiBaseUrlstringBackend origin. Defaults to http://localhost:3001.
sessionIdstringOptional active session to summarize in the Data and Overview tabs.
onConfigSaved(config) => voidCalled after save or reset so an app can remount providers from the new runtime config.
onClose() => voidOptional close handler for modal or drawer integrations.

Behind that single export, the package now keeps the admin console split into:

  • a root shell component
  • a state/orchestration hook for load/save/reset/export behavior
  • focused section modules for overview, modes, personalities, calculations, data, APIs, and export
  • shared primitives and styles

That split is internal to the package. Consumers still mount the same <AdminConsole /> component from @dionysys/react.

What You Can Control​

The console has focused tabs for the main adaptive surfaces:

TabWhat it shows or edits
OverviewCurrent default mode, connector status, session event count, top deterministic and MCP persona scores, resources, supported tools, and fallback variant.
ModesDefault adaptive mode, presentationMode, decisionApplication, provider event threshold, polling interval, MCP minimum confidence, and fallback variant.
PersonalitiesMCP personality resource names, ids, descriptions, decision hints, base weights, scoring signals, actions, and UI states.
CalculationsDeterministic personas, initial counts, policy epsilon, event weight rules, and heuristic rules.
DataSummarized interaction data, derived counts, timing metrics, and sanitized recent events for the selected session.
BanditInspect and maintain the Thompson-sampling arms — see Bandit tab below.
MCP APIsRuntime API status and the active MCP resource catalog.
ExportFull JSON editor, local JSON apply, and JSON export for future use.

Bandit tab​

The Bandit tab opens up the otherwise-opaque weak-signal learner. Arms are grouped by context (<modality>:<expertise>); each arm shows:

  • Posterior mean and a 90% credible interval over its Beta posterior.
  • Observations (n) — evidence beyond the prior — and the evidence weight wBandit = n / (n + banditEvidenceK) that sets how much the arm pulls against the LLM.
  • P(best) — a Monte-Carlo estimate of how often the arm wins a posterior draw. This replaces argmax-of-means as the "would pick" signal, so the highlighted arm reflects genuine uncertainty.

A decision trace (when a sessionId is supplied) reconstructs gate → LLM pick → bandit sample → blend → applied variant from the stored decision metadata. Maintenance controls let you decay all arms once, export/import a snapshot of learned state, or reset everything to priors. Decay status (on/off, effective window, derived γ) is shown alongside the totals. See mcp.bandit.decay for the underlying model.

Runtime Config API​

When enabled, the backend exposes the same /api/admin routes listed above.

PUT /api/admin/config validates the full admin config payload before updating runtime state. Invalid config returns 400 with schema issues.

GET /api/admin/overview summarizes session events before returning them. The console sees capped, sanitized recent event metadata rather than raw unbounded payloads.

Excalidraw Demo Integration​

The Excalidraw demo mounts the console as an overlay. When the console saves or resets config, the demo:

  1. Reads config.mode.defaultMode.
  2. Reads config.mode.presentationMode and config.mode.decisionApplication.
  3. Updates minEventsBeforeLock and pollingIntervalMs.
  4. Remounts AdaptiveProvider so lock state and active decisions reset cleanly.

This means you can change the default mode from deterministic to mcp, tune thresholds, edit MCP resources, save, and immediately continue the demo with the active runtime configuration.

Exporting Configuration​

Use Export to download:

{
"exportedAt": "2026-04-19T00:00:00.000Z",
"config": {
"version": 1,
"mode": {
"defaultMode": "mcp",
"presentationMode": "prototype",
"decisionApplication": "next-refresh",
"minEventsBeforeLock": 5,
"pollingIntervalMs": 3000
}
}
}

The export is for future use outside the current runtime session. It does not overwrite demos/excalidraw/frontend/src/config/variantConfig.ts or demos/excalidraw/backend/src/services/ExcalidrawMcpResources.ts.

The same rule applies to every control in the console: it edits validated runtime state only. The browser does not rewrite tracked markdown, TypeScript, or config files in the repository.

Safety Model​

  • Admin APIs are disabled by default and require ADMIN_CONSOLE_ENABLED=true.
  • LLM API keys remain server-side.
  • Session data is summarized and sanitized before display or LLM connector use.
  • Source files are not mutated from the browser.
  • Deterministic and MCP decision paths continue to validate config through package schemas.