Skip to main content

Overview

System settings provide access to low-level configuration values organized by category. These settings control database connections, authentication, job processing, infrastructure, and AI model behavior. Navigate to Admin > Administer > System Settings.

Categories

Settings are organized into tabs by category: Each tab shows the number of settings in that category. The tabs follow the category key (Authentication & SSO first, and the tab the page opens on), except that Async Parsing sits right after Jobs Settings.

Viewing Settings

Settings are displayed as key-value pairs with:
  • Setting name
  • Current value (encrypted values are masked)
  • Read-only indicator (for settings that cannot be changed from the UI)

Editing Settings

Settings marked as editable can be modified directly from the admin panel. Read-only settings must be changed through environment variables or the Django admin interface.
Only settings marked “Show in Dashboard” in the Django admin are visible here. If you need to access additional settings, use the Django admin interface or configure them via environment variables.
Changing system settings can affect the behavior of the entire platform. Ensure you understand the impact of a change before saving. Some changes may require a server restart to take effect.
A deploy refreshes FALKOR_PASSWORD, NEO4J_PASSWORD, and RABBITMQ_PASS from the environment. Those services start with the Omnistrate secret, and the app reads the database copy. Other encrypted settings keep the value saved here. seed_config --update-from-env copies every environment value into the database.

Asking the Copilot

The Admin Copilot panel (⌘J / Ctrl+J) sees the settings of the category you have open and the reference below, and can:
  • Explain a setting in plain words — what it controls and what a value means in practice — citing this page. It checks that the admin guide is indexed first; if the index is out of date it says so and offers the re-index rather than answering from memory.
  • Propose a change when you ask (“set it to enforce”, “is this set up right?”) as a card listing setting · current → proposed · reason. Apply stages the value in the page’s form exactly as if you had typed it — it is not saved — and the page’s own Save persists it, with the same validation, confirmations, and permissions as a hand edit.
Encrypted settings are shown to the copilot only as set or not set and can’t be proposed — a person types those. If you can’t save on this page, the copilot explains without proposing.

Settings Reference

Legend: Settings prefixed with 🔒 store encrypted values. Settings marked (Dashboard) are visible in the admin dashboard UI. Settings marked (Client) are accessible to the frontend client application.

LLM Settings

Produced Documents in Chat Context

When a flow writes a document into a conversation, an excerpt of that document is included in the chat’s context as a head start on follow-up questions about it. The two caps bound that excerpt only — they are not the limit of what the assistant can see, because it can also list the documents produced in the conversation, search inside one, and read any part of it on demand (each read is access-checked for the person asking). They still matter, because the excerpt is what the assistant has before it goes looking. PRODUCED_DOC_CONTEXT_CHARS bounds the document text in a single excerpt. PRODUCED_DOC_CONTEXT_TOTAL_CHARS is spent on document text and on the sentences that announce a cut — an excerpt that had to be truncated carries that sentence on top of its own allowance, and the sentence is charged in full against the conversation budget. A conversation full of truncated documents therefore carries less document text than the total alone suggests. The conversation budget is spent newest first, so the document the flow just wrote — the one the user’s next message is almost certainly about — keeps its excerpt, and older documents give way instead. Nothing is dropped quietly: an excerpt that was cut short says so, and a document that got no budget at all is still named in the context as existing, with its body omitted. That announcement is deliberately exempt from PRODUCED_DOC_CONTEXT_TOTAL_CHARS — saying a document exists must not be starved by the budget it is announcing — so the injected text can exceed the total by one short fixed sentence for every document whose body was omitted. A truncation notice is never cut in half either, because half a notice reads as document text: when the leftover budget cannot hold body text plus a whole notice, that document degrades to the omission announcement instead of getting a sliver of body.

Graph Text in Chat Context

Some graph nodes carry prose: the body of a clause or a document, in their text property. When the assistant reads the neighborhood of an entity, that text goes into the context the answer is written from, and every model call of the answer carries it again. Without a bound, one entity with many long clauses could add hundreds of kilobytes. Two limits keep it in check:
  • GRAPH_CONTEXT_TEXT_CHARS cuts the text of each node. A text that was cut ends with …[truncated].
  • GRAPH_CONTEXT_TEXT_TOTAL_CHARS caps the node text of the whole answer. It is spent in the order the entities were found, so the first entities keep their text and the ones after the budget runs out lose it. An entity that lost its text is marked, so the assistant can say the text was left out for size and does not read as absent from the graph.
