Background
When configuring workflows to automatically create and update access through Lumos, you may find yourself needing to reference attributes from the target user. For example:- When creating a username (setting it to
first_name.last_name) - When assigning custom attributes in apps like Slack or Okta (
team,title,manager) - When scheduling an action relative to a user’s start date (e.g. 2 days before)
- When updating a last name (ensuring names remain aligned with values from the HRIS)
timedelta, isoformat(), or datetime are not available. This guide covers every function and operator that LEL supports.
What You Can Do With Expression Language
With Lumos Expression Language, you can:- Reference attributes from user identities in your workflows
- Combine identity attributes with static text
- Transform data with built-in functions (lowercase, uppercase, split, etc.)
- Perform date arithmetic (add or subtract days/hours from dates)
- Create conditional logic to handle different scenarios
- Generate random values for temporary passwords or unique identifiers
- Convert non-Latin characters to ASCII equivalents
- Normalize country names to standard ISO codes
- Skip setting an attribute entirely when a condition isn’t met
Syntax Basics
Referencing Identity Attributes
To reference an attribute from the user in your workflow, use theuser object:
The Pipe Operator (|)
LEL supports two ways to apply transformations: the pipe operator and method-call syntax. Both are equivalent — use whichever you find more readable.
String Concatenation
Use the+ or ~ operator to combine values together. Both work the same way.
Static Text
Wrap static text in single or double quotes:Available Attributes
Standard Attributes
These can be accessed directly on theuser object:
Custom Attributes
Custom attributes defined in your Lumos settings are accessed via thecustom_attributes field:
Groups
If your workflow context includes group information:Operators
Comparison Operators
Logical Operators
String Operators
Conditional Logic
Inline If/Else
Use inlineif/else to return different values based on a condition:
Fallbacks with or
For simple “use this value if available, otherwise use that value” logic, the or operator is more concise:
Fallbacks with default
Use the default filter to provide a fallback value when an attribute might be missing or empty:
Skipping an Attribute with DO_NOT_SET
Sometimes you want to conditionally skip setting a value entirely — rather than setting it to an empty string. Use the special DO_NOT_SET sentinel:
DO_NOT_SET, Lumos will skip the attribute update for that user entirely.
Data Transformations
String Transformations
Special Character Removal
strip_punc — Removes all punctuation characters from a string, including ASCII punctuation (!@#$%^&* etc.) and Unicode punctuation (fullwidth commas, curly quotes, Japanese brackets, etc.):
Jean-Pierre O'Connor into jeanpierre.oconnor@company.com.
strip_chars — Removes only the specific characters you define:
Jean-Pierre into JeanPierre (hyphens removed, all other characters kept).
Transliteration
Convert non-Latin characters (Greek, Chinese, Cyrillic, etc.) to Latin/ASCII equivalents:transliterate('Müller')→"Muller"transliterate('Μαρία')→"Maria"transliterate('张伟')→"zhangwei"
Any-Latin; Latin-ASCII;) converts from any script to ASCII.
Base64 Encoding
Encode a value as Base64 for systems that require it:"john@example.com" → "am9obkBleGFtcGxlLmNvbQ=="
Date Arithmetic
LEL provides built-in filters for performing arithmetic on date values. These are the only way to manipulate dates in LEL — standard programming constructs liketimedelta or isoformat() are not available.
add_days(n)
Adds a number of days to a date. Use negative numbers to subtract.
subtract_days(n)
Subtracts a number of days from a date.
add_hours(n)
Adds a number of hours to a date.
Combining Date Filters
You can chain date filters together:Handling Missing Dates
All date filters gracefully handle missing dates — if the input date isNone, the result is also None (no error). Combine with conditional logic if you need different behavior:
Current Timestamp
Get the current date and time withnow():
Country Lookup
Normalize a country name or code to standard ISO format usinglookup_country:
Generating Random Values
Lumos supports generating cryptographically secure random values, useful for temporary passwords, unique IDs, and access codes.random_string(length, charset?)
Generates a random string of the specified length. Defaults to alphanumeric characters if no charset is specified.
Composing formats — use
~ to concatenate multiple random_string calls:
"XY654321" (2 uppercase letters + 6 digits)
Maximum length: 50 characters per random_string call.
random_int(min, max)
Generates a random integer within an inclusive range.
random_string and random_int generate a new value every time the expression is evaluated. They are ideal for temporary passwords or one-time codes, but not for values that need to be stable across runs.
Common Recipes
Generate a username from name
"jsmith"
Generate an email with preferred name fallback
Extract handle from email
Set a value 2 days before start date
Schedule for 9 AM, 2 days before start date
Create a clean email from names with special characters
Transliterate non-Latin names for provisioning
Conditionally set an attribute, or skip it
Generate a temporary password
"KXPM4821abcd"
Get the first 4 characters of an Employee ID (safely)
FAQs
What happens if an attribute I reference doesn’t exist? If you reference an attribute that doesn’t exist, the workflow step will fail and generate an Error Task in Lumos with details about the failure. Use thedefault filter or if/else logic to handle potentially missing attributes gracefully.
Can I use expressions in all workflow actions?
Yes. Expressions can be used in any input field for any workflow action that expects a “string” value.
Why doesn’t timedelta, isoformat(), or datetime work?
LEL is not Python. It uses its own set of built-in functions. For date manipulation, use add_days, subtract_days, and add_hours. For converting a date to a string, use | string.
Can I reference attributes from connected systems (like Okta or AzureAD)?
Yes, but you must first store them as custom attributes on the Identity in Lumos to use them in provisioning workflows.
How do I handle names with special characters when creating email addresses?
Use strip_punc to remove all punctuation, or strip_chars with specific characters to remove only certain ones. For non-Latin scripts, use transliterate.
Are randomly generated values the same each time a workflow runs?
No — random_string and random_int generate a new value every time the expression is evaluated.
Can I use random_string to generate secure passwords?
Yes. Lumos uses Python’s secrets module under the hood, which is cryptographically secure.
What does DO_NOT_SET do?
When an expression evaluates to DO_NOT_SET, Lumos skips the attribute update for that user entirely. This is different from setting the value to an empty string — DO_NOT_SET means “don’t touch this attribute at all.”
How complex can my expressions be?
While you can create fairly complex expressions combining multiple conditions and transformations, Lumos recommends keeping expressions reasonably simple for maintainability.