Skip to main content
Data Transformers let you run deterministic text logic on any value your agent pulls in from variables, actions, or flows—no custom code required. Use them to normalise CRM fields, branch on boolean checks, or clean up API payloads before the LLM ever sees the data.

When to use Data Transformers

  • Format external data (e.g. strip symbols from phone numbers or rewrite salutations) before you reference it inside prompts.
  • Enforce guard rails by comparing values or routing between true/false outputs.
  • Share the same transformation across multiple agents, Pre-conversation Actions, or flow nodes and keep everything in sync.

Open the workspace view

1
Open Data Transformers in any of three ways: select the Data Transformers card on an agent’s page, press Cmd/Ctrl+K and search for Data Transformers, or use Build → Data Transformers in the sidebar. The page isn’t in the default sidebar, so to use that route, add it first with Customize sidebar — see Navigating Studio. The card on an agent’s page shows a count such as 3 transformers. That count covers every transformer in your account, not only the ones that agent uses, and the card opens the same list as the sidebar page. A transformer link in a Co-pilot reply opens that transformer straight in the editor.
2
The page shows one card for each transformer in your account, most recently updated first. A card shows the name, a one-line description (hover to read all of it, or No description if you left it empty), and when the transformer was created and last updated. Select a card to open it in the editor, or use the menu on the card for Edit and Delete.
3
Use the search bar to filter by name or description. Under the cards, Show sets how many cards appear on each page (10, 20 or 50; the default is 10), and the arrows move between pages. If you have no transformers yet, or a search matches none, the page reads No Data Transformers Yet with a Create Data Transformer button.

