Configuration reference
Every configuration key read by the gateway (and, where noted, the panel host), with defaults where the code sets one. See Configuration & secrets for precedence and secret handling.
#Connections & hosting
| Key | Default | Purpose |
|---|---|---|
ConnectionStrings:GatewayDb | — | Gateway SQL database. Both apps. |
ConnectionStrings:UserManagementDb | — | Identity SQL database. Panel host only (legacy name ApplicationDbContext still accepted). |
Identity:BaseUrl / ClientId / ClientSecret / CallbackPath / Scope | — / — / — / /signin-identity / tenancy.read launcher.read | Panel sign-in through the company identity app. BaseUrl must be https; the host refuses to start without ClientSecret. |
Gateway:PublicBaseUrl | http://localhost:5300 | The gateway's public address — used by the panel's Playground and for workflow resume / webhook URLs. |
Gateway:InternalBaseUrl | falls back to PublicBaseUrl | Address the panel host uses to reach the gateway (Playground proxy) when it differs from the public one. |
Gateway:PanelBaseUrl | http://localhost:5198 | Panel address used in approval-inbox links sent by workflows. |
Cors:PanelOrigins | — | Allowed origins for the gateway's CORS policy (any origin when unset). |
Seed:MockBaseUrl | http://localhost:8899 | Mock provider base URL used by the dev-only --seed mode. |
#Chat & agents
| Key | Default | Purpose |
|---|---|---|
Gateway:DefaultModel | — | Global model used when a request omits model. There is no per-workspace default. |
Gateway:FallbackModel | — | Global fallback, used only when a model declares no fallback chain of its own. Set a per-model fallback in Models → Edit → Fallback model instead — it takes precedence. See Model routing & fallback. |
Gateway:ModelAliases:{requested} | — | Dynamic remap of a requested model name. |
Gateway:ToolMaxIterations | 5 | Max model↔tool round-trips for agents with MCP or workflow tools (and the workflow Agent node). Connector agents use Gateway:Connectors:MaxIterations; dataset agents use Gateway:Data:MaxIterations. |
Gateway:MaxImageBytes | 5242880 | Largest image content part accepted, in decoded bytes per image (5 MB). A larger one is refused with 400 image_too_large. |
#File attachments
| Key | Default | Purpose |
|---|---|---|
Gateway:Files:MaxBytes | 25000000 | Upload size cap (the endpoint also has a fixed 25 MB request limit). |
Gateway:Files:MaxCharacters | 200000 | Extracted text kept per file. |
Gateway:Files:MaxTabularRows | 200 | Rows kept per worksheet or CSV in an attachment (knowledge-base ingest is uncapped). |
Gateway:Files:MaxPerRequest | 10 | Attachments one request may name. |
Gateway:Files:TtlHours | 24 | Hours before an attachment expires. 0 disables expiry. |
#Routing & resilience
| Key | Default | Purpose |
|---|---|---|
Gateway:MaxRetries | 2 | Transient retry count (non-streaming calls). |
Gateway:RetryBaseDelayMs | 250 | Retry backoff base; doubles per attempt. |
Gateway:CatalogCacheSeconds | 10 | In-process model/provider catalog cache TTL; panel edits take effect when it expires. |
Gateway:BudgetRefreshMinutes | 5 | How often workspace and end-user spend is recomputed from telemetry. |
Gateway:EndUserBudgetCacheSeconds | 30 | End-user budget cache on the request path. |
#Response cache
| Key | Default | Purpose |
|---|---|---|
Gateway:Cache:TtlSeconds | 0 (off) | Response-cache TTL for non-streaming chat and embeddings. |
Gateway:Cache:MaxEntries | 5000 | Response-cache size cap (shared with the 24-hour idempotency store). |
#Moderation
| Key | Default | Purpose |
|---|---|---|
Gateway:Moderation:Enabled | false | Turn moderation on (input, and output of non-streamed calls). |
Gateway:Moderation:Block | true | Block flagged content (400 content_flagged) vs. only flag it in a header. |
Gateway:Moderation:FlagJailbreak | true | Detect prompt-injection / jailbreak. |
#RAG
| Key | Default | Purpose |
|---|---|---|
Qdrant:Url | — | Vector store endpoint. Absent → knowledge endpoints return 503 vector_store_unavailable and agent retrieval is skipped. |
Qdrant:ApiKey | — | Vector store key (if required). |
Gateway:Rag:HybridAlpha | 0.5 | Dense vs. lexical blend weight. |
Gateway:Rag:MmrLambda | 0.7 | MMR relevance/diversity tradeoff. |
#Dataset agents (SQL)
Reached by the gateway and, for the editor's picker only, by the panel host. Both hosts should carry the same BaseUrl and ApiKey — a mismatch means the picker lists a different company's datasets than a run resolves. See Dataset agents.
| Key | Default | Purpose |
|---|---|---|
Gateway:Data:BaseUrl | — | Data app base URL. Absolute http/https, no query or fragment; an invalid value fails at startup. In development use https://localhost:7434 — the http port 307-redirects and redirects are not followed. Absent → 503 dataset_backend_unconfigured. |
Gateway:Data:ApiKey | — | Data app API key. A secret — user-secrets / env / Key Vault. Carries the data app's company, so one key = one company for the whole instance. |
Gateway:Data:TimeoutSeconds | 15 | Per-call timeout to the data app. |
Gateway:Data:MaxResponseBytes | 8388608 | Largest data-app response accepted (64 KiB – 64 MiB). |
Gateway:Data:ModelMaxRows | 100 | Rows shown to the model. |
Gateway:Data:CallerMaxRows | 1000 | Rows fetched, i.e. what the caller receives in relay_dataset. Clamped between ModelMaxRows and 1000. |
Gateway:Data:ModelMaxChars | 20000 | Character budget for the row JSON handed to the model. |
Gateway:Data:MaxIterations | 6 | Tool-loop iterations (model calls) per turn, including describe-table calls in index mode; exhausting it on a rejected query fails with 422 sql_execution_failed. |
Gateway:Data:CacheTtlSeconds | 120 | Schema + grant cache TTL per (dataset, user). 0 disables — useful while editing grants. |
Gateway:Data:NegativeCacheSeconds | 30 | How long "not accessible" is remembered, so a wrong id does not hammer the data app. |
Gateway:Data:CacheMaxEntries | 500 | Schema cache size cap. |
Gateway:Data:SchemaMaxChars | 24000 | Prompt budget for the schema block; past it the prompt switches to a table index. |
Gateway:Data:IndexColumnPreview | 8 | Columns previewed per table in index mode. |
Gateway:Data:UserIdHeader | X-Relay-User-Id | Header naming the acting end user. X-User-Id is always accepted as a fallback. Named under Data: because dataset agents introduced it, but it is Relay's single acting-user header — agent sharing, connectors, file ownership and trace attribution read the same one. |
Gateway:Data:CatalogUserId | — | Data-app identity used only to populate the panel's dataset picker. |
Gateway:Data:AllowInvalidCertificates | false | Accept the data app's self-signed dev certificate. Honoured only in Development. |
#Connectors (Microsoft 365)
| Key | Default | Purpose |
|---|---|---|
Connectors:RedirectUri | derived from the request | Panel host. OAuth callback URL override for a reverse proxy that rewrites the host; must match the app registration exactly. |
Gateway:Connectors:MaxIterations | 8 | Tool-loop budget for a connector agent. |
Gateway:Connectors:MaxFileBytes | 8388608 | Largest file microsoft_read_file will download. |
Gateway:Connectors:MaxFileChars | 20000 | Text returned to the model from microsoft_read_file and from a microsoft_get_email body. |
#Workflows
All clamped to sane ranges; a workflow's own settings can tighten but never exceed them. See Workflows.
| Key | Default | Purpose |
|---|---|---|
Gateway:Workflows:PollSeconds | 10 | Engine queue poll interval. |
Gateway:Workflows:NodeConcurrency | 4 | Nodes run in parallel within a wave. |
Gateway:Workflows:MaxNodes | 100 | Nodes per workflow. |
Gateway:Workflows:MaxDepth | 3 | Sub-workflow nesting depth. |
Gateway:Workflows:MaxIterations | 100 | Loop iterations per run; MaxLoggedIterations (50) caps the per-iteration rows kept. |
Gateway:Workflows:MaxStateBytes | 1048576 | Run state size. |
Gateway:Workflows:StepPreviewMaxChars | 4000 | Step input/output preview kept per node. |
Gateway:Workflows:StepRetentionDays | 30 | Default step retention (per-workflow override). |
Gateway:Workflows:StaleRunMinutes | 10 | A claimed run with no heartbeat for this long is requeued. |
Gateway:Workflows:MaxSyncWaitSeconds | 60 | How long ?wait=true, the chat shim and waiting webhooks block. |
Gateway:Workflows:MaxInlineWaitSeconds | 60 (0–600) | A Wait longer than this suspends the run durably; Waits inside a loop body must stay within it. |
Gateway:Workflows:MaxEventStreams | 100 | Concurrent SSE run-event streams. |
Gateway:Workflows:Http:AllowedHosts | (empty) | Hosts HTTP, integration and webhook nodes may reach. Empty disables them. Private, loopback and link-local addresses are always refused. |
Gateway:Workflows:Http:MaxResponseBytes / MaxTimeoutSeconds | 1048576 / 30 | HTTP node response cap and timeout ceiling. |
Gateway:Workflows:Sql:AllowedHosts | (empty) | SQL servers the SQL node may connect to. |
Gateway:Workflows:Sql:TrustServerCertificate | false | Accept a self-signed certificate on SQL node connections. |
Gateway:Workflows:Email:AllowedDomains | (empty) | Recipient domains for Send email. |
Gateway:Workflows:Email:Host / Port / UseSsl / From / User / Password | falls back to Gateway:HealthProbe:Smtp:* | SMTP for Send email. |
Gateway:Workflows:Webhook:RatePerMinute / MaxBodyBytes | 60 / 1048576 | Per-token webhook rate limit and body cap (also applied to resume URLs). |
#Batch & eval processors
| Key | Default | Purpose |
|---|---|---|
Gateway:BatchPollSeconds | 10 | Batch queue poll interval. |
Gateway:BatchConcurrency | 4 (1–32) | Batch row concurrency. |
Gateway:EvalPollSeconds | 10 | Eval queue poll interval. |
Gateway:EvalConcurrency | 4 (1–32) | Eval case concurrency. |
Gateway:EvaluatorPollSeconds / EvaluatorLagSeconds | 60 (min 10) / 30 (min 5) | LLM-judge evaluator cycle, and how far behind "now" it reads so buffered rows are not missed. |
Gateway:AlertRules:IntervalSeconds | 60 (min 15) | Workspace alert-rule evaluation interval. |
#Health probing & alerting
| Key | Default | Purpose |
|---|---|---|
Gateway:HealthProbe:Enabled | false | Actively probe providers (a token-free GET on the base URL). |
Gateway:HealthProbe:IntervalSeconds | 60 | Probe interval. |
Gateway:HealthProbe:TimeoutSeconds | 5 | Probe timeout. |
Gateway:HealthProbe:AlertThreshold | 2 | Consecutive failures before alert. |
Gateway:HealthProbe:WebhookUrl | — | Slack-compatible alert webhook. |
Gateway:HealthProbe:AlertEmail | — | Alert recipient. |
Gateway:HealthProbe:Smtp:Host / Port / UseSsl / From / User / Password | 587 / true | SMTP for email alerts. |
Gateway:Alerts:Enabled | false | Gateway-wide telemetry-threshold alerting (all workspaces; per-workspace rules live in the panel). |
Gateway:Alerts:IntervalSeconds | 300 | Alert evaluation interval. |
Gateway:Alerts:WindowMinutes | 15 | Look-back window. |
Gateway:Alerts:ErrorRatePercent | 10 | Error-rate threshold. |
Gateway:Alerts:P95LatencyMs | 0 (off) | p95 latency threshold. |
#Telemetry & OTLP
| Key | Default | Purpose |
|---|---|---|
ClickHouse:ConnectionString | — | Observability store (read/write). Set on the gateway and the panel. Empty = no telemetry. |
ClickHouse:ObservationTable / ScoreTable | relay_observation / relay_score | Table names (created and evolved at startup). |
ClickHouse:FlushIntervalMs / BatchSize / Capacity | 1000 / 500 / 10000 | Writer batching; events are dropped (never blocking) when the buffer is full. |
ClickHouse:QueryTimeoutSeconds | 30 | Panel/API query timeout. |
ClickHouse:TracesTable / OtelServiceName | otel_traces / relay-gateway | Read side when Telemetry:DashboardSource=otel; the service name must match Gateway:Otlp:ServiceName. |
Telemetry:DashboardSource | clickhouse | otel reads the usage Dashboard and Telemetry pages from the collector's otel_traces table instead of relay_observation. Observations are always written regardless. |
Telemetry:Backend | — | Obsolete, not read. OTLP export is Gateway:Otlp:Enabled; the dashboard source is Telemetry:DashboardSource. |
Telemetry:Capture:Default | metadata | Body capture when a workspace has no setting: none, metadata, full. |
Telemetry:Capture:RedactPii | true | Default PII redaction of captured text. |
Telemetry:Capture:MaxBodyChars | 20000 (256–1,000,000) | Default per-field cap on captured text. |
Telemetry:RetentionDays / BodyRetentionDays | 0 / 30 | Default row and captured-text retention (0 = keep). |
Telemetry:SettingsCacheSeconds | 60 | How long the gateway caches a workspace's observability settings. |
Telemetry:Panel:ShowBodies | true | Panel host. Show captured text in the panel; set false to hide it (metrics still show). |
Gateway:Otlp:Enabled | false | Enable OTLP export (traces + logs + metrics). |
Gateway:Otlp:Endpoint | http://localhost:4318/v1/traces | Traces endpoint (logs/metrics derived). |
Gateway:Otlp:LogsEndpoint / MetricsEndpoint | derived | Override the derived endpoints. |
Gateway:Otlp:ServiceName | relay-gateway | Service name on emitted signals. |
Gateway:Otlp:ApiKey | — | HyperDX ingestion key (Authorization header). |
Gateway:Otlp:MetricsIntervalSeconds | 30 | Metrics export interval. |
OTEL_EXPORTER_OTLP_ENDPOINT | — | Environment variable read by Application.ServiceDefaults: when set, the OpenTelemetry SDK also exports generic ASP.NET Core / HttpClient / runtime telemetry (as relay-api / relay-panel) — a separate pipeline from the hand-written exporter above, used by the Aspire dashboard. |
Streaming usage is always requested from OpenAI-compatible providers (stream_options.include_usage) so streamed calls are costed; this is not configurable.
#Secrets
| Key | Purpose |
|---|---|
Encryption:MasterKey | Base64, 32 bytes. AES-256-GCM key for every at-rest secret (provider keys, Azure discovery secret, connector secrets and tokens, workflow credentials and webhook tokens); also keys the Playground delegation token. Must be identical on Application and Application.Api. |
config[<SecretRef>] | Fallback provider API key, read by name only when the Provider row has no encrypted key stored. |