> For the complete documentation index, see [llms.txt](https://stage-precision.gitbook.io/grid/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://stage-precision.gitbook.io/grid/scripting/workflow-script-actions.md).

# Workflow Script Actions

### Adding a Workflow Script Action

To add a Script Action, open a Workflow and secondary-click anywhere in the Node Editor.

Select **Script** from the Action menu to create a new Workflow Script Action.

<div align="left"><figure><img src="/files/yaaWbMAcwiU4FjhUHbWV" alt="" width="563"><figcaption></figcaption></figure></div>

The Script Action is added directly to the Workflow and can then be connected to other Events and Actions.

### Opening the Script Editor

Select the Script Action in the Workflow to display its settings in the Inspector.

The script is shown directly in the **Action** tab.

Click the **Script Editor** button in the upper-right corner of the script panel to open the full Script Editor.

<div align="left"><figure><img src="/files/7asLcJlfSqG5A90HEB2v" alt="" width="329"><figcaption></figcaption></figure></div>

This is where the Python code for the Workflow Script Action can be edited.

<div align="left"><figure><img src="/files/djIpz6bT5OxWUkNaSb4y" alt="" width="563"><figcaption></figcaption></figure></div>

### Saving Workflow Scripts

Workflow Scripts should be saved after making changes in the Script Editor.

{% hint style="info" %}
Make sure to save changes made to a Workflow Script before closing the Script Editor.
{% endhint %}

<div align="left"><figure><img src="/files/2xGnr4kOsiksGM3qFoVL" alt="" width="563"><figcaption></figcaption></figure></div>

### How Workflow Script Actions Work

Unlike Script Modifiers, Workflow Script Actions do not use configurable Parameter-based input pins.

Instead, the script receives the data that is currently available within the Workflow and can access it dynamically by its data path.

A Workflow Script Action uses the following function:

```python
def action(data, callback):
    pass
```

The `data` function provides access to incoming Workflow data, while `callback()` is used to continue execution through one of the Action's output branches.

### Accessing Workflow Data

Workflow Script Actions can access the data currently available at their position in the Workflow using:

```python
data("path/to/data")
```

For example:

```python
def action(data, callback):
    print(data("Event/time"))
```

The available data depends on the current Workflow context and can grow as previous Actions add additional data.

#### Finding the Correct Data Path

To inspect the data available to a Script Action, open the **Data** panel in the Workflow Editor.

Click the left-most icon in the toolbar at the bottom of the Workflow Editor to show the Data panel.

<div align="left"><figure><img src="/files/tftfibXj9cAGLdNmKyF4" alt="" width="563"><figcaption></figcaption></figure></div>

The Data panel displays the complete data tree currently available at the selected position in the Workflow.

{% hint style="info" %}
Workflow data can change and grow as Actions add additional values.

To inspect the data available to a specific Script Action, select that Action and execute the Workflow at least once before checking the Data panel.
{% endhint %}

Once the correct data is visible in the tree, secondary-click the required entry and select: **Copy Tree Path**

<div align="left"><figure><img src="/files/eynEdclVgDVX3UuT2Nse" alt="" width="364"><figcaption></figcaption></figure></div>

The copied path can then be used directly with the `data()` function.

For example, copying the tree path for the Event time results in:

```python
data("Event/time")
```

This is the recommended way to find the correct data path instead of manually constructing it.

### The Callback Function

The `callback()` function is used to return data and control how execution continues through the Workflow.

It uses the following structure:

```python
callback(result, failed, outPinIndex, finished)
```

The arguments control the returned data and execution flow:

* `result` — data returned to the Workflow
* `failed` — determines whether the regular output or the Error output is triggered
* `outPinIndex` — selects which regular output pin is triggered
* `finished` — determines whether the Script Action has finished its calculation

#### Result Data

The `result` passed to `callback()` can be either a standard Python `dict` or an `sp.ValueTree`.

Using a Python dictionary:

```python
result = {
    "someData": 1
}

callback(result, False, 0, True)
```

Using an `sp.ValueTree`:

```python
result = sp.ValueTree("root")
result["someData"].value = 1

callback(result, False, 0, True)
```

Both formats can be used to return structured data to the Workflow.

#### Selecting an Output

When `failed` is `False`, `outPinIndex` determines which regular output pin is triggered.

For example:

```python
callback(result, False, 0, True)
```

triggers **Output 0**.

```python
callback(result, False, 1, True)
```

triggers **Output 1**.

`Output 0` is always the first regular output pin.

#### Triggering the Error Output

When `failed` is set to `True`, the **Error** output is triggered.

```python
callback(result, True, 0, True)
```

In this case, `outPinIndex` is ignored.

#### Finishing the Script Action

The `finished` argument determines whether the Script Action has completed its calculation.

When `finished` is `True`, the Script Action finishes and releases the Workflow execution chain that is waiting for the Action to complete.

```python
callback(result, False, 0, True)
```

When `finished` is `False`, the Script Action remains open and additional callbacks can be triggered before it is finished.

### Multiple Callbacks

A Workflow Script Action can call `callback()` multiple times before completing.

For example:

```python
def action(data, callback):
    result = sp.ValueTree("root")

    result["someData"].value = 1
    callback(result, False, 0, False)

    result["someData"].value = 2
    callback(result, False, 0, True)
```

The first callback triggers **Output 0** with `someData` set to `1`, but does not finish the Script Action.

The second callback triggers **Output 0** again with the updated data and sets `finished` to `True`, completing the Script Action.

{% hint style="info" %}
A Workflow Script Action keeps the Workflow execution chain waiting until a callback is sent with `finished` set to `True`.
{% endhint %}

### Output Pins

The number of output pins for a Workflow Script Action is configured directly in the Inspector.

Select the Script Action and open the **Action** tab. Use **Output Pins** to define how many regular output branches the Action should provide.

<div align="left"><figure><img src="/files/bYsUDDD0hI1hMq52pAdL" alt="" width="329"><figcaption></figcaption></figure></div>

The outputs are created automatically and are named:

```
Output 0
Output 1
Output 2
...
```

The output that should be triggered is selected from the script using the `outPinIndex` argument of `callback()`.

For example:

```python
callback(result, False, 0, True)
```

triggers **Output 0**.

To trigger **Output 1** instead:

```python
callback(result, False, 1, True)
```

The output pins are primarily used to branch Workflow execution. Data itself is passed through the `result` returned by `callback()`.

{% hint style="info" %}
An **Error** output is always available in addition to the configured regular output pins.
{% endhint %}

### When to Use Workflow Script Actions

Workflow Script Actions are useful when custom Python logic needs to work directly with Workflow data.

Typical use cases include:

* Reading dynamic Event or Action data
* Processing or transforming Workflow data
* Creating additional data for following Actions
* Branching Workflow execution based on custom logic
* Returning structured data into the Workflow
* Implementing logic that is not available through existing Actions

For reusable scripts that should exist independently in the Project Tree and be executed from different locations, use a **Project Script** instead.