Create or edit a transformer

  1. Click Create Data Transformer (or use the menu beside an existing item and choose Edit).
  2. Enter a Name (required) and an optional Description so team-members understand what the transformer does. Each name must be unique among your transformers. Saving a name that’s already taken fails with “A transformer with this name already exists in this workspace”.
  3. Under Inputs, enter a test Value for input1. Use Add Input if the transformer needs more than one incoming value (input2, input3, and so on).
    • Extra inputs have a ✕ button; input1 can’t be removed. Studio asks you to confirm (Delete Input) before it removes one.
    • An input that a block’s Input still refers to can’t be removed — Studio shows “Cannot delete input2 - it is referenced by expressions”, so point that block at another input first.
    • Removing an input renumbers the inputs after it (input3 becomes input2) and updates each block’s Input to match, but not references you typed into other fields, such as a Compare Value, so check those afterwards.
    • A transformer with more than one input can’t be applied in-line from the variable popper, which only offers single-input transformers — use it from a Set Variable or Decision step instead. See Use a transformer in Set Variable and Decision steps.
  4. Build the Expression Pipeline:
    • Each block (e.g. expr1, expr2) represents one transformation step.
    • Choose the Transformation type and set the block’s Input:
      • {{input1}} (or any {{input#}}) runs against that input’s value.
      • Any {{expr#}} lets you chain from a previous block’s output.
    • Fill out the parameters that appear for the selected type (see the table below).
    • Add more blocks with Add Expression or remove a block with the ✕ icon (except the first one). Studio asks you to confirm (Delete Expression) first.
      • A block that a later block’s Input still refers to can’t be removed — Studio shows “Cannot delete expr2 - it is referenced by other expressions”.
      • Each new block starts with its Input set to the block before it, so in a chain where each block feeds the next, you can remove only the last block until you point the next block’s Input somewhere else.
      • Removing a block renumbers the ones after it (expr3 becomes expr2), but Studio doesn’t rewrite references to them, so check each remaining block’s Input afterwards.
  5. Click Run to try the full chain against your test values. The Output box shows the result of the last block so you can verify the logic. Run needs a test Value that isn’t blank for every {{input#}} named in a block’s Input — if one is empty, Studio asks you to fill it in first. If Run or Create refuses to go ahead, see If Run or Create won’t go through.
  6. Click Create (or Update when editing). The transformer is saved and ready to use. You can apply a single-input transformer in-line in most fields where you insert a variable, and use any transformer from a Set Variable or Decision step — see Apply a transformer to variables. Editing a transformer changes it for every agent that uses it, but an agent you’ve published keeps running the version it was published with, and reads Unpublished edits, until you Publish it again (see What Waits for Publish).

Supported expression types

You can mix and match types inside the same pipeline. Every block outputs plain text, so downstream steps (and the agent) can read the result immediately.
Empty inputs are handled gracefully. If an input value is empty — or an expression references an input that was never supplied — the reference resolves to an empty string and the pipeline keeps running, instead of failing the transformation. This means transformers attached to optional variables (for example, a CRM field that is sometimes blank) no longer need guard expressions just to survive missing data. Pad String is the one exception: an empty input comes out as a full-length run of the pad character rather than as an empty string. In the editor, Run needs a test Value that isn’t blank for each input a block’s Input refers to, so you can’t try blank handling out there.

Behaviour worth knowing

  • Extract Number (fixed) and Extract Number (min–max) match on the whole run of digits. With a Length or Max Length of 3, a four-digit run such as 2019 is skipped entirely rather than clipped to 201 — so a date in the text will not be mistaken for a 3-digit code.
  • String Length counts characters the way software does, not the way the eye does: an emoji counts as 2.
  • Pad String counts length in whole characters, while String Length counts the way software does — an emoji is one position to Pad String and 2 to String Length. Chaining String Length into the Target Length of a Pad String block will therefore not line up on emoji or other astral characters.
  • Pad String accepts an emoji or an accented letter as a pad character, but rejects one built from several code points — a combining accent, or a multi-person emoji such as 👨‍👩‍👧 — rather than padding by visual clusters.
  • Extract Email covers everyday addresses. It does not match accented or non-Latin local parts, quoted local parts, or intranet addresses without a dot (user@localhost).
  • Regex Extract caps the work a pattern can do — input up to 100,000 characters, patterns up to 1,000 characters, and up to 10,000 matches — and returns a clear error rather than stalling if a pattern exceeds them.
  • Modulo (%) truncates both values to whole numbers first, and the sign of the result follows the first value: -7 modulo 3 is -1, not 2; 7 modulo -3 is 1; and 10.9 modulo 3.9 is 1.
  • Compare treats a side as a number only when it is a plain number: an optional minus sign, digits, and an optional decimal part, such as 42, -7 or 3.14 (spaces around it are ignored). Anything else, including 1,000, $50, +5, .5, 1e3 and 10 kg, is text. If both sides are plain numbers, Compare compares them as numbers, so 10 is greater than 9 and Case sensitive makes no difference. If either side is text, it compares both as text, so Less Than and Greater Than follow alphabetical order and Case sensitive applies: $10 is less than $9, because 1 comes before 9. To compare amounts such as $50, strip the symbol first (for example with Find & Replace).
  • Conditions and Ternary Operator decide true or false the same way, ignoring capitals and any spaces around the text. These count as true: true, yes, y, 1, any other number that isn’t zero, and any other text at all. These count as false: false, no, n, 0 (and 00 or 0.0), and a blank value. So a status word such as active counts as true, and so do none, null and off. If you need an exact match, run a Compare or Matches Regex step first and feed its true or false result into Conditions or Ternary Operator.
  • The two Extract Letter transformers match on the whole run of letters, exactly as the two Extract Number transformers do with digits — a run that is too long is skipped rather than clipped. Only ASCII letters count, so digits, spaces and punctuation end a run, and accented or non-Latin letters are not letters at all.
  • Round Number sends an exact half away from zero (-2.5 rounds to -3), while Floor (down) and Ceil (up) go toward negative and positive infinity (-2.1 floors to -3). A blank or non-numeric input counts as 0 rather than failing the chain.
  • Unlike Random Number, which never fails a chain, the Extract Letter and Extract Number transformers, Round Number and Pad String do fail the expression at run time if a referenced parameter resolves to an invalid number — a length or bound that isn’t a whole number of 1 or more, a Precision that isn’t a whole number from 0 to 100, a range whose bounds are the wrong way round, or — for Pad String — a pad character that is blank or longer than one character. Arithmetic is more forgiving: it fails only on a zero divisor, because a blank or non-numeric reference counts as 0. An empty result from an Extract Letter or Extract Number transformer is not a failure — it simply means no run matched. What the agent receives when a transformer fails during a conversation is covered in When a transformer fails during a conversation.
  • Datetime, Date and Date Offset return a millisecond timestamp, not a date to read out to a caller. When one of them is the last block and you click Run, the Output box shows the result as a readable UTC date — 2026-01-08T00:00:00Z, or 2026-01-08 for Date — but a later block, and your agents, flows and actions, always receive the number. Use these results for comparisons.
  • Date Offset month and year steps stop at the end of a shorter month: 31 January plus one month and 31 March minus one month both give 28 February (29 in a leap year).
  • Date Offset in Days, Weeks, Months or Years keeps the local clock time across a daylight-saving change in the selected Timezone, while Hours counts elapsed time. From 09:00 on the day before the clocks go forward, one day later is 09:00, but 24 hours later is 10:00. An input that carries its own offset, such as +11:00, stays on that fixed offset instead, with no daylight-saving adjustment.
  • An offset in the input, such as +11:00 or Z, takes precedence over Timezone in Datetime and Date Offset only when the Format reads it — with a Z, ZZ or ZZZ token, with ISO, or, for a trailing Z only, with a quoted 'Z'. Otherwise, input that carries an offset doesn’t match the format and the block fails.
  • With a date-only Format, Date Offset and Datetime read the date as midnight in the selected Timezone, whereas Date always uses midnight UTC. Keep Timezone on UTC when you compare a Date Offset result with a Date result, or the two will be hours apart.
  • A literal Value in Date Offset that isn’t a whole number of 0 or more is rejected when you save or run. A referenced Value that resolves to blank, a decimal, a negative number or text counts as 0, so the date passes through unchanged rather than failing the block.
  • To offset a value that is already a timestamp — the output of an earlier Datetime block, for example — set Format on the Date Offset block to x (milliseconds) or X (seconds).
  • For all three date transformers, input that doesn’t match the Format fails the block with an error saying so, and a blank input returns a blank result. A later Compare treats a blank result as text rather than a number, so a missing date can still come out true — if the date can be blank, check for that first. Use yyyy for the year: YYYY is rejected.
  • The Co-pilot can add date steps, but only in a fixed set of formats: yyyy-MM-dd or dd/MM/yyyy for Date; yyyy-MM-dd HH:mm:ss, yyyy-MM-dd'T'HH:mm:ss or yyyy-MM-dd'T'HH:mm:ssZ for Datetime; and any of those five for Date Offset. For ISO, a timestamp or any other format, edit the block’s Format yourself.

Date formats and timezones

Datetime, Date and Date Offset read the incoming text using the Format you write, and the text has to match the format exactly. Click the help icon beside Format to see this list in Studio. You can type a space, -, /, :, . and , as they are. Wrap any other letters in single quotes, such as the T in yyyy-MM-dd'T'HH:mm:ss. These examples all describe 21 November 2025: Timezone, on Datetime and Date Offset, is the same picker as the Timezone card in an agent’s settings. Select it to open a list with Search timezones ready to type in. Type part of a region or city name to find a zone; a name with a space in it, such as “new york”, finds America/New_York. An abbreviation such as PST, EST, CST or MST puts the matching North American zones first, and UTC or GMT puts UTC first. Other abbreviations, such as IST, AEST or BST, aren’t recognised, so search by city or region instead. The zone in use has a tick and the list opens scrolled to it, and a search that finds nothing says No timezone found. Each entry shows the zone name, its offset today and its full name, for example Asia/Tokyo (+09:00) Japan Standard Time. UTC is the default. The offset in the label is only a guide; the transformer applies the offset that was in force on the date it’s reading, so daylight saving is taken into account.

Tips for complex pipelines

  • Use descriptive descriptions so future editors understand why a pipeline exists.
  • When chaining expressions, double-check each block’s Input field; expr2 defaults to the previous block, but you can point it at any earlier result.
  • Clicking Run often helps you catch whitespace or case-sensitivity issues before anyone attaches the transformer to production prompts.

If Run or Create won’t go through

Run and Create (or Update) make the same checks first. Studio shows only the first problem it finds, as a pop-up message, so fix it and try again to see whether anything else is left. The usual causes:
  • The Name is blank. Create (or Update) stays greyed out until you enter one, and Run needs a name too.
  • A block has no Transformation chosen, or its Input is blank — for example “expr1: Input source is required”.
  • A required parameter is missing or not valid — for example “expr1: Search value is required for Find & Replace” or “expr2: Pad Character must be a single character”.
  • A block refers to something that doesn’t exist, such as {{input3}} when you have two inputs (“expr1: Invalid reference “input3”. Must reference an input or expression.”), or to itself or a block that comes after it (“expr2: Expression reference expr3 is invalid (must reference a previous expression)”). This applies to a block’s Input and to most of the parameter fields that accept references, such as Search Value or Value.
  • Run only: a test Value is blank for an input that a block’s Input refers to. Studio says “Input source “input1” is empty. Please enter a test value for input1 to run the transformation.” Blank values are fine when the transformer runs in a live conversation (see the note above), but not in the editor’s Run.
  • The pipeline itself fails on your test values — for example a date that doesn’t match its Format. Studio shows the error as a pop-up message and the Output box stays empty.

Apply a transformer to variables

In most text fields that accept variables — for example Guidelines, Greeting & Sign-off, a Say message or an API request — you can apply a transformer in-line. Choose the transformer first, then the variable:
  1. Type {{ to open the variable popper.
  2. Tick Apply data transformation at the bottom of the popper.
  3. Choose the transformer from the Select transformer dropdown. It lists transformer names only, and stays greyed out until the box is ticked. It reads No transformers available if you don’t have any single-input transformers.
  4. Click the variable you want, or arrow down to it and press Enter. The inserted snippet renders as [TransformerName({{variableName}})], and the stored value includes the transformer ID so the platform can run the pipeline automatically.
The popper inserts a variable the moment you click it and then closes. If you click the variable first — or tick Apply data transformation but leave Select transformer empty — you get the plain {{variableName}} with no transformation. Delete it and insert it again in the order above.
A few things to know:
  • The Select transformer list only offers transformers with exactly one input. A transformer you built with Add Input (two or more inputs) never appears there — use it from a Set Variable or Decision step instead, as described below.
  • Action references can’t be transformed. Ticking Apply data transformation hides the ACTIONS group in the popper, and the option isn’t available while you’re inserting an action reference in Guidelines.
  • The option isn’t offered in the fields of Set Variable and Decision steps, or in the fields of the transformer editor itself.
This works for system, interaction, and custom variables. On execution the platform pushes the transformed value into the agent prompt, HTTP request body, or wherever the variable lives.

Use a transformer in Set Variable and Decision steps

The Set Variable and Decision steps in a flow list your transformers, including those with several inputs. Like the Data Transformers page, they show the 100 most recently updated. For each input (input1, input2, and so on) you give a value, which can include {{variables}}. See In-conversation Actions for the flow editor, including the Set Variable Node and Decision Node.
  • Set Variable — pick the variable, then choose the transformer in the Transformation Logic dropdown (the other choice is Static Value). The transformer’s result is stored in the variable.
  • Decision — in a condition, choose the transformer under Condition Rule and fill in the Input Values. The condition matches when the transformer’s result is true, so end the pipeline with a step such as Compare, Matches Regex or Conditions.

When a transformer fails during a conversation

A transformer that passed Run can still fail on real data — for example a referenced length that turns out to be text, or a zero divisor. The conversation carries on; what the agent gets depends on where the transformer is used and how many inputs it has.
  • Applied in-line to a variable — a variable that has no value at all comes out as empty text, and the transformer isn’t run. If the transformer runs and fails, the agent gets the variable’s original, untransformed value.
  • Set Variable — with a single-input transformer, a failure stores the original input value in the variable. With two or more inputs nothing is stored: the assignment is skipped and the flow keeps going.
  • Decision — with a single-input transformer, a failure hands the original input to the condition, which matches only if that input is itself true. With two or more inputs the condition counts as not matched, and the Decision moves on to its next condition (or Otherwise).
Try your transformer with Run, including awkward values such as text where a number belongs, before you attach it to a live agent.

Manage safely

  • Usage-aware deletion – clicking Delete runs a usage check first. If the transformer is referenced by any agent, action, or flow node you will see a detailed report and deletion is blocked until you remove those references. See Deleting a transformer.
  • Instant search – the list loads up to 100 transformers, most recently updated first, and filters them in your browser as you type, so there are no extra round trips. If you keep more than 100, the least recently updated ones don’t appear in the list or in search, and the Set Variable and Decision steps don’t offer them either.
  • Exports & clones – AI Agent exports, imports and duplicates automatically carry along any referenced transformers and rebuild usage links in the target workspace. Duplicate links the copy to the original agent’s transformers instead of copying them, so editing a transformer changes both agents (each one that has been published reads Unpublished edits until its next Publish). Importing into the workspace the agent was exported from does the same, and creates again any transformer that has since been deleted. Importing into a different workspace reuses a transformer whose Expression Pipeline is exactly the same, even under a different name, and creates any other as a new transformer, adding _(2) to its name if the name is taken.

Deleting a transformer

Choose Delete from the menu beside a transformer. Studio first checks where it is used, and the menu item reads Checking… while it does. If the check can’t be completed, Studio asks you to try again and deletes nothing.
  • Not in use — a Delete Data Transformer window asks you to confirm. Select Delete (or Cancel to keep it) and the transformer is removed. This can’t be undone.
  • In use — a Data Transformer In Use window says how many items still use it and lists them, grouped under AI Agents, Pre-conversation Actions, Post-conversation Actions and Flow Nodes. Each entry shows the item’s name and a Fields list of where the transformer is used. Actions and flow nodes also show the AI agent they belong to, and flow nodes show their flow. Deletion is blocked until you remove those references. Select Close, point each item at a different transformer (or remove the transformation), then delete again.
Anything that holds the transformer counts as a reference: an agent’s own fields such as Guidelines or Greeting & Sign-off (wherever you applied it in-line), a pre-conversation or post-conversation action, or any step in a flow, including Set Variable and Decision steps. The platform repeats the check when the delete goes through, so a delete that races someone wiring the transformer into a flow at the same moment is refused too. In that case Studio shows “Failed to delete data transformer” and the transformer stays in your list. You can also ask the Co-pilot to delete a transformer. It shows a card that names the transformer and warns that deletion can’t be undone, and deletes it only after you select Delete transformer (Cancel leaves it in place). The same rule applies: if an agent still uses the transformer, the Co-pilot refuses and tells you what’s using it, so remove those references first.

AI Agents

Inject transformed values into greetings, guidelines, and agent settings.

Pre-conversation Actions

Combine transformers with API responses before a call starts.