Both limits cut what the assistant reads, not what the graph stores. If answers about long clauses lack detail, raise them, and expect each model call to cost more. 0 leaves node text out of the context entirely.

Copilot Scheduled Follow-ups

The admin Copilot can schedule a follow-up: a message it receives later in the same conversation, once or on a recurring schedule, and acts on without anyone watching. The thirteen COPILOT_SCHEDULE* settings above bound it. They are on Admin > Administer > System Settings, in the LLM tab.
  • How many and how far. COPILOT_SCHEDULE_MAX_ACTIVE_PER_USER is the number of active follow-ups per person; COPILOT_SCHEDULE_MAX_DAYS_AHEAD how far ahead a one-time one may be set; COPILOT_SCHEDULE_RECURRING_EXPIRY_DAYS when a recurring one stops by itself. A request over a limit is refused and the Copilot names the limit.
  • How often. COPILOT_SCHEDULE_MIN_INTERVAL_MINUTES is the shortest gap between two runs of a recurring follow-up (0 * * * *, every hour, is exactly the default and is allowed; */30 * * * * is not).
  • How many runs. A recurring follow-up also stops by itself after a number of runs that depends on how often it runs. COPILOT_SCHEDULE_MAX_RUNS_HOURLY (3) applies to one that runs every hour or several times a day, COPILOT_SCHEDULE_MAX_RUNS_DAILY (30) to one that runs once a day or less often, and COPILOT_SCHEDULE_MAX_RUNS_SUB_HOURLY (10) to one that runs more than once an hour, which is possible only when COPILOT_SCHEDULE_MIN_INTERVAL_MINUTES is lowered. How often is the shortest gap between two of its runs, so every hour from 09:00 to 17:00 on weekdays counts as hourly. Whichever comes first, the run limit or COPILOT_SCHEDULE_RECURRING_EXPIRY_DAYS, ends the follow-up. Each run limit is 1 to 200; a larger number is lowered to 200. A change applies to follow-ups created after it, and those already running keep the limit they were given: to stop follow-ups from running right away, turn COPILOT_SCHEDULES_ENABLED off.
  • What a run may cost. Each run is a full Copilot turn that reads the whole conversation again on every model call, so COPILOT_SCHEDULE_MAX_TOKENS_PER_RUN counts that (cached input counts in full) and COPILOT_SCHEDULE_MAX_SECONDS_PER_RUN bounds the time. A run that reaches either stops and tells the person. Together with the number of follow-ups and their run limit they decide what scheduling can cost: ten hourly follow-ups make 30 runs in all, three each, and then stop until someone schedules them again. COPILOT_SCHEDULE_MAX_CONCURRENT_RUNS caps the runs in progress on the whole instance, so a crowd of follow-ups due at the same minute starts a few at a time and the rest wait for the next minute.
  • Failures. A failed run is tried again COPILOT_SCHEDULE_MAX_RETRIES times, the first retry after COPILOT_SCHEDULE_RETRY_BACKOFF_SECONDS and each next one after twice as long, then marked failed.
  • The switch. COPILOT_SCHEDULES_ENABLED turns the feature off: no scheduling tool, and nothing is started. Follow-ups that fall due while it is off run once when it is back on.
A change to a limit applies to the Copilot’s next turn within about 30 seconds, and to the scheduler at its next pass, without a restart. A value that cannot be read, or is below its minimum, means the default. Follow-ups are started by the flow runner that runs beside every server, which asks the API server over loopback at ASYNC_PARSE_DISPATCH_URL, so that setting must be right for follow-ups to start.

DB Settings

Graph connectivity uses GRAPH_PROVIDER plus either the Neo4j or FalkorDB connection group. See Graph backend (Neo4j & FalkorDB) for how switching works and when to run a migration.
Older deployments may still list USE_NEO4J, USE_FALKOR, FALKOR_DB_USER, or FALKOR_DB_PASSWORD. Those keys are legacy; GRAPH_PROVIDER with NEO4J_* / FALKOR_* is authoritative for new installs and the dashboard. Prefer aligning configuration with the rows above.

Graph Read Time Limit

