Skip to content

Configuring the workspace ​

This page documents the seven Administration screens that configure tenant-wide behavior: System Settings, Branding, Platform dictionary, Notification templates, API rate limits, Read replica routing and Chat flows. For the permission summary and conventions see Administration and DevOps overview.

System Settings ​

System Settings holds tenant-wide developer toggles. In this release it contains one switch: whether login (session) enforcement is applied to pages that require authentication. It is intended for faster development, for example opening a page in a second browser tab without signing in again. Tenant administrators and developers use it.

Where to find it: Workspace > Administration > System Settings. Page key system-settings.

Key concepts ​

TermMeaning
Session checkThe enforcement that a page marked "Authenticated" requires a valid session. When off, login enforcement is skipped.
Tenant defaultThe value stored on the tenant record (session_check_enabled, default on). Every Application inherits it unless the Application overrides it in its own Details tab in Applications.

Fields and options ​

Section Authentication:

FieldType or allowed valuesDefaultRequiredDescription
Session check (all users, this tenant)SwitchOnNoOff skips login enforcement tenant-wide, for every "Authenticated" page whose own Application has not overridden the setting. The screen warns: for faster development only, never leave off in production.

Actions ​

ActionEffectAPI
Toggle the switchSaves immediately, reloads the tenant record and shows "Saved." The switch is disabled while savingPUT /api/v1/branding/tenant-settings with {"sessionCheckEnabled": false}
HomeReturns to the Studio homenone

Procedures ​

  1. Open System Settings.
  2. Turn Session check (all users, this tenant) off. The banner "Saved." appears.
  3. Open an Authenticated page in a new tab; it loads without a login prompt.
  4. Turn the switch on again before the tenant goes live.

Permissions ​

Reading is open. Writing requires branding:tenant-settings / update; without it the server answers 403 and the screen shows the error. The request names only sessionCheckEnabled, so it cannot overwrite branding values (absent fields are left untouched).

API and CLI ​

bash
erp api get /api/v1/branding/tenant-settings
erp api put /api/v1/branding/tenant-settings --body '{"sessionCheckEnabled":true}'

Limits and behavior ​

  • The same endpoint serves Branding and System Settings; a field set to null or omitted is not changed, an empty string clears a text override.
  • The effective value read by the runtime is returned by GET /api/v1/branding/effective as sessionCheckEnabled (true when the tenant record is missing).

Errors and troubleshooting ​

Message or symptomCauseFix
Error banner with an HTTP 403 textMissing branding:tenant-settings / updateGrant the permission
Authenticated page still asks for loginThe page's Application overrides the settingChange the override in the Application's Details tab

Branding ​

Branding sets this tenant's white-label identity: brand name, company font, logo images, and the color palette applied to the tenant's apps. An empty value means "use the platform default". Tenant administrators use it.

Where to find it: Workspace > Administration > Branding. Page key branding. For design-time themes see Themes.

Key concepts ​

TermMeaning
Stored tierThe raw values saved on the tenant record. The screen always edits this tier, never the blended result.
Effective brandingThe stored value, or the platform default where the stored value is empty. Served by GET /api/v1/branding/effective.
ClearAn empty string sent on save removes an override (stored as null).

Fields and options ​

Identity:

FieldTypeDefaultRequiredDescription
Brand nameText (placeholder "ERP Studio")Platform default ERP StudioNoName shown in the product chrome
Company fontText (placeholder "Inter")noneNoFont family name

