> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://docs.itential.com/itential-platform/6/studio/tasks/reference/run-code/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.itential.com/_mcp/server. # runCode > Reference for the runCode workflow task, which executes a Python script within a workflow. Platform 6.4.0+ The `runCode` task executes a Python script directly in a workflow. Use it to replace combinations of existing canvas tasks, such as chains of [JSON Schema Transformations (JSTs)](/itential-platform/studio/transformations/overview), [query](/itential-platform/studio/tasks/reference/query) tasks, and [merge](/itential-platform/studio/tasks/reference/merge) tasks, with a single, readable Python script. The task uses Itential Gateway to create a virtual Python environment and execute the script. ## Prerequisites Before using the `runCode` task, ensure the following: * Install Gateway Manager 1.0.10 or later with Platform 6.4.0 or later. * Register an active Gateway 5.4.0 or later cluster with Itential Platform using Gateway Manager. For information, see [Create cluster in Gateway Manager](/itential-gateway/create-gateway-cluster). * Verify that the Python version on the Gateway 5 host is compatible with your scripts and packages. The task uses the default Python interpreter on the host, which is the version invoked by `python` or `python3` on the [iagctl command line](https://docs.itential.com/itential-gateway/5/iagctl/run-service-python-script). Gateway does not enforce a minimum version. To check, run `python --version` on the Gateway 5 host. * Confirm that the `gateway:code` role from **GatewayManager** is assigned to your group. Contact your administrator to have this role assigned. ## Potential use cases Use this task when existing canvas tasks become unwieldy for the logic you need to express. Common scenarios include: * Replacing a chain of JST tasks that extract, filter, and aggregate API response data * Performing data aggregation, calculation, or text processing on task outputs * Reshaping nested JSON structures for consumption by downstream tasks ## Task properties ### Incoming | Variable | Type | Required | Description | | ---------------- | ------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | | `clusterId` | String | Yes | The active Gateway 5 cluster that executes the script. | | `language` | String | Yes | The script language. Set to `python`. | | `code` | String | Yes | The Python script to execute. Limited to 2 MB. | | `safety.timeout` | Integer | Yes | Execution timeout in seconds. Range: 1–1000 seconds. Default: 1 second. | | `packages` | Array | No | A list of pip package specs to install into the virtual Python environment before execution. For example: `["requests>=2.28.0", "pandas==2.0.0"]`. | | `data` | Object | No | Input data for your script. Keys defined here are accessible in your script via `stdin`. | ### Outgoing The task returns all output fields as properties of the `result` outgoing variable. | Field | Type | Description | | -------------------- | --------------- | --------------------------------------------------------------------------------------------- | | `result.stdout` | String | Raw string of everything the script printed to `stdout`. | | `result.stdout_json` | Any | The `stdout` content parsed as JSON. Present only when `stdout` is valid JSON. | | `result.stderr` | String | Everything your script writes to `stderr`, including debug messages and exception tracebacks. | | `result.status` | String | Execution status: `completed` or `error`. | | `result.return_code` | Integer or null | Process exit code. `0` indicates success. | | `result.started_at` | String | ISO 8601 timestamp when execution started. | | `result.finished_at` | String | ISO 8601 timestamp when execution completed. | | `result.elapsed_ms` | Number | Server-measured execution time in milliseconds. | ### Error This field appears in the task response only when `result.status` is `error`. | Field | Type | Description | | -------------- | ------ | ---------------------------------------------------- | | `result.error` | String | Platform-specific failure reason, such as a timeout. | ## Use runCode in a workflow The following sections walk through configuring the task, mapping inputs from upstream tasks, and referencing outputs in downstream tasks. ### Configure the task The `runCode` task is configured across two surfaces: the task panel and the code editor. See [Configure and manage tasks](/itential-platform/studio/workflows/tasks/configure-manage-tasks) for the general task configuration pattern. #### Select a cluster In the task panel, select the active Gateway 5 cluster from the **Cluster** dropdown. #### Open the code editor Click **Open Editor** in the task panel. #### Add packages In the **Packages** tab, click **+ Add Package**. Enter the package name, select a version constraint, and enter a version number if needed. Gateway 5 installs packages from the public PyPI index by default. To restrict available packages, configure your Gateway 5 host at the OS or network level. #### Set the timeout Set a value in seconds in the **Timeout** field at the top of the editor. #### Write your script Write your Python script in the code area. To test before saving, click **Run Code**. The result appears in the **Outputs** tab. To test with specific input values, add key:value pairs in the **Inputs** tab. These values are saved across sessions but do not affect workflow execution. ### Configure data inputs Configure the keys and their sources in the task's **Data** tab. | Variable Source | When to use | | --------------- | ------------------------------------------------------------------------------------ | | `task` | Pass output from an upstream task. Also set **Previous Task** and **Task Variable**. | | `static` | Pass a hard-coded value. | | `job` | Pass a job variable. | For example, to pass the output of an upstream `getDevices` task into your script as `devices`, add a key named `devices` and set **Previous Task** to `getDevices` with the appropriate reference variable. ### Reference secrets in your script If your script needs a credential or other sensitive value, such as an API token or database password, you can reference an external secret alias instead of hard-coding the value. Gateway resolves the alias at execution time using the syntax `$GATEWAYSECRET_(alias-name)`. For example: ```python api_token = "$GATEWAYSECRET_(api-token)" ``` The secret value is never sent back to Itential Platform. To set up a secret provider and create aliases, see [External secrets overview](/itential-gateway/secrets/external-secrets/overview). ### Reference runCode output in downstream tasks To use the `runCode` output in a downstream task, configure that task's input with: * **Previous Task**: the `runCode` task * **Task Variable**: `result.stdout_json` for the parsed JSON result, or any other `result` field If you need a specific nested value from `result.stdout_json`, use a task query to extract it directly on the input field without adding a [query](/itential-platform/studio/tasks/reference/query) task to the canvas. See [Task query](/itential-platform/studio/workflows/tasks/configure-manage-tasks#task-query) for details. ## Errors and timeout The task catches unhandled Python exceptions and captures the traceback in `result.stderr`. The task still completes and the workflow does not follow the error transition. The **Timeout** (`safety.timeout`) stops execution if exceeded. When the timeout is exceeded, `result.status` becomes `error` and `result.error` contains the Platform-specific failure reason. The timeout applies to your code only, not to package installation. If the task cannot run on the gateway, for example, if the gateway is not enabled or loses connectivity, the task itself fails and no `result` output is produced. The error is visible in the task's **Error** tab in Operations Manager. For example: ```json { "state": "Error", "domain": "gateway_manager", "code": 503, "timestamp": "2026-04-28T16:20:02.092Z", "message": "Gateway with id test-code-task is not enabled" } ``` ## Size limit Code is limited to 2 MB. You cannot save code that exceeds this limit. The limit applies to code text only. Installed packages do not count toward it. ## Package caching The first time you run a task with a new set of packages, the runner installs them into a virtual environment. Subsequent runs reuse the cached environment, so there's no install overhead. Any change to the `packages` list triggers a fresh install. ## Example: filter a device list by status This example filters a list of devices to return only those with an `active` status. It replaces the equivalent JST filter operation with a single readable script. ### Data inputs Configure one key in the `data` object in the **Inputs** tab: | Key | Source | | --------- | ---------------------------------------------------------------- | | `devices` | Output of the upstream task that retrieves your device inventory | ### Sample input ```json { "devices": [ {"hostname": "router-01", "ip": "10.0.0.1", "status": "active"}, {"hostname": "router-02", "ip": "10.0.0.2", "status": "inactive"}, {"hostname": "switch-01", "ip": "10.0.0.3", "status": "active"} ] } ``` ### Script ```python import sys, json data = json.load(sys.stdin) devices = data.get('devices', []) # Keep only devices with an active status active_devices = [d for d in devices if d.get('status') == 'active'] print(json.dumps({'devices': active_devices, 'total': len(active_devices)})) ``` ### Output Downstream tasks access the result as `result.stdout_json`: ```json { "devices": [ {"hostname": "router-01", "ip": "10.0.0.1", "status": "active"}, {"hostname": "switch-01", "ip": "10.0.0.3", "status": "active"} ], "total": 2 } ``` ## Troubleshoot Use the following to troubleshoot errors and issues. ### Execution status vs. exit code `result.status` and `result.return_code` communicate different types of failure: * `status: completed` with `return_code: 0` means the script ran and exited cleanly. * `status: completed` with a non-zero `return_code` means the script ran but exited with a failure code. Your code executed; the script itself signaled failure. * `status: error` indicates a Platform-level failure, such as a timeout. The script may not have run, or it stopped mid-execution. Check `result.error` for details. Gateway connectivity failures produce a different outcome. The task itself errors and no result fields are populated, because a task failure is distinct from a task error. See [Errors and timeout](#errors-and-timeout). ### stdout\_json absent after a successful run If `result.stdout_json` does not appear after a successful execution (`return_code: 0`), the most common causes are: * `stdout` contained non-JSON content, a mix of JSON and other output, or no output * A type in the output object was not JSON-serializable, causing `json.dumps()` to raise a `TypeError` and write a traceback to `stderr` instead of JSON to `stdout` Inspect `result.stdout` and `result.stderr` directly to determine which applies. ## Related information * [Configure and manage tasks](/itential-platform/studio/workflows/tasks/configure-manage-tasks) > Reference for the runCode workflow task, which executes a Python script within a workflow.