Using transform-data steps
Use a transform-data step to run code that formats, filters, combines, or calculates Flow data. The Flow editor labels this step Run Code.
Before you begin
Open a Flow in the Flow editor. For instructions, see Creating and editing flows.
Add a transform-data step
To add and configure a transform-data step, follow these steps:
- In the Flow editor, click the + control where you want to insert the step.
- In the step picker, select Run Code. The step card opens.
- In Execution Environment, choose the environment that matches your code. The default Cloudflare Worker (Default) environment runs JavaScript.
- In Input Mode, select Code (Write your own logic).
- Select a code template or click Write code to open the editor.
- In the code editor, write a script that returns the value that you want to store.
- In Output variable, enter the name for the returned value.
- In the toolbar, click Create for a new Flow or Save for an existing Flow.
- Run the Flow. The output variable holds the value that the script returned.
Optional: Rename the step in its header to describe its transformation.
The step inspector shows the same settings with shorter labels: Runtime for the execution environment, and Code or Variable for the input mode.
To check the output without a full run, see Test a transformation.
Choose an execution environment
The following table compares the execution environments:
To run TypeScript or Python, choose Runtype Sandbox or Daytona Sandbox, then set Language to the language that you want to use.
Cloudflare Worker (Default) supports async/await and blocks network access by default. Its helper functions include helpers.slugify, helpers.extractEmails, helpers.html2markdown, and helpers.formatDate. QuickJS (Legacy) exposes the same functions as globals, such as slugify(text). For the full list, see Cloudflare Worker helper functions.
Runtype bills Runtype Sandbox runs as usage, based on how long the container runs. Use Cloudflare Worker (Default) for JavaScript that does not need packages or another language. For more information, see Billing and plans.
Daytona Sandbox uses the Daytona API key that you add in Settings > Integrations. If you don’t add a key, Runtype uses a platform key when one is available for your organization. If no key is available, the step fails with Daytona API key not configured.
For HTTP requests that need step-level request and response configuration, use the Fetch URL or Make API Call step.
Install packages
To install npm packages for a JavaScript or TypeScript script in a container environment, enter the package metadata in Package.json (Optional). Runtype Sandbox ignores this field when Language is Python.
On Runtype Sandbox, the package installation obeys the step’s Network Access setting. Allow the package registry, such as registry.npmjs.org, or choose Unrestricted. If the installation fails, the step fails with npm install failed and the installer’s output.
Reuse a sandbox
By default, a container environment removes its sandbox when the step finishes. To keep the sandbox, select Persist Sandbox (Keep sandbox alive for reuse). The step writes the sandbox ID to the _sandboxId variable. To run a later step in that sandbox, enter {{_sandboxId}} in Reuse Sandbox ID.
Script time limits
A Runtype Sandbox script runs for up to 30 seconds by default. When the run sets a step timeout, the script gets that time instead, from a minimum of 30 seconds to a maximum of 10 minutes. Package installation has its own limit of the same length. A Cloudflare Worker (Default) script runs until the step timeout, which is 5 minutes unless the run sets another value. A QuickJS (Legacy) script runs for up to 5 seconds unless the run sets a step timeout. To set the step timeout for a run, see Timeouts and long-running work.
Control network access
Cloudflare Worker (Default) and Runtype Sandbox block outbound requests by default. To change this, follow these steps:
- On the step card, expand Advanced. In the step inspector, click the network chip, such as Network: off, instead.
- In Network Access, choose one of these options:
- Blocked (default): Block every outbound request.
- Unrestricted: Allow requests to any public host.
- Allowed Hosts Only: Allow requests only to the hosts in Allowed Hostnames.
- If you chose Allowed Hosts Only, enter each hostname in Allowed Hostnames and press Enter. A wildcard such as
*.example.commatches every subdomain. Until you add a hostname, the step still blocks every request.
In a Flow definition, the same options are the networkAccess values "off", "on", and { "allowedHostnames": ["api.example.com"] }.
A blocked request does not throw. It returns an HTTP 403 response. Under Blocked (default), the response body starts with Network access is disabled for this. Under Allowed Hosts Only, the body starts with Host 'HOST' is not in the sandbox networkAccess allowlist, where HOST is the blocked hostname. To allow the host, add it to Allowed Hostnames. Check the response status in your script so that a blocked request does not pass as data. On Runtype Sandbox, private-network addresses, loopback addresses, cloud metadata hosts, and *.internal hosts stay blocked under every setting.
Daytona Sandbox does not use this setting. Outbound access from a Daytona container follows the Daytona sandbox policy.
Outbound WebSockets work on Cloudflare Worker (Default) and Runtype Sandbox after you enable network access, and the host must be allowed like any other request.
On Cloudflare Worker (Default), open the connection with fetch() and an Upgrade: websocket header, then accept the returned socket:
On Runtype Sandbox, use the Node WebSocket global:
Write a script
Write a script that produces the value that you want to store. How the script reads Flow variables and returns its result depends on the environment.
JavaScript on Cloudflare Worker and QuickJS
Return the value from the script. Earlier step outputs are available by their outputVariable names, and the complete variable map is available as input. Use input.NAME when a variable name is not a valid JavaScript identifier or is a reserved word. The examples on this page use input so that they work for every variable name.
The following script formats a customer object:
Replace customer_data with the earlier step’s outputVariable name.
The following script counts words in a generated summary:
Replace generate_summary with the earlier step’s outputVariable name.
Scripts on Runtype Sandbox
Runtype Sandbox provides the Flow variables as parameters, an object in JavaScript and TypeScript and a dictionary in Python. It does not define input or top-level variable names.
A JavaScript or TypeScript script returns its value:
A Python script prints its value. The step parses the printed output as JSON when it is valid JSON and stores it as text otherwise, so print structured results with json.dumps:
Replace generate_summary with the earlier step’s outputVariable name.
Scripts on Daytona Sandbox
Daytona Sandbox provides the complete variable map as input and each variable with a valid name at the top level. In every language, the script prints its result, and the step parses the printed output as JSON when it is valid JSON:
Run code from a variable
To run code that an earlier step generated, set Input Mode to Variable (From template variable). In Script Variable, enter the variable that holds the code, such as {{generated_code}}.
Call tools from a script
When you select tools for the step, the code templates include Call a Tool. Each selected tool is an async function named after the tool, with hyphens and other special characters replaced by underscores, such as await my_tool({ query: input.searchQuery }). Tool calls work only on Cloudflare Worker (Default). On other environments, validation shows the TRANSFORM_POOL_TOOLS_ON_CONTAINER_PROVIDER warning and any tool call fails when the step runs.
Use authenticated APIs
Transform-data scripts cannot read managed secrets. Make authenticated requests in a Fetch URL or Make API Call step, then transform the response in a transform-data step. For more information, see Managing secrets.
Common transformations
Use the following patterns to transform arrays, objects, strings, and numbers. They use the input form for Cloudflare Worker (Default).
Filter and map arrays
Filter an array and create a new object for each remaining item:
Replace order_data with the variable that contains the order list.
Merge objects
Combine values from multiple sources into one object:
Replace customer_data and order_history with the variables that you want to merge.
Format strings
Create a name and a URL-friendly slug from contact information:
Replace contact_info with the variable that contains the contact information.
Calculate values
Calculate a cart subtotal, tax, and total:
Replace cart with the variable that contains the cart items.
Use available JavaScript features
JavaScript transform scripts support these features:
- Array methods such as
map,filter, andreduce. - Destructuring and spread operators.
- Arrow functions.
- Template literals.
async/awaitin every environment except QuickJS (Legacy).Dateobjects.Mathfunctions.JSON.parseandJSON.stringify.- Helper functions on Cloudflare Worker (Default) and QuickJS (Legacy).
External libraries are unavailable in Cloudflare Worker (Default) and QuickJS (Legacy). Choose Runtype Sandbox or Daytona Sandbox when your script needs packages.
Run a coding agent in the step
Runtype Sandbox preinstalls the opencode, pi, fx, claude (Claude Code), and codex (Codex) command-line coding agents. For versions and default models, see Preinstalled sandbox software. The agents can call models only when the step sets inference to true.
The Flow editor has no control for inference. Set it in the step’s config when you create the Flow through the API or manage it as code. For more information, see Manage flows as code.
The following step runs opencode from a Python script and prints its output:
Model access ends when the step returns or times out. Runtype bills the inference to the account that runs the Flow. If the script fails, the step follows its error-handling setting, as described in Handle errors.
Each agent selects a model with --model. The available models are:
@cf/zai-org/glm-5.2(default)@cf/moonshotai/kimi-k2.7-code@cf/openai/gpt-oss-120b
Coding agents often need more than the default 30 seconds. Raise the run’s step timeout, as described in Script time limits. Set Network Access to allow any host the agent needs to read. Model access works under every Network Access setting, including Blocked (default).
Other execution environments ignore inference. Only Runtype Sandbox has the container that these agents run in.
Handle errors
Transform-data steps continue after a script error by default. The step stores its configured default value in the output variable, or null when no default exists, and records the error on the step result.
To change this, open the step’s error-handling control and choose one of these options:
- Continue on error: Continue the Flow with the default value. This is the default.
- Stop on error: Stop the Flow when the step fails.
- Use fallbacks: Try the fallbacks that you configure before the step fails.
Wrap operations that can throw in try/catch when you want to return a structured result:
Replace raw_data with the variable that contains the JSON string. Use a downstream Conditional Logic step to branch on success.
To find why a step failed, open the step result in the run’s execution logs. For more information, see Debugging flows.
Test a transformation
To test a top-level transform-data step against variables from the last run, follow these steps:
- Run the Flow once.
- On the top-level step card, click the action menu (⋯).
- Choose Test with last run. The test sheet opens.
- Review the output and update the script if needed.
Follow best practices
Use these practices when you write transform-data scripts:
- Keep each transformation focused.
- Name each step and output variable to describe its result.
- Check for
nullandundefinedbefore you access properties. - Return the same structure from each successful run.
Next steps
Continue with these guides:
- Flow variables and templates: reference inputs and step outputs.
- Using conditional steps: branch on transformed values.
- Using fetch-url and api-call steps: fetch data before you transform it.
- Timeouts and long-running work: set step timeouts for long scripts.
- Debugging flows: inspect step results and logs.
- Flow validation warnings: resolve warnings about languages and tools on transform-data steps.
- Manage flows as code: define transform-data steps with the SDK.