---
title: Using the Script Native Action
slug: using-the-script-native-action
docTags: 
createdAt: 2025-08-11T11:13:48.000Z
---

## Overview

The Script native action executes Python code within a sandboxed environment. It provides access to standard Python libraries and pre-configured global variables for accessing inputs, setting outputs, and handling errors. Scripts run in isolated containers to ensure security and resource management.

## Key Benefits of the Script Action

- **Flexibility with Python:** Leverage Python 3 to manipulate data and handle edge cases.
- **Efficiency:** Reduces complexity compared to JSONata for simpler tasks.
- **Additional Libraries:** Beyond the Python standard library, scripts have access to `numpy`, `pendulum`, and `beautifulsoup4`.
- **Preloaded Libraries:** Access standard Python libraries including `json`, `datetime`, `math`, `csv`, `base64`, `hashlib`, `itertools`, `statistics`, and more.
- **Sandboxed Execution:** Scripts run in isolated containers for security and resource management.
- **Global Variables:** Pre-configured variables (`action_inputs`, `action_outputs`, `action_error`) simplify script development.
- **Attachment Support:** Built-in support for handling file attachments as inputs and outputs.

## Available Global Variables

The Script native action provides three global variables:

- `action_inputs`: A dictionary containing all input values passed to the script. Access inputs using `action_inputs["propertyName"]` or `action_inputs.get("propertyName")`.
- `action_outputs`: A dictionary used to set output values. Assign values using `action_outputs["outputName"] = value`.
- `action_error`: A dictionary that, when populated, will fail the action with the corresponding error payload. Set error information using `action_error["message"] = "Error description"`.
- `output_attachment`: A pre-injected global object used to create and return file attachments from a script. Call `output_attachment.open("filename.ext")` to open a writable file handle, then assign the handle to action\_outputs.

**Example:**

:::BlockQuote
*# Read an input value*
score = action\_inputs\["last\_malicious\_score"]*# Perform logic and write to outputs*
**if** score > 0.9:
&#x20;   action\_outputs\["verdict"] = "Malicious"
&#x20;   action\_outputs\["score"] = score
**else**:
&#x20;   action\_outputs\["verdict"] = "Clean"
&#x20;   action\_outputs\["score"] = score
:::

## Setting Up the Script Native Action

Here is how to configure a Script action in your playbook:

1. From the Add Panel, drag and drop the **Script** action onto the playbook canvas.
2. Click **Configure**, then **Add property** to define input data types (String, Number, Boolean, Object, Array, or Attachment).
3. Write your Python script in the provided field or select upstream playbook inputs using the property drawer.

::Image[]{src="https://app.archbee.com/api/optimize/511c8QBH-VHiwWnyzIwUb/iE3dg0CmEBbsUtJAgr6cJ_canvas-script.png" size="76" width="1082" height="652" darkWidth="1082" darkHeight="652" position="center" alt="Script Native Action Example" showCaption="false"}

### Script Inputs

Define static and dynamic inputs using the following supported types:

- **String**: Text values
- **Number**: Numeric values (integers or floats)
- **Boolean**: True/false values
- **Object**: JSON objects/dictionaries
- **Array**: JSON arrays/lists
- **Attachment**: File attachments

### Configuring Script Inputs

Follow these steps to set up your inputs:

1. Click **Add property** in the Inputs pane to define your inputs.
2. Rename properties as needed using the pencil icon.
3. Set input values by:
   - Entering static values directly
   - Selecting properties from upstream actions using the property drawer
   - Using expressions to reference playbook data
4. Write or paste your Python code in the Script pane.
5. Access inputs in your script using `action_inputs["propertyName"]`.

**Example:** In this example, a script evaluates a **last\_malicious\_score** to determine if it meets the **Malicious** score threshold:

::Image[]{src="https://app.archbee.com/api/optimize/511c8QBH-VHiwWnyzIwUb/Urk2_k1h28TKbkwGLtpbL_script-inputs-example.png" size="72" width="1800" height="850" darkWidth="1800" darkHeight="850" position="center" alt="Script Inputs Example" showCaption="false"}

### Outputs Tab

The **Outputs** tab enables promotion of action outputs for downstream use.

- **View Outputs**: See all outputs provided by the script action.
- **Mark Sensitive**: Click the ellipsis button (⋯) next to an output and select **Mark Sensitive** to mark sensitive data.
- **Delete Outputs**: Remove outputs that are not needed.