A graph read that a person is waiting for carries GRAPH_READ_TIMEOUT_MS: the retrieval behind a chat answer, the tools of an agent flow, the graph evidence shown with an answer, and dashboard widgets and records. Ingestion, enrichment and the other background work are not limited by it, and neither is the rebuild of the schema cache, because a limit there would leave the cache on its last good value. The limit works the same on Neo4j and FalkorDB. When a read passes the limit, the graph server stops it and Experio treats it as “the knowledge graph could not answer”, not as “no data”. A chat answer then says so (see When the Knowledge Graph Cannot Be Queried), and a dashboard widget or record answers The knowledge graph is busy. Try again in a moment. and is not retried automatically. The same applies when the graph is unreachable or a query hits FalkorDB’s per-query memory cap. Experio does not ask the model to rewrite such a query, because a rewrite would meet the same busy graph. A value above 55000 is lowered to 55000, so the graph server stops a query before the client’s own 60-second wait does. If answers report the graph as unavailable while it is healthy, the limit may be too low for the size of your graph.

FalkorDB Aggregate Guard

FalkorDB 6.0.3 answers some grouped aggregations wrongly and can crash on others (upstream FalkorDB issues 3375 and 3150). A grouped aggregation puts grouping columns next to aggregate functions, for example RETURN p.name, p.stage, p.code, count(i), sum(i.total). When a grouping column is computed in that same RETURN or WITH and sits after the variables in scope, a number can come back wrong (a sum that equals the row count, say), or the graph server can restart. That is the case when there are more grouping columns than variables in scope, and also when a grouping column is listed after an aggregate. With FALKORDB_AGGREGATE_GUARD on, the default, Experio refuses a query of that shape before it reaches FalkorDB, and explains how to write it: compute each grouping column in a WITH that also carries the variables the aggregates read, list the grouping columns first, then the aggregates. In chat, the model reads the explanation and rewrites the query. A dashboard widget shows an error that asks for the widget to be regenerated, or for its query to be edited the same way. Experio also refuses an aggregating query that names a variable or alias when, then, else, starts, ends, csv or on, because each of these is also a Cypher keyword and a query that uses one as a name can be misread and answered wrongly. The refusal asks for the variable to be renamed. In chat, the model renames it and runs the query again. Nothing is rewritten behind your back, and a query of any other shape runs as before. Turn the guard off only after FalkorDB is moved to a release that contains the upstream fixes. A change applies within 30 seconds. The setting has no effect on Neo4j.

AUTH Settings

Login Methods

ALLOW_PASSWORD_LOGIN, ALLOW_MAGIC_LINK_LOGIN, and ALLOW_SELF_REGISTRATION control which authentication paths the public login/register pages expose. They compose with USE_PROPELAUTH and ALLOW_HYBRID_LOGIN:
  • For SSO-only tenants, set ALLOW_PASSWORD_LOGIN=False, ALLOW_MAGIC_LINK_LOGIN=False, ALLOW_SELF_REGISTRATION=False, USE_PROPELAUTH=True, and ALLOW_HYBRID_LOGIN=False.
  • Magic-link login requires a working email provider (see Transactional Email below). The link is valid for MAGIC_LINK_TOKEN_TTL_MINUTES minutes.

Transactional Email Deliverability

The AZURE_ECS_SENDER_ADDRESS, AUTH_FROM_DISPLAY_NAME, and AUTH_REPLY_TO_ADDRESS settings together control how outbound auth emails appear to recipients and to mailbox spam filters:
  • The From: line is rendered as "<AUTH_FROM_DISPLAY_NAME>" <AZURE_ECS_SENDER_ADDRESS> (e.g. "Experio" <login@experiolabs.ai>).
  • A Reply-To header points at AUTH_REPLY_TO_ADDRESS so replies land in a monitored inbox instead of bouncing off the no-reply sender.
  • Every send also sets Message-ID (with the sender’s host), Date, and Auto-Submitted: auto-generated, and ships a real plain-text alternative alongside the HTML body — these reduce the chance of the message landing in junk.
  • AZURE_ECS_SENDER_ADDRESS must be a verified MailFrom on the Azure ECS linked domain. Update it (and the corresponding domain verification) if you re-brand the sender.

SSO / PropelAuth

USE_PROPELAUTH, SSO_BACKEND, PROPELAUTH_SSO_USERS_ACTIVE_BY_DEFAULT, and ALLOW_HYBRID_LOGIN work together to enable enterprise Single Sign-On with either backend. USE_PROPELAUTH turns SSO on for both backends despite its name. PROPELAUTH_API_KEY and PROPELAUTH_AUTH_URL are used only when SSO_BACKEND is propelauth. See the SSO Configuration page for complete setup instructions, identity provider guides, and troubleshooting.

Google Workspace Integration

The GOOGLE_MCP_CLIENT_ID and GOOGLE_MCP_CLIENT_SECRET settings enable per-user Google Workspace MCP integration. See the Integrations page for setup instructions.