Color fields (text, placeholder #2563EB; a color swatch preview is shown). No format validation is applied by the server; use #RRGGBB.

GroupFieldPlatform default
Brand colorsPrimary#2563EB
Secondary#06B6D4
Accent#14B8A6
Semantic colorsSuccess#22C55E
Warning#F59E0B
Danger#EF4444
Info#3B82F6
Surface & textBackground#E7ECF3
Surface#FFFFFF
Border#E5E7EB
Text primary#111827
Text secondary#6B7280
Interaction & chromeFooter#F1F5F9
Divider#E5E7EB
Placeholder#9CA3AF
Disabled#D1D5DB
Link#2563EB
Selection#BFDBFE
Focus#2563EB
Hover#F3F4F6
ChromeHeader (top bar)none (theme decides)
Sidebarnone (theme decides)

Images (each row shows a preview, the current URL or a hint, and the buttons Upload or Replace, and Clear when set):

FieldHint shownDescription
Logo"Shown in the top bar and login screen."Primary logo
Logo (dark mode)"Used in place of Logo when dark mode is active."Dark variant
Favicon"Browser tab icon."Tab icon
Login background"Full-bleed image behind the login form."Login page background

The upload control accepts image files. The file is uploaded to the tenant's asset store immediately and its URL is placed in the field; the value is persisted only when you select Save Branding. The asset endpoint accepts PNG, JPEG, WebP, GIF and SVG (and several document types) up to 25 MB.

Actions ​

ActionEffectAPI
Upload / ReplaceUploads the file and fills the URL fieldPOST /api/v1/assets (multipart file)
ClearEmpties the image field (applied on save)none until Save
Save BrandingSends all fields (blank = clear) and reloads. Banner "Branding saved."PUT /api/v1/branding/tenant-settings
HomeReturns to the Studio homenone

Procedures ​

Apply a corporate palette:

  1. Open Branding. Enter Brand name Northwind Traders, Company font Inter.
  2. Under Brand colors set Primary #0B5FFF, Secondary #00A3A3, Accent #FF7A00.
  3. Under Images select Upload for Logo and choose northwind-logo.png; the row shows the asset URL.
  4. Select Save Branding. The banner "Branding saved." appears and the swatches reflect the saved values.
  5. To return the Accent color to the platform default, empty the field and save again.

Permissions ​

Reading the stored tier is open. Saving requires branding:tenant-settings / update; otherwise HTTP 403.

API and CLI ​

bash
erp api get /api/v1/branding/effective
erp api put /api/v1/branding/tenant-settings --body '{"brandName":"Northwind Traders","primaryColor":"#0B5FFF","accentColor":""}'

Limits and behavior ​

  • Fields omitted or null in the request are left unchanged; an empty string clears. The Studio screen always sends every field, so a Save from this screen rewrites all of them with what is shown.
  • The tenant tier only overrides platform defaults; an application theme can still apply on top at design time (see Themes).

Errors and troubleshooting ​

Message or symptomCauseFix
Unsupported content type: xThe asset type is not allowedUse PNG, JPEG, WebP, GIF or SVG
file is requiredEmpty uploadChoose a file
Color does not changeValue not saved, or an application theme overrides the areaSave and check the Application's theme
Error 403 on saveMissing branding:tenant-settings / updateGrant the permission

Platform dictionary ​

Platform dictionary lets a tenant search the platform's own terminology and customize the wording its users see, without changing the platform default. Only keys that a platform administrator has published to the catalog and marked overridable can be customized. Tenant administrators and localization owners use it.

Where to find it: Workspace > Administration > Platform dictionary. Page key platform-dictionary.

Key concepts ​

TermMeaning
Catalog entryA translation key published for tenants: key, module, description, tags, default value per language and an Overridable flag.
Customer layerThe tenant's own value for a key and language. It takes precedence over the plugin and system layers.
CustomizedThe tenant has a value saved for this key and language.

Fields and options ​

Toolbar:

FieldType or valuesDefaultRequiredDescription
LanguageSelect of languages as "Label (code)"First language of the catalogYesLanguage being browsed and edited
SearchText (placeholder "key, description, module, or tag")emptyNoCase-insensitive contains over key, description, module and tags

Entry card:

ElementDescription
Module chipThe owning module
Customized chip (green)A tenant value exists
Not overridable chip (lock icon)The key may not be customized; the text field is disabled
KeyThe translation key in monospace
Tag chipsSearch tags
DescriptionExplains where the term appears
Value fieldPre-filled with the tenant value, else the platform default; placeholder is the default or "(no platform default yet)"; helper text "Platform default: ..."
SaveEnabled only when the value differs from the current one and the key is overridable
Revert icon (title "Revert to platform default")Shown for customized entries; removes the tenant value

Empty states: "Nothing has been published to the catalog yet - ask your platform administrator to publish keys from Translation Keys & Values." when the catalog is empty, and "No matching entries." when the search finds nothing.

Actions ​

ActionEffectAPI
SaveStores the tenant value for the key and languagePUT /api/v1/authoring/platform-dictionary/{keyId} with {"languageCode":"fr","value":"..."}
RevertDeletes the tenant value; resolution falls back to plugin and system layersDELETE /api/v1/authoring/platform-dictionary/{keyId} with {"languageCode":"fr"}
Language changeReloads the catalog for that languageGET /api/v1/authoring/platform-dictionary?languageCode=fr

Procedures ​

Rename "Employee" to "Associate" for English users:

  1. Open Platform dictionary, choose Language English (en) and search employee.
  2. On the entry whose key is hcm.employee.title (an example key), replace the value with Associate and select Save. The Customized chip appears.
  3. To undo, select the revert icon; the value returns to the platform default.

Permissions ​

Browsing is open. Save and Revert require the EDIT_TRANSLATIONS capability on translation for the actor.

API and CLI ​

bash
erp api get "/api/v1/authoring/platform-dictionary?languageCode=en"
erp api put /api/v1/authoring/platform-dictionary/412 --body '{"languageCode":"en","value":"Associate"}'

Limits and behavior ​

  • The catalog only lists keys that are public and overridable; the full internal key registry is visible to platform staff only.
  • A customization is tenant-scoped and keyed by the key string, so it applies wherever that key is resolved.
  • Deleting a customization that does not exist is not an error.

Errors and troubleshooting ​

Message or symptomCauseFix
Unknown language code: xxLanguage not definedPick a language from the list
Translation key 'k' is not open for tenant overrideKey not public or not overridableAsk the platform administrator to publish it as overridable
Unknown platform-wide translation key id NStale IDReload the screen
Save disabledKey not overridable, or the value is unchangedEdit the value

Notification templates ​

Notification templates customizes the subject and body of the system notifications the platform sends (welcome e-mail, password reset, security alerts, document workflow notices). Each event has a built-in English text and, for most events, built-in translations. A tenant may override any of them, per language. Administrators and brand owners use it.

Where to find it: Workspace > Administration > Notification templates. Page key notification-templates.

Key concepts ​

TermMeaning
Event typeA notification the platform sends, for example WELCOME_EMAIL.
LocaleA language tag such as hi or pt-BR. The empty locale is the tenant's locale-agnostic default.
OverrideThe tenant's own subject and body for an event and locale (notification_template, one row per tenant, event type and locale).
Merge tagA placeholder in double braces, replaced with real values when the notice is sent.

Resolution order at send time: the recipient's locale override; then the tenant's locale-agnostic override; then the built-in translation for the language (matched by the language subtag, so hi-IN uses hi); then the built-in English text.

Built-in translations exist for ar, de, es, fr, hi, ja, pt, ru and zh. PASSWORD_RESET_REQUESTED has an English built-in only.

Fields and options ​

Event list (left):

EventLabelMerge tags
WELCOME_EMAILWelcome Emailusername
PASSWORD_RESETPassword Reset (confirmation)username
PASSWORD_RESET_REQUESTEDPassword Reset Requestedusername, resetLink
ACCOUNT_LOCKEDAccount Lockedusername
PASSWORD_EXPIRY_REMINDERPassword Expiry Reminderusername
LOGIN_ALERTLogin Alertusername, device, ipAddress
NEW_DEVICE_ALERTNew Device Alertusername, device, ipAddress
OTP_LOGINOTP Login Codeusername, code
DOCUMENT_CREATEDDocument CreatedownerId, title, documentNumber
DOCUMENT_APPROVAL_PENDINGDocument Approval PendingownerId, title, documentNumber
DOCUMENT_APPROVEDDocument ApprovedownerId, title, documentNumber
DOCUMENT_REJECTEDDocument RejectedownerId, title, documentNumber
DOCUMENT_EXPIREDDocument ExpiredownerId, title, documentNumber

A "customized" chip marks events that have a locale-agnostic override. The API enumeration contains further event types (TENANT_PROVISIONING_COMPLETED, TENANT_PROVISIONING_FAILED, ACCOUNT_ACTIVATED, ACCOUNT_DEACTIVATED, ACCOUNT_UNLOCKED, ROLE_CHANGED) that this screen does not list.

Editor:

FieldType or valuesDefaultRequiredDescription
Locale select"Locale-agnostic default", or a built-in language with the suffix "(built-in translation available)"Locale-agnostic defaultNoWhich variant is being edited
Or a custom locale tagText, placeholder "e.g. pt-BR"emptyNoAny other locale tag; stored as typed
SubjectTextThe override, else the built-in defaultYes in practiceSubject line
BodyMulti-line textThe override, else the built-in defaultYes in practiceMessage body; line breaks are kept
Merge tagsChipsnoneNoSelecting a chip appends the tag to the Body
Origin chip"Tenant override" or "Platform default"derivedn/aShows whether an override exists for the selected event and locale

Preview panel: shows the subject and body with each known merge tag displayed as the tag name between guillemets, for example the username tag appears as the word "username" in guillemets.

The built-in English text of Welcome Email, as an example of tag syntax:

text
Subject: Welcome to ERP, {{username}}
Body:    Hi {{username}},

         Your account has been created. You can now sign in with your username or email.

         - ERP

Actions ​

ActionEffectAPI
SaveCreates or updates the override for the selected event and locale. Banner "Saved."PUT /api/v1/notification-templates with {"eventType":"WELCOME_EMAIL","locale":null,"subject":"...","body":"..."}
Reset to DefaultDeletes the override (enabled only when one exists). Banner "Saved."DELETE /api/v1/notification-templates?eventType=WELCOME_EMAIL&locale=
Load defaults and overridesDone on openGET /api/v1/notification-templates/defaults, GET /api/v1/notification-templates?pageIndex=0&pageSize=500, GET /api/v1/notification-templates/defaults/{eventType}/locales

Procedures ​

Customize the welcome e-mail in Hindi:

  1. Select Welcome Email. In the locale select choose hi (built-in translation available). The editor shows the built-in Hindi text with the chip "Platform default".
  2. Change the greeting in Body, keeping the tag for the user name. Use the username chip to insert it.
  3. Select Save. The chip becomes "Tenant override".
  4. To go back to the platform text, select Reset to Default.

Permissions ​

Reading defaults and overrides is open. Save and Reset require the AUTHOR capability on artifact type notification-template; otherwise the request is denied with a message of the form Actor "x" lacks AUTHOR on notification-template for tenant T.

API and CLI ​

bash
erp api get "/api/v1/notification-templates?pageIndex=0&pageSize=500"
erp api put /api/v1/notification-templates --body '{"eventType":"OTP_LOGIN","locale":"","subject":"Your sign-in code","body":"Your code is 123456"}'
erp api delete "/api/v1/notification-templates?eventType=OTP_LOGIN"

Limits and behavior ​

  • Substitution is a plain text replacement of the double-brace tag with the value supplied by the sender; a tag with no supplied value is left as written, and a null value becomes empty text.
  • Delivery uses the configured channel. By default (platform.notification.email.enabled=false) messages are written to the server log instead of being e-mailed; with platform.notification.email.enabled=true and a configured mail sender they are sent from platform.notification.email.from (default no-reply@erp.local). A failed send is logged and never fails the business action that triggered it.
  • An empty recipient address skips the notification silently.

Errors and troubleshooting ​

Message or symptomCauseFix
Reset to Default disabledNo override for this event and localeNothing to reset
Override not used for a userThe user's locale differs from the one editedCreate the locale variant, or edit the locale-agnostic default
Tag shows literally in the e-mailThe tag is not one the event supplies, or is misspelledUse the merge-tag chips

API rate limits ​

API rate limits overrides the platform-wide request ceiling for this tenant. The ceiling counts every call to /api/v1/** that carries the tenant header within the current one-minute window. Other tenants are unaffected. Tenant administrators use it to protect a tenant from runaway integrations or to give a busy tenant more headroom.

Where to find it: Workspace > Administration > API rate limits. Page key rate-limit-settings; the screen title reads "API Rate Limits".

Key concepts ​

TermMeaning
Platform defaultThe platform-wide ceiling, 1200 requests per minute by default. Set by the operator.
Platform switchAn operator setting, off by default. While it is false the tenant ceiling is not enforced for any tenant, whatever the tenant override says.
Tenant overrideThis tenant's own switch and limit per minute.

Fields and options ​

Section Override:

FieldTypeDefaultRequiredDescription
Use this tenant's own limit instead of the platform defaultSwitchOff (no override saved)NoOn applies the tenant value; off falls back to the platform default while keeping the saved row. A caption states "This tenant currently has a saved override row." or "This tenant has no override saved yet - it is using the platform default below."

Section Ceiling:

FieldTypeDefaultRequiredDescription
Requests per minute for this tenantNumberThe platform default (shown in the helper text "Platform default: N/minute. Used automatically when the override switch above is off.")Yes when the override is onDisabled while the override switch is off. Must be greater than 0

Actions ​

ActionEffectAPI
Save Rate Limit PolicyValidates, saves, banner "Rate-limit policy saved."PUT /api/v1/authoring/rate-limit/tenant-policy with {"enabled":true,"limitPerMinute":600}
LoadOn openGET /api/v1/authoring/rate-limit/tenant-policy

Validation message on the screen: "Limit per minute must be a positive number." The server answers 400 for a limit of 0 or less.

Procedures ​

  1. Open API rate limits. The caption reads that no override is saved and the field shows 1200.
  2. Turn the switch on and enter 600.
  3. Select Save Rate Limit Policy. The caption now states that an override row exists.
  4. When the tenant exceeds 600 requests in a minute, further calls receive HTTP 429 until the next minute starts.

Statuses and lifecycle ​

StateReads back as
No rowenabled: false, limitPerMinute = platform default, hasOverride: false
Row with enabled: falseThe platform default applies; the saved value is kept
Row with enabled: trueThe tenant value applies

Permissions ​

Reading is open (it never returns 404). Saving requires rate-limit:tenant-policy / update; otherwise HTTP 403.

API and CLI ​

bash
erp api get /api/v1/authoring/rate-limit/tenant-policy
erp api put /api/v1/authoring/rate-limit/tenant-policy --body '{"enabled":true,"limitPerMinute":600}'

Response:

json
{ "tenantId": 7, "enabled": true, "limitPerMinute": 600, "globalDefaultLimitPerMinute": 1200, "hasOverride": true }

Limits and behavior ​

  • The window is a fixed calendar minute (UTC, truncated to the minute); the counter is stored per tenant and window in api_rate_limit_window and shared by all server instances.
  • Only requests whose path starts with /api/v1/ and which carry a numeric X-Tenant-Id are counted.
  • The rejection body is {"code":"api-rate-limit-exceeded","message":"tenant 7 exceeded its 600/minute ceiling"} with status 429.
  • This ceiling is separate from per-rule limits attached to API access rules, which are enforced per actor and answer 429 with Actor "x" exceeded the N/minute rate limit for PATH.

Errors and troubleshooting ​

Message or symptomCauseFix
"Limit per minute must be a positive number."Empty, zero or negative inputEnter a whole number above 0
429 api-rate-limit-exceededCeiling reachedWait for the next minute, reduce call volume, or raise the ceiling
Saved limit has no effectThe platform switch enabled is falseAsk the operator to switch the platform ceiling on
403 on saveMissing rate-limit:tenant-policy / updateGrant the permission

Read replica routing ​

Read replica routing controls whether this tenant's eligible reads may be served by a healthy read replica instead of the primary database, and how a replica is chosen. A second block, Operational Config, tunes the health monitor and connection pools for the whole replica pool. Tenant administrators use the first block; platform operators use the second.

Where to find it: Workspace > Administration > Read replica routing. Page key read-replica-settings; the screen title reads "Read Replica Routing".

Key concepts ​

TermMeaning
PrimaryThe writable database. Writes, reads inside the read-after-write window (default 2 seconds after a write) and reads that explicitly require the primary always go to the primary, whatever this screen says.
Replica stateSTARTING, HEALTHY, DEGRADED, LAGGING, UNAVAILABLE, DRAINING. Only HEALTHY replicas receive normal read traffic.
Feature switchAn operator setting. When off the module does not load: the tenant-policy endpoints answer 503 and the operational-config endpoints do not exist (404).
Platform defaultAn operator setting, off by default. A tenant is routed to replicas only when its own setting is On, or Inherit with the platform default on.
Load balancingSet by the operator, health and latency weighted by default. Not editable on this screen.

Fields and options ​

Tenant policy, section Enablement:

FieldType or valuesDefaultRequiredDescription
Enabled for this tenantSelect: "Inherit platform default" (null), "On - route eligible reads to a replica" (true), "Off - always route to primary" (false)InheritNoAn explicit On or Off always wins for this tenant

Section Routing:

FieldType or valuesDefaultRequiredDescription
Read policySelectLocal replicaNoSee the next table
Home regionTextdefaultNoMatched against each replica's region for the Local replica policy. Single-region deployments leave it as default

Read policies:

ValueLabelBehavior
LOCAL_REPLICALocal replicaPrefer a healthy replica in this tenant's home region, then any region, then the primary
ANY_REPLICAAny replicaPrefer any healthy replica regardless of region, then the primary
PRIMARY_ONLYPrimary onlyNever route this tenant's reads to a replica

Operational Config (platform-wide, applied to every tenant, effective without a restart):

FieldTypeDefault (seeded from application.yml)MinimumDescription
Health-check interval (seconds)Integer51How often each replica is polled for connectivity and lag
Failure thresholdInteger31Consecutive failed pings before a replica is marked UNAVAILABLE rather than DEGRADED
Max replica lag (seconds)Integer50A replica lagging beyond this is demoted to LAGGING and leaves the eligible pool
Per-tenant max pool sizeInteger31Maximum pool size of each (replica, tenant) connection pool; applied live to pools already open

The operational values are seeded once from configuration; later changes are made on this screen. The health monitor picks up new values at its next scheduled tick.

Actions ​

ActionEffectAPI
Save Read Replica PolicySaves the tenant policy. Banner "Read-replica policy saved."PUT /api/v1/authoring/read-replica/tenant-policy with {"enabled":true,"homeRegion":"in-east","readPolicy":"LOCAL_REPLICA"}
Save Operational ConfigSaves the four values. Banner "Operational config saved - the health monitor picks up the new values on its next scheduled tick."PUT /internal/read-replica/operational-config
LoadOn openGET /api/v1/authoring/read-replica/tenant-policy, GET /internal/read-replica/operational-config

When the feature is off, the screen shows the warning "Read-replica routing is disabled platform-wide (switched off by the operator), so this tenant's policy can't be read or changed right now. Ask a platform operator to enable the feature first." and, for the operational block, a similar warning.

Procedures ​

Route a reporting tenant's reads to its regional replica:

  1. Open Read replica routing. Set Enabled for this tenant to "On - route eligible reads to a replica".
  2. Set Read policy to Local replica and Home region to in-east.
  3. Select Save Read Replica Policy.
  4. Reads that are not in a recent-write window and do not require the primary are now eligible for a healthy in-east replica.

Make failover detection quicker (operators): set Health-check interval to 2 and Failure threshold to 2, then select Save Operational Config.

Permissions ​

Reading the tenant policy is open (an unset tenant reads back enabled: null, homeRegion: "default", readPolicy: LOCAL_REPLICA). Saving it requires read-replica:tenant-policy / update; otherwise HTTP 403. The operational-config endpoints do not check a permission; restrict this screen to platform operators.

API and CLI ​

bash
erp api get /api/v1/authoring/read-replica/tenant-policy
erp api put /api/v1/authoring/read-replica/tenant-policy --body '{"enabled":true,"homeRegion":"in-east","readPolicy":"LOCAL_REPLICA"}'
erp api get /internal/read-replica/operational-config
erp api get /internal/read-replica/status

GET /internal/read-replica/status returns the feature flags, the load-balancing strategy, each replica with its state, lagSeconds and lastLatencyMillis, and all tenant policies. Operators can also force a replica state with POST /internal/read-replica/{name}/force-state/{state} and clear it with POST /internal/read-replica/{name}/clear-force.

Limits and behavior ​

  • The operational PUT merges: a field that is omitted keeps its current value.
  • Replica selection never changes what a user is authorized to see; it only chooses the physical connection.
  • A read that must be answered by a replica and finds none available fails instead of falling back to the primary.

Errors and troubleshooting ​

Message or symptomCauseFix
Warning "Read-replica routing is disabled platform-wide"Feature switch off (HTTP 503 or 404)Operator switches read-replica routing on
healthCheckIntervalSeconds must be >= 1Value below minimumEnter 1 or more
healthCheckFailureThreshold must be >= 1SameEnter 1 or more
maxReplicaLagSeconds must be >= 0Negative valueEnter 0 or more
perTenantMaxPoolSize must be >= 1Value below minimumEnter 1 or more
403 on tenant policy saveMissing read-replica:tenant-policy / updateGrant the permission
Policy saved but reads stay on the primaryReplicas not HEALTHY, lag above the budget, or the read is inside the write windowCheck /internal/read-replica/status

Chat flows ​

Chat flows defines branching conversation trees made of message, question, condition and end nodes, and tests them in a live conversation. A chat flow is a versioned artifact; a session is a real run of the flow against the execution engine, stored with its transcript. Bot designers and support administrators use it. For voice and phone bots built on agents see the AI Studio designer pages.

Where to find it: Workspace > Administration > Chat flows. Page key chat-flows.

Key concepts ​

TermMeaning
Flow definitionA JSON document startNodeId plus nodes.
NodeOne step with a unique id and a type.
SessionOne conversation (chat_session), status active or ended, with its variables and message transcript.
VariableA value captured by a question node; substituted into later texts.
Artifact lifecycledraft, published, deprecated, archived; a published version is immutable.

Fields and options ​

List panel "Chat flows": each row shows the name and "vN - status". New opens a blank editor.

Editor:

FieldTypeDefaultRequiredDescription
NameText (create only)emptyYesArtifact name; the error "Name is required" appears otherwise. Names are unique per version
Flow definition JSONMulti-line JSONA greeting flow (below)YesMust be valid JSON ("Definition must be valid JSON")
Status chip"vN - status"n/an/aCurrent version and status

Node types and properties:

TypePropertiesBehavior
messageid, text, nextEmits text after variable substitution, then continues to next. If next is missing the conversation ends.
questionid, text, variable, nextEmits text and waits for the user. The reply is stored in variable, then the flow continues to next (the conversation ends if next is missing).
conditionid, expression, trueNext, falseNextEvaluates expression against the variables with the platform formula evaluator; only the supported formula subset and whitelisted formula functions are accepted. Continues to trueNext when the result is true, otherwise falseNext; ends when the chosen target is missing. A failing expression stops with the message Condition node "id" expression failed: ....
endid, optional textEmits the optional text and ends the conversation.

Variable substitution replaces each double-brace variable name in a text with the stored value. Variables hold the text the user typed.

Default definition offered for a new flow:

json
{
  "startNodeId": "greet",
  "nodes": [
    { "id": "greet", "type": "message", "text": "Hi! What's your name?", "next": "askName" },
    { "id": "askName", "type": "question", "variable": "name", "next": "thanks" },
    { "id": "thanks", "type": "message", "text": "Nice to meet you, {{name}}!", "next": "done" },
    { "id": "done", "type": "end" }
  ]
}

Conversation panel ("Conversation", with an "ended" chip when the session has ended): bot messages on the left, user messages on the right, a reply box with placeholder "Type a reply..." and Send (Enter also sends). The box is hidden once the session has ended.

Actions ​

ActionEffectAPI
CreateCreates a draftPOST /api/v1/authoring/chat-flows with name, definitionJson
Save draftSaves the draft using the revision shown (optimistic locking)PUT /api/v1/authoring/chat-flows/{id}/draft with expectedRevision
PublishPublishes the draft (shown for drafts only)POST /api/v1/authoring/chat-flows/{id}/publish
Try itStarts a session and shows the first bot messagesPOST /api/v1/chat-flows/{id}/sessions
SendSends a replyPOST /api/v1/chat-flows/sessions/{sessionId}/messages with {"message":"Ana"}
(API only) transcriptFull message historyGET /api/v1/chat-flows/sessions/{sessionId}/transcript

The screen does not offer clone, new version, deprecate, archive, delete or history. These exist on the API (POST .../{id}/clone, /new-version, /deprecate, /archive, DELETE .../{id}, GET .../name/{name}/history) and through the CLI.

Procedures ​

Build and test a lead-qualification flow:

  1. Select New, enter Name lead-qualifier.
  2. Replace the JSON with a flow that asks for a plan and branches:
json
{
  "startNodeId": "ask",
  "nodes": [
    { "id": "ask", "type": "question", "text": "Which plan are you interested in: basic or enterprise?", "variable": "plan", "next": "check" },
    { "id": "check", "type": "condition", "expression": "plan == \"enterprise\"", "trueNext": "big", "falseNext": "small" },
    { "id": "big", "type": "end", "text": "Thanks, a specialist will call you." },
    { "id": "small", "type": "end", "text": "Thanks, see our self-service plans." }
  ]
}
  1. Select Create, then Try it. The bot asks for the plan; reply enterprise; the conversation ends with the specialist message.
  2. Select Publish when satisfied.

Statuses and lifecycle ​

Flow artifact: draft to published to deprecated or archived. Editing a non-draft is rejected with chat_flow definition N is PUBLISHED - published definitions are immutable; create a new version instead. Sessions: active while waiting on a question, ended after an end node or a missing next.

Permissions ​

Authoring calls need AUTHOR (create, save, clone, new version) or PUBLISH (publish, deprecate, archive, delete) on artifact type chat_flow. Starting a session, replying and reading a transcript are not permission-checked in this release.

API and CLI ​

bash
erp artifact list --type chat-flows
erp artifact create --type chat-flows --name lead-qualifier --file lead-qualifier.json
erp artifact publish --type chat-flows --id 12
erp api post /api/v1/chat-flows/12/sessions
erp api post /api/v1/chat-flows/sessions/301/messages --body '{"message":"enterprise"}'

erp plugin op artifact-create --type chat-flows ... performs the same through the plugin-builder operations (artifact-list, artifact-get, artifact-history, artifact-create, artifact-update, artifact-publish, artifact-delete).

Limits and behavior ​

  • One turn follows at most 50 automatic steps (messages and conditions). Exceeding it returns Chat flow exceeded 50 auto-advance steps - likely a cycle with no question/end node.
  • The definition is stored as written; structure is checked when the flow runs, not when it is saved.
  • Sessions record each bot and user message with the node that produced it.

Errors and troubleshooting ​

Message or symptomCauseFix
Chat flow has no valid startNodeIdstartNodeId missing or not a node idCorrect the id
Chat flow references unknown node id: xA next, trueNext or falseNext points nowhereFix the id
Unknown node type "x" at node "id"Type not one of the fourUse message, question, condition or end
Session N has already endedReply sent to an ended sessionStart a new session with Try it
Session is not currently waiting on a question nodeReply sent while no question is pendingStart a new session
No such chat session: NWrong session IDUse the ID returned by start
Definition must be valid JSONSyntax error in the editorFix the JSON