:::hint{type="info"}
Outputs are set in your Python script using `action_outputs["outputName"] = value`. The Outputs tab allows you to manage which outputs are promoted and marked as sensitive.
:::

### Script Testing

Want to test your Script action before continuing to build your playbook? In the Script action, from the **Test** tab:

1. **View Inputs**: See all configured inputs on the left side of the test panel.
2. **View Script**: See your Python code on the right side of the test panel.
3. **Modify Test Inputs**: Change input values to test different scenarios.
4. **Run Test**: Execute the script with the test inputs.
5. **View Results**: See the output in the Results pane at the bottom.

**Important Notes:**

- **Attachment Limitations**: Input attachment fields are not shown in the Test tab and cannot be used in test runs. You must perform a full playbook test to test input attachment handling. Output attachments can be tested directly in the Test tab.
- **Discovered Outputs**: Just like discovered outputs in an HTTP action, results vary. In addition to the base property types, depending on the inputs you select, the action outputs may return additional properties. These are the discovered outputs, which you can promote and/or delete from the Outputs tab.
- **Error Handling**: If your script encounters an error during testing, error details will be displayed in the Results pane.

See a [Script Test Use Case](#) for an example on testing the Script native action.

## Handling Attachments in Scripts

If you need to return an attachment or use an attachment as an input in the Script native action, follow the instructions below:

### Output Attachment

In your playbook, follow the instructions below to configure an output attachment:

1. Add a Script action to your playbook, title it (for example, **Return Attachment**), and click **Configure**.
2. In the **Script** pane, use the output\_attachment global to create and return a file. There are two equivalent styles:

**Context manager style (recommended):**

:::BlockQuote
with output\_attachment.open("report.txt") as f:
&#x20;   f.write("This is the attachment content.")
&#x20;   action\_outputs\["my\_file"] = f
:::

**Direct open/close style:**

:::BlockQuote
my\_file = output\_attachment.open("report.txt")
my\_file.write("This is the attachment content.")
action\_outputs\["my\_file"] = my\_file
:::

The string passed to output\_attachment.open() becomes the filename of the returned attachment. Assign the file handle to action\_outputs to make it available to downstream actions.

1. Click **Apply** to save changes.

### Input Attachment

You can use an attachment input in a Python script using a Script native action. Attachment inputs in action\_inputs are custom objects — call .open() on them to get a readable file handle and use the methods described below.

1. Add a Script action and click **Configure**.
2. In the **Inputs** pane, click **Add property** and select **Attachment**.
3. Rename the property (for example, **file1**) using the pencil icon.
4. Click **Select a property** and select the upstream attachment from the playbook property drawer.
5. In the **Script** pane, read the attachment using one of the following styles:

**Context manager style (recommended):**

:::BlockQuote
**with** action\_inputs\["file1"].open() **as** file1:
&#x20;   action\_outputs\["file1\_text"] = file1.read()
&#x20;   action\_outputs\["file1\_size"] = file1.size()
&#x20;   action\_outputs\["file1\_mimetype"] = file1.mimetype()
:::

**Direct open/close style:**

:::BlockQuote
file2 = action\_inputs\["file2"].open()
action\_outputs\["file2\_text"] = file2.read()
file2.close()
:::

**Available methods on an opened attachment handle:**

| Method        | Description                                                                  |
| ------------- | ---------------------------------------------------------------------------- |
| `.read()`     | Returns the file contents                                                    |
| `.size()`     | Returns the file size in bytes                                               |
| `.mimetype()` | Returns the MIME type of the file (for example, text/plain, application/pdf) |
| `.close()`    | Closes the file handle (called automatically when using with)                |

Click **Apply** to save changes.

:::hint{type="info"}
Attachment inputs are not shown in the **Test** tab. You must run a full playbook test to verify attachment input handling.
:::

### Testing the Script

Test your script in the **Test** tab before full integration. The results appear in the Results pane. This is useful for debugging and validating output.

See the [Script Test Use Case](#) for detailed examples.

## Available Python Libraries

Scripts have access to the full [Python 3.11 standard library](https://docs.python.org/3.11/library/index.html). In addition, the following non-standard libraries are pre-installed:

| Library        | Version |
| -------------- | ------- |
| numpy          | 1.26.4  |
| pendulum       | 2.1.2   |
| beautifulsoup4 | 4.12.3  |

:::hint{type="info"}
No other third-party packages can be imported. If you need a library not listed above, use the Python standard library equivalents or restructure your logic accordingly.
:::

## Hashing in Script Actions

Starting in Turbine 26.3.0, all connector actions—including the native Script action—run on FIPS-enabled images. To maintain compliance, avoid using non-FIPS-approved hash functions (such as MD5, MD5-SHA1, BLAKE2b, or BLAKE2s) for cryptographic or security operations.

Swimlane does not recommend using MD5, MD5-SHA1, BLAKE2b, or BLAKE2s in a Script action to compute or compare full file hashes. Do not use them for integrity checking, authentication, or digital signatures. For those cases, use a FIPS-approved algorithm such as SHA-256.

## Error Handling

You can handle errors in your script using the action\_error global variable. When action\_error is populated, the action fails with the error payload you provide. Use a try/except block to catch exceptions and surface meaningful messages to the playbook:

:::BlockQuote
**import** json**try**:
&#x20;   *# Validate that a required input is present*
&#x20;   **if** "target\_ip" **not** **in** action\_inputs:
&#x20;       action\_error\["message"] = "Missing required input: target\_ip"
&#x20;   **else**:
&#x20;       target\_ip = action\_inputs\["target\_ip"]
&#x20;       *# Perform processing*
&#x20;       action\_outputs\["result"] = f"Processed "**except** Exception **as** e:
&#x20;   action\_error\["message"] = f"Script failed with error:&#x20;
:::

:::hint{type="info"}
Once `action_error` is populated, the action stops and the On Failure path (if configured) is taken. Do not set both `action_outputs` and `action_error` in the same code path.
:::

## Troubleshooting

- **Script Fails with Import Error**: Custom package imports are not allowed. Use only standard Python libraries that are preloaded.
- **Input Not Found**: Use `action_inputs.get("propertyName", default_value)` to provide default values for optional inputs, or check if keys exist before accessing them.
- **Output Not Appearing**: Ensure you are setting outputs using `action_outputs["outputName"] = value`. Outputs must be set before the script completes.
- **Attachment Not Working**: Attachments cannot be tested in the Test tab. Use a full playbook test to verify attachment handling.
- **Boolean/Null Values**: All playbook data is JSON. Python does not natively support all JSON types (for example, `true`/`false`/`null` vs Python's `True`/`False`/`None`). Use `json.loads()` to parse JSON strings containing Boolean or Null values:

:::BlockQuote
**import** json\*# If the input arrives as a JSON string (for example, "true" or "null")\*
raw\_value = action\_inputs.get("is\_malicious", "false")
is\_malicious = json.loads(raw\_value)  *# Converts "true" → True, "null" → None*
:::

- **Type Errors**: Ensure you are using the correct data types. Use type conversion functions (int(), str(), float(), bool()) when needed.

## Best Practices

- **Start Simple:** Begin with straightforward scripts before moving to more complex logic.
- **Use Comments:** Comment your code for clarity and easier debugging. The script editor includes helpful comments about available global variables.
- **Test Frequently:** Use the Test tab to validate your script iteratively with different input values.
- **Handle Errors Gracefully:**
  - Use try-except blocks to catch and handle errors.
  - Use `action_error` to provide meaningful error messages.
  - Validate inputs before processing them.
- **Validate Inputs:** Check that required inputs exist and have valid values before using them:&#x20;

:::BlockQuote
**if** "severity" **not** **in** action\_inputs:
&#x20;   action\_error\["message"] = "Missing required input: severity"
**elif** **not** isinstance(action\_inputs\["severity"], (int, float)):
&#x20;   action\_error\["message"] = "Input 'severity' must be a number"
**else**:
&#x20;   action\_outputs\["level"] = "High" **if** action\_inputs\["severity"] > 7 **else** "Low"
:::

- **Use Default Values:** Use `.get()` method with default values for optional inputs:

:::BlockQuote
threshold = action\_inputs.get("threshold", 0.9)
description = action\_inputs.get("description", "No description provided")
:::

- **Keep Scripts Focused:** Write scripts that do one thing well. Break complex logic into multiple Script actions if needed.
- **Document Your Scripts:** Add comments explaining what the script does, especially for complex logic or business rules.