Slack Notifications

Users can receive flow run notifications (completed, failed, needs review) as Slack direct messages. This is off until you set SLACK_NOTIFICATIONS_BOT_TOKEN; the Slack column then appears in each user’s notification settings. See Notifications for what users see. To get a token:
  1. In your Slack workspace’s app configuration at api.slack.com, open your Slack app (or create one) and add a bot user.
  2. Under OAuth & Permissions, add these bot token scopes: chat:write, im:write, users:read, and users:read.email.
  3. Under App Home, turn on the Messages tab, so the app can send direct messages.
  4. Install (or reinstall) the app to the workspace.
  5. Copy the Bot User OAuth Token, which starts with xoxb-.
  6. In System Settings, paste it into SLACK_NOTIFICATIONS_BOT_TOKEN and save.
The token is stored encrypted and is never shown again in full. Select Clear value under the field to turn Slack notifications off. Users who saved a Slack choice keep it, and it applies again when a token is set. Experio sends each message to the Slack member linked to the user’s Slack integration, or else the member whose email matches the user’s Experio email. Notifications contain only the flow name, what happened, and a link.

Email Notifications

Email notifications use the same email provider as other transactional email (EMAIL_PROVIDER, see above). Without a configured provider, notifications still appear in the bell, but no email is sent.

CORE Settings

Persona feature flags

PERSONAS_ENABLED and REQUIRED_PERSONAS ship off so existing tenants are unaffected until you opt in. See Personas for the behavior matrix, admin workflow, and deploy checklist.
  • PERSONAS_ENABLED — Off hides persona gate, profile picker, and composer toggle; the agent does not inject identity or run persona graph nodes. Admin Settings > Personas stays available for seeding.
  • REQUIRED_PERSONAS — On (with master on) blocks the app until the user picks a persona. Seed active personas and gating forms before enabling.

Chat Turn Limits and the Ingestion Notice

Turn deadline. A chat answer used to have no time limit: a slow model provider could leave an answer waiting for many minutes while it held database connections. CHAT_TURN_DEADLINE_S now stops an answer whose agent run passes it. The user is told This answer took longer than the time limit, so I stopped it. Please ask again in a moment., and that message is saved in the conversation as the answer. Keep the limit under 300 seconds, the database’s idle session limit on Experio deployments: the database closes the connection that holds the answer’s state after 300 idle seconds, so a longer answer fails when it is saved anyway. Answers started with the Deep Research toggle are not limited. Work after the answer. Once an answer is complete, Experio prepares the suggested follow-up questions, the filter suggestions and, in a new conversation, the title. CHAT_POST_ANSWER_TIMEOUT_S bounds that work. Whatever is not ready in time is skipped, because the user already has the answer; a new conversation can then keep the title New Chat. Ingestion notice. While files are ingested, the graph can answer more slowly. With CHAT_INGESTION_NOTICE on, an answer that starts during ingestion shows a Data update in progress step with the sentence New data is being added right now, so answers may take longer than usual. Ingestion counts as running when any of these is true:
  • a file is in a download, parse, classify or ingest stage and was updated within the last 15 minutes;
  • a structured-data scan started within the last 12 hours is still running;
  • an enrichment job started within the last 12 hours is still running.
The time bounds keep a stuck record from showing the note for ever. The notice ships off because users see it. Whether ingestion is running is remembered for 30 seconds per server process. All three settings apply within about 30 seconds of a change, without a restart.

Source document preview

With CHAT_SOURCE_DOCUMENT_PREVIEW off, a source document in chat opens its original link. With it on, the same click opens the parsed text stored for that document, and the viewer still offers the original link. The setting ships off. A change applies the next time the page is loaded. While graph clearance is enforced, that preview is available only after the Document label is scoped. Until an admin scopes it, every preview is the same result as a missing document, including for a person who can otherwise open the original link. A superuser whose graph bypass is on can still open the parsed text.

JOBS Settings

Business-Hours Hold for Scheduled Flows

A flow that re-scans and re-ingests your data writes to the knowledge graph for as long as it runs, and the graph answers other questions more slowly meanwhile. The usual answer is to schedule such flows for your night. As a guard for the day, you can set a business-hours window: while it is open, scheduled flows do not start.
  • INGESTION_PEAK_HOURS is the window, HH:MM-HH:MM in 24-hour time, from the start (included) to the end (excluded). A window that ends before it starts crosses midnight (22:00-06:00). Empty, or a start equal to the end, turns the hold off, and that is how it ships.
  • INGESTION_PEAK_TIMEZONE is the IANA name of the time zone the window is written in. It is UTC until you change it, so set it together with the hours.
  • INGESTION_PEAK_DAYS lists the weekdays the window applies on. The local date in that time zone decides. With 22:00-06:00 on mon,tue,wed,thu,fri, Friday night is held until midnight but its Saturday part is not, and Monday’s early morning is held although the night began on a Sunday.
