Variables and secrets (Tenant Variables)
Required Access Level
- Process variables (the definition's Variables tab): Admin, Modeler or Super Admin.
- Company variables and secrets (menu Administration → Variables and secrets): Admin or Super Admin.
This page covers both places a variable can live: each process's Variables tab and the Administration → Variables and secrets menu item, which holds what applies to the whole company.
Tenant Variables hold static keys and values that the platform injects as process variables every time an instance starts. They belong to one process at a time: each variable is stored together with the key of the process it belongs to, and the same name — exchange_rate, say — can exist with different values in different processes.
A process variable does not apply to the whole tenant
A variable registered on a process applies to that process: it is stored with its process key, and the platform only loads it when starting an instance of that process. If five processes need the "Support Email", the value has to be registered in all five — what you set on process A simply does not exist for process B.
What belongs to the whole company — an IMAP inbox password, an ERP token several robots use — goes under Variables and secrets, described right below.
Company-wide variables and secrets (outside any process)
An inbox and a robot are not processes, but they need credentials: the IMAP password, the ERP token. That is what Administration → Variables and secrets (path /admin/variables) is for: it stores variables of the whole tenant, with no process at all.
- Go to Administration → Variables and secrets and click New variable.
- Enter the key — it starts with a letter or
_and uses only letters, digits,_,.and-. It is what goes inside${var.key}. - Pick the type, enter the value and switch Secret on for a password or token.
- Save. From then on the inbox or the robot points at it with
${var.key}.
A secret is never shown again after saving. The list shows ********, so does the API response, and when editing, the value field comes empty: leave it blank to keep the stored value, or type a new one to replace it. The value is stored encrypted in the database.
Creating does not overwrite. Creating a variable whose key already exists is refused, naming the key — to change its value, use Edit on its row. Before, creating with the key of an existing secret silently replaced its value.
The inbox password field and the robots' secret parameters show a Create variable button only while the referenced variable does not exist. It opens the same creation dialog on top of the screen you are on, with the reference's key filled in and Secret switched on, and does not lose what you were editing.
If the list fails to load, the screen shows the error — not "no variable yet", which would suggest they were gone.
The reference is checked on save
When an inbox or a robot's parameters are saved, the platform checks that every ${var.key} exists. If it does not, the save is refused with a message naming the missing variable and pointing to Variables and secrets — the error shows up right away, not at the next poll of the inbox or the next run at night.
Keeping it in the vault instead of storing the value
When the installation has a vault connected (see External vault), a secret variable gets the Stored value / Vault reference choice. With Vault reference you type where the secret lives, for example vault://kv/flowi/tenants/<your-tenant>/erp#password, and the platform reads the value from the vault at the moment of use — the database keeps only the reference.
- The list shows the reference with the Vault tag; the value never appears.
- On save the platform fetches the reference once to check it: if it does not exist in the vault, or points outside your Tenant's prefix, the save is refused naming the reference. If the vault is down at that moment, the variable is saved anyway and checked on first use.
- A reference is only accepted on a variable marked Secret, and is at most 900 characters long.
- A secret stored as a reference is never copied into the instance, even with secret injection on: use
${secrets.get(execution, 'key')},{{secret:key}}or${var.key}. - With no vault connected the choice does not appear, and a value starting with
vault://is refused on save.
Who wins when the same key exists in both places
- Inside a process, the process variable wins. A process that defines its own
apiKeyuses it; a process that does not falls back to the companyapiKey— but only through the secret reader (${secrets.get(execution, 'apiKey')}and{{secret:apiKey}}). The company variable is not copied into instances, so the IMAP password does not spread across every process that runs. - Inboxes and robots use the company variable first. If it does not exist, the variables registered inside processes still count, as before: a single one with that key resolves; two with different values are refused, naming the processes.
The screen is managed by the tenant Admin, and by the Super Admin with the tenant selected. The Modeler does not see it: a company credential is administration, not process design.
What are they for?
Imagine a billing process that depends on the "Support Email" or on a "Standard Exchange Rate". Instead of hardcoding that value in the BPMN diagram — which forces you to publish a new version of the process every time it changes — create an support_email or exchange_rate variable in that process's configuration.
If the rate changes tomorrow, you edit the value on screen and new instances are born with it, with nothing to republish. Running instances keep the value they received: the variable is copied into the instance at start time, not re-read at every step.
Managing Variables
Variables live inside the process, not under a menu item of their own. Process Catalog is what gathers a process's configuration, and it is the way into all of it: variables, business key template, attachment policy, knowledge bases, agents and self-learning.
- Go to Process design → Process Catalog and open the process you want.
- Switch to the Variables tab.
- Enter an identifier that is unique within that process (no spaces, preferably
snake_case) and the value. - Pick the type (
STRING,INTEGER,DECIMAL,BOOLEAN,DATE) — it decides how the value reaches the process: anINTEGERarrives as a number, not as text. - Tick Secret when the value must not appear on screen or be returned by the public API that pre-fills forms.
Secret variables and AI agents
A variable marked Secret never reaches an AI agent as a value. In the agent's prompt, a {{my_key}} pointing at a secret variable renders as {{secret:my_key}} — the agent sees the name, never the content.
To use the credential in an API call, the agent writes that same handle in the HTTP request tool, for instance in a header:
Authorization: Bearer {{secret:my_key}}The platform substitutes the real value at the last moment, on the way out to the network. The value does not enter the prompt, is not sent to the model provider, does not stay in the conversation history, and does not appear in the log — which records the method, the URL, the header names and the body length.
Write the prompt with the name, not the value: a prompt that says "authenticate with {{my_key}}" works — the call is made, the credential reaches its destination, and the model never sees the value.
On screen, a secret variable is displayed as ******** on the instance and task screens too, not only on the variables screen. Whoever opens the instance sees that the variable exists, never its content.
What this does not protect
An agent only reaches the hosts its own definition declares — see How far an agent may call in AI Agents. With no list declared the behaviour follows the installation's policy (AI_HTTP_TOOL_DEFAULT_POLICY), and internal network addresses are always blocked.
The Microsoft 365 app secret
The connection that syncs knowledge bases with SharePoint and OneDrive (see Knowledge Bases) has no secret field. The secret of the app registered in Entra lives in a secret company-scope variable — the value, or a vault:// reference —, and the connection keeps only its name. Rotating the secret means changing this variable's value; the connection uses it on its next token.
The credential of an external knowledge base
An external base (Elasticsearch or OpenSearch) authenticates with a company secret variable — the list of variables outside any process. Create the variable here (its value may be a vault reference) and, on the base, pick its name: no field of the base accepts the value. For an API key, store the encoded key Elasticsearch prints; for user and password, store user:password. The platform reads the secret on every query, in the tenant of the retrieval, and it only exists in the request header — not in the log, the API response, the prompt or the audit.
Using a secret in a process expression
A secret variable can be read at the moment of use, without being copied into the instance:
${secrets.get(execution, 'my_key')}The value is fetched when needed, used, and stored nowhere — neither in the instance variables nor in the history.
The copy into the instance, and how to switch it off
For compatibility, secret variables are also copied into the instance's variables when a process starts — and Flowable stores instance variables in clear text, including in the history, which outlives the instance.
A new installation should run with SECRETS_INJECT_INTO_PROCESS_VARIABLES=false. The secret then never enters the instance, and expressions must use the form above. Every withheld variable is logged by name, so you can see what was held back.
Usage in Processes
The variable enters the instance under its plain name, exactly as you registered it. For a variable called my_variable, the BPMN expression is:
${my_variable}
${tenant.my_variable} does not resolve
Always use the plain name. The platform creates no object named tenant in the process scope, so ${tenant.my_variable} does not return the variable's value — it fails, or arrives empty in your flow, and the diagram is published without complaint.
If any point of your BPMN uses the prefix, replace ${tenant.x} with ${x} in all of them.