Skip to main content

Configuration Guide

This guide covers every environment variable, client option, and connector selection used by the Dionysys SDK stack.

Runtime configuration layers​

LayerResponsibility
@dionysys/coreSchemas, deterministic logic, MCP resources, shared contracts
@dionysys/serverRoute wiring, storage integration, connector dispatch, admin orchestration
@dionysys/clientAPI transport and current-session persistence
@dionysys/reactProvider behavior, feedback UI, admin console UI
App codeEvent translation, UI rendering, app-specific metadata

Backend environment variables​

VariableTypeDefaultEffect
PORTnumber3001Port the Express server binds to
ALLOWED_ORIGINstringhttp://localhost:5173CORS allowed origin(s); comma-separate for multiple; * allows all
MONGO_URIstringmongodb://127.0.0.1:27017/autoui_ab_testingMongoDB connection string when using the MongoDB storage adapter
ADMIN_CONSOLE_ENABLEDbooleanfalseEnables the admin config endpoints (/api/dionysys/admin/*)
DIONYSYS_STORAGEmemory|mongodbmemoryStorage backend; mongodb requires MONGO_URI
DIONYSYS_LLM_PROVIDERmock|custom-http|openai|gemini|anthropicmockDecision connector to use

OpenAI connector variables​

VariableTypeDefaultEffect
OPENAI_API_KEYstring—Server-side only. Required when DIONYSYS_LLM_PROVIDER=openai
DIONYSYS_OPENAI_MODELstringgpt-4oOpenAI model to use for MCP decision calls
DIONYSYS_OPENAI_TEMPERATUREnumber0.2Sampling temperature (0–2)
DIONYSYS_OPENAI_TIMEOUT_MSnumber15000Request timeout in milliseconds

Gemini connector variables​

VariableTypeDefaultEffect
GEMINI_API_KEYstring—Server-side only. Required when DIONYSYS_LLM_PROVIDER=gemini
DIONYSYS_GEMINI_MODELstringgemini-3.1-flash-liteGemini model to use for MCP decision calls
DIONYSYS_GEMINI_TEMPERATUREnumberprovider defaultSampling temperature

Anthropic connector variables​

VariableTypeDefaultEffect
ANTHROPIC_API_KEYstring—Server-side only. Required when DIONYSYS_LLM_PROVIDER=anthropic
DIONYSYS_ANTHROPIC_MODELstringclaude-3-5-haiku-20241022Anthropic model to use for MCP decision calls
DIONYSYS_ANTHROPIC_TEMPERATUREnumberprovider defaultSampling temperature
DIONYSYS_ANTHROPIC_MAX_TOKENSnumber1024Maximum output tokens for the decision tool call

Custom HTTP connector variables​

VariableTypeDefaultEffect
DIONYSYS_CUSTOM_CONNECTOR_ENDPOINTstring—Required. Full URL of the custom connector endpoint
DIONYSYS_CUSTOM_CONNECTOR_METHODstringPOSTHTTP method
DIONYSYS_CUSTOM_CONNECTOR_BEARER_TOKENstring—Bearer token added to Authorization header
DIONYSYS_CUSTOM_CONNECTOR_HEADERS_JSONstring—JSON-serialized object of additional request headers
DIONYSYS_CUSTOM_CONNECTOR_TIMEOUT_MSnumber15000Request timeout in milliseconds

Security: Never expose OPENAI_API_KEY, GEMINI_API_KEY, ANTHROPIC_API_KEY, or connector credentials to the browser. All connector variables are server-side only.

Connector selection​

Choose a decision connector based on your needs:

Need deterministic scoring only?
└─ Leave DIONYSYS_LLM_PROVIDER=mock (default) — no LLM calls, always returns deterministic output.

Need an OpenAI-powered MCP connector?
└─ DIONYSYS_LLM_PROVIDER=openai + OPENAI_API_KEY + optional DIONYSYS_OPENAI_MODEL

Need a Gemini-powered MCP connector?
└─ DIONYSYS_LLM_PROVIDER=gemini + GEMINI_API_KEY + optional DIONYSYS_GEMINI_MODEL

Need an Anthropic-powered MCP connector?
└─ DIONYSYS_LLM_PROVIDER=anthropic + ANTHROPIC_API_KEY + optional DIONYSYS_ANTHROPIC_MODEL

Need to call your own inference endpoint?
└─ DIONYSYS_LLM_PROVIDER=custom-http + DIONYSYS_CUSTOM_CONNECTOR_ENDPOINT

In code:

import { createDionysysServer } from '@dionysys/server';
import { openAiConnector } from '@dionysys/connector-openai';
import { geminiConnector } from '@dionysys/connector-gemini';
import { anthropicConnector } from '@dionysys/connector-anthropic';
import { mockConnector } from '@dionysys/server'; // built-in

// OpenAI
createDionysysServer({ llmConnector: openAiConnector({ apiKey: process.env.OPENAI_API_KEY }) });

// Gemini
createDionysysServer({ llmConnector: geminiConnector({ apiKey: process.env.GEMINI_API_KEY }) });

// Anthropic
createDionysysServer({ llmConnector: anthropicConnector({ apiKey: process.env.ANTHROPIC_API_KEY }) });

// Mock (deterministic only, no LLM)
createDionysysServer({ llmConnector: mockConnector() });

// Custom HTTP
createDionysysServer({
llmConnector: customHttpConnector({ endpoint: process.env.DIONYSYS_CUSTOM_CONNECTOR_ENDPOINT }),
});

Client configuration​

import { createDionysysClient } from '@dionysys/client';

export const dionysys = createDionysysClient({
apiBaseUrl: 'http://localhost:3001',
session: {
persistence: 'browser', // 'memory' | 'tab' | 'browser'
storageKey: 'dionysys_current_session', // optional, customise the storage key
},
});

persistence options:

ValueStorageLifetime
memoryIn-memoryPage lifetime only
tabsessionStorageTab lifetime
browserlocalStoragePersistent across tabs and refreshes

React provider configuration​

<AdaptiveProvider
client={dionysys}
mode="mcp" // 'deterministic' | 'mcp'
presentationMode="production" // 'prototype' | 'production'
decisionApplication="next-refresh" // 'immediate' | 'next-refresh'
persistenceMode="browser" // 'memory' | 'tab' | 'browser'
sessionId="session_123"
defaultVariant="neutral"
minEventsBeforeLock={5}
pollingIntervalMs={3000}
/>

Key settings:

PropTypeEffect
modedeterministic|mcpDeterministic uses local scoring; MCP calls the connector
presentationModeprototype|productionPrototype shows decision debug UI; production is silent
decisionApplicationimmediate|next-refreshImmediate applies instantly; next-refresh queues until next page load
persistenceModememory|tab|browserWhere the provider stores pending/applied decision state
minEventsBeforeLocknumberMinimum events collected before a decision can lock in
pollingIntervalMsnumberInterval between automatic passive feedback evaluations

Event envelope guidance​

Preferred envelope:

{
type: 'ui.interaction',
subject: 'toolbar.text',
action: 'selected',
payload: { tool: 'text' },
metadata: { source: 'my-app' }
}

Naming conventions:

  • type — required; lowercase dot namespace (e.g. ui.interaction, session.start)
  • subject — recommended; lowercase dot namespace targeting the UI element
  • action — recommended; simple verb (selected, opened, completed)
  • payload — app-specific structured detail; camelCase keys
  • metadata — optional non-decision context; camelCase keys

Admin runtime config​

When ADMIN_CONSOLE_ENABLED=true the backend exposes runtime admin state:

GET /api/dionysys/admin/config Read current config
PUT /api/dionysys/admin/config Update config at runtime
POST /api/dionysys/admin/config/reset Reset to file defaults
GET /api/dionysys/admin/config/export Export as downloadable JSON
GET /api/dionysys/admin/overview Current session overview snapshot
GET /api/dionysys/admin/overview/stream Server-sent events stream

Use the React AdminConsole to edit runtime config in memory. Export a snapshot when you want to promote tuned configuration back into source control.

MCP gate and bandit​

MCP-mode decisions run through a confidence gate and an evidence-weighted bandit blend. Both live under mcp in the admin config, are tunable at runtime in the admin console's Modes tab, and are carried through export/import. All fields default to safe values, so existing configs and the demo work unchanged.

mcp.gate​

FieldTypeDefaultEffect
lockMinEventsnumber2Minimum modality events before the deterministic signal counts as "strong"
lockMarginnumber (0–1)0.15Minimum gap between the top and runner-up modality scores for a "strong" signal

When the signal is strong, deterministic rules decide. When it is weak, the LLM and bandit blend.

mcp.bandit​

FieldTypeDefaultEffect
enabledbooleantrueMaster switch; when false, weak-signal decisions are a pure LLM choice and no bandit reads/updates occur
banditEvidenceKnumber3Observation count at which the bandit and the LLM carry equal weight (wBandit = n / (n + K))
priorAlphanumber1Beta prior alpha for a fresh arm
priorBetanumber1Beta prior beta for a fresh arm
keepRewardnumber (0–1)1Reward applied to the chosen arm on explicit "keep"
revertRewardnumber (0–1)0Reward applied on explicit "revert"
passiveRewardWeightnumber (0–1)0.25Weight of the passive session reward relative to explicit feedback
decayobjectsee belowDiscounted Thompson sampling — pulls arms back toward their priors so the bandit keeps exploring

mcp.bandit.decay​

Without decay, a Beta arm's evidence accumulates forever, so a context that was popular months ago stays locked in even after user behaviour shifts. Decay applies discounted Thompson sampling (Raj & Kalyani 2017; the f-dsw variant, MDPI 2023): each arm is periodically pulled a fraction of the way back toward its prior, which lowers its effective sample size and re-opens exploration.

FieldTypeDefaultEffect
enabledbooleantrueWhen false, arms never forget — the bandit reproduces its pre-decay behaviour exactly (atomic increment)
effectiveWindownumber (>1)200Target effective sample size. The per-step discount is γ = 1 − 1/effectiveWindow, so an arm "remembers" roughly the last effectiveWindow observations

Decay is applied in three scheduler-free places:

  • On update (FeedbackService): before each reward increment the arm is discounted toward its prior, so old evidence fades as new evidence arrives. With enabled: false this falls back to the original atomic incrementBanditParams.
  • On read (DecisionService): at decision time a quiet arm is discounted by γ^(days since last update), in memory only — the stored arm is never mutated by a read.
  • On demand (POST /admin/bandit/decay): a hard, one-shot decay pass over every arm for hosts that prefer periodic maintenance.

See Feedback Loop for how feedback updates the bandit arms, and Admin Console for inspecting and maintaining them.

Bandit inspector & maintenance routes​

The admin API exposes the learned bandit state behind the same authorize hook as the rest of /admin:

Method & pathPurpose
GET /api/dionysys/admin/banditOverview: arms grouped by context, each with posterior mean, a 90% credible interval, observation count, evidence weight, and Monte-Carlo P(best); plus the decay echo and (with ?sessionId=) a decision trace
POST /api/dionysys/admin/bandit/resetReset a single arm ({ stateId, variant }), a whole context ({ stateId }), or every arm ({}) to its prior
GET /api/dionysys/admin/bandit/exportSnapshot the learned arms as JSON
POST /api/dionysys/admin/bandit/importRestore arms from a snapshot ({ arms })
POST /api/dionysys/admin/bandit/decayRun one decay pass over all arms

These are surfaced in the SDK client as client.admin.getBandit / resetBandit / exportBandit / importBandit / decayBandit.