The hold only delays. A flow that falls due inside the window keeps its due time, starts once on the first runner pass after the window closes, and is then scheduled as usual. Run Now and a run already in progress are never held. While flows are held, the flow runner’s log says how many and until when, at most every 15 minutes. A value that cannot be read (for example 8-18, an unknown time zone or an unknown weekday) turns the hold off and writes one warning to the log for that value, so a typo cannot stop the flow runner. If scheduled flows keep starting inside your business hours, look for that warning.

Async Parsing Settings

The ASYNC_PARSE_* rows above configure async document parsing: how long a file may wait, how often a person may queue files, what the parser may use to read one file, and how Agent Flows wait for it. They are on Admin > Administer > System Settings, in the Async Parsing tab (right after Jobs Settings), where each one can be edited. They are also Configuration Settings in the Django admin (/staff/), in their own ASYNC_PARSE category (Async Parsing) rather than JOBS. The UPLOAD_EXTRACTION_* and COPILOT_ATTACHMENT_OCR_* rows, which stay in JOBS, are not listed on the page: they are edited in the Django admin only. The rows are seeded with the defaults shown, and a value you save is kept. A database that holds them from an earlier version, under JOBS and hidden from this page, has them moved to ASYNC_PARSE and shown by the next seed_config run (a deploy runs it), with the values it saved. For a number, a value that cannot be read, or that is below the setting’s minimum, means the default. The minimum is 1, except where a row says 0 is allowed (ASYNC_PARSE_OCR_ASK_ABOVE_PAGES, ASYNC_PARSE_MAX_EMBED_CHUNKS, ASYNC_PARSE_PRECHECK_MAX_FILE_MB, ASYNC_PARSE_PRECHECK_MAX_SPREADSHEET_MB and ASYNC_PARSE_INLINE_TEXT_EMBED_MAX_CHARS) and 30 for ASYNC_PARSE_EMBED_BUDGET_SECONDS.

INFRA Settings

FEATURE_FLAGS Settings

Enter the policy before switching GRAPH_AUTHORIZATION_MODE to enforce. A label with no baseline row is treated as private, so on a deployment where the policy has not been entered yet, enforce makes the knowledge graph invisible to everyone. Use shadow first: it works out and records the same decision while still answering from the unfiltered query, so you can see what would change before anything does.
GRAPH_AUTHZ_SUPERUSER_BYPASS is one switch for all superusers, not a per-account setting. Turning it on means every superuser reads the graph unfiltered, immediately, with no further step. It exists so a tester or the customer’s own IT owner can check the whole graph; it is not a way to give one person more access.It has no effect unless the mode is enforce, and a bypassed read still works out the decision it is ignoring and records it, so the audit trail survives. Anyone whose session is bypassing sees a banner saying so — see What the AI can see.

Environment Settings

A few settings are read from the server’s environment when a process starts, not from a row in the tables above. The database timeouts have to be known before the first database connection opens, and a System Settings row can only be read through a connection that already works. These settings are not shown on this page, and a change takes effect when the process restarts. Of the variables below, two are exposed as Omnistrate deployment parameters: GRAPH_EXECUTOR_THREADS (graphExecutorThreads, see FalkorDB deployment parameters) and DB_POOL_MAX_SIZE (Database Pool Size per Process, dbPoolMaxSize, see Service scaling). The others keep their default unless the server’s environment sets them. The three database timeouts and the connection pool apply to the web server process only, because only there can one slow call hold up every connected user. The job runners, the document-reading worker and management commands such as migrate get no timeout and no pool, so a migration is never cut short by a lock wait. With several server processes in a pod (see Service scaling) each process has its own pool, so the most connections the web server can hold is the number of pods times the number of processes times DB_POOL_MAX_SIZE, in addition to the chat agent’s own connections. Every process tags its database connections with an application_name of experio-web, experio-worker, experio-job or experio-other, so pg_stat_activity shows which kind of process owns a connection. The connections the chat agent opens for its checkpoints and its memory store are tagged experio-langgraph and use the connect timeout of the process that opens them.