Skip to main content

Python Scripting in Torq Workflows

Add custom Python logic to workflows for flexible, advanced automation

Updated yesterday

Python scripting allows you to incorporate familiar coding patterns directly into your workflows. You can write and execute your own Python logic to process data, apply conditions, or extend automation capabilities beyond built-in actions. This flexibility makes it easy to adapt workflows to complex or unique business requirements.

Torq offers four Python scripting steps to integrate seamlessly into your workflows, giving you the flexibility to reuse existing Python code or build custom logic to meet your automation needs.

All Python script steps come with:

  • Python Standard Library

  • pyOpenSSL

  • crcmod

  • requests

You can also use the optional REQUIREMENTS variable to install additional packages as needed.

Available Script Steps

  • Run an inline Python Script: Ideal for general-purpose scripting and API interactions. Includes Python 3.13 with the standard set of pre-installed packages listed above.

  • Run a Python Data Processing Script: Best for data wrangling, transformation, and Excel file manipulation. Extends the base environment (Python 3.11) with the following additional packages:

    • pandas

    • numpy

    • openpyxl

  • Run a Python Script with Database Tools: Useful for querying, inserting, or analyzing data stored in external databases. Includes all packages from the Data Processing step, plus database connectivity tools:

    • psycopg (PostgreSQL)

    • PyMySQL (MySQL)

    • pymssql (Microsoft SQL Server)

  • Run a Python IOC Extraction Script: Perfect for extracting Indicators of Compromise (IOCs) and structuring threat-related data. Specialized for security automation and threat intelligence parsing, pre-installed with Python 3.9 and the following packages:

    • ioc-finder

    • msticpy

    • pydantic

    • jinja2

    • ruamel.yaml

    • python-json-logger

Working with Python Scripts in Workflows

Python scripting in Torq workflows often involves passing data between steps, printing values for visibility, returning parameters for use downstream etc. To help you get started, this section includes practical script samples that show common patterns.

Passing Values from Previous Steps into a Python Script

To use a value from a previous step in your Python script, Torq supports the following templating syntax:

{{ $.<step_name>.<output_field> }}

When configuring your Python step, simply paste your script into the input field and reference variables using this format. A string can be enclosed in single quotes "...", but if it contains newlines, it must be wrapped in triple quotes """...""". JSON data doesn’t always need to be treated as a string, it depends on the script and how the input is being handled.

Examples

  • If you have a step named get_data and want to access its result output, your script would look like:

    data = """{{ $.get_data.result }}""" 
    print(f"Data from previous step: {data}")
  • If you have a previous step named "Get IP Information" and want to print its result, your Python script would look like this:

    print("IP Information:", $.get_ip_information.result)

Use the autocomplete feature when typing {{ $... to quickly locate and insert the correct variable path.

Returning a Parameter from a Python Script in Workflows

To pass a value from a Python script to subsequent steps in your Torq workflow, follow these steps:

  1. Add a Python Step: Go to the Scripting category under Public steps, and drag the Python step into your workflow.

  2. Write Your Script:

    • In the script editor, write your logic as needed.

    • Assign the value you want to pass to a variable.

    • Use the print() function to return that value. For example:

    result = "Hello, Torq!" print(result)

    Torq captures anything printed to stdout, making it accessible to later steps.

  3. Access the Output in the Next Step:

    • In any subsequent step, reference the Python step’s output using the $. notation.

    • Use autocomplete to easily construct the correct path.

    • For example, if your Python step is named "My Python Step", you can access its output like this:

    $.my_python_step.stdout
  4. Test Your Workflow: Run the workflow to ensure the Python script's output is correctly passed and available to the next step.

  5. Pass Output Downstream with an Exit Operator (Optional):

    • Add or edit the Exit operator in your workflow.

    • Create an output schema:

      • Add parameters (e.g., summary, score, success_flag).

      • Choose the correct type: Text, Number, Boolean, etc.

      • Optionally add a short description for clarity.

    • Reference values from your Python step (e.g., {{ $.my_python_step.stdout }}) in your Exit fields.

Make sure all Exit operators in your workflow are aligned in structure to ensure smooth output handling.

Throwing an Exception with a Successful Step Status in Inline Python

Sometimes you might want a Python step to raise an error but still exit with a successful status (code 1) so that the workflow continues. This is useful for logging exceptions, skipping logic, or controlling flow without halting the automation.

  1. Raise an exception in your inline Python code:

    raise Exception("Something went wrong, but keep going.")
  2. Set the step's execution to ignore failure:

    • In the step configuration, go to Execution Options.

    • Set Ignore failure to Yes.

By raising an exception and ignoring the failure, the step will complete with a status code of 1, which Torq interprets as a successful execution, even though the Python code encountered an issue. This lets the workflow proceed while still capturing the error event.

Making Inline Python Exit Gracefully in Workflows

When using inline Python in Torq workflows, it’s important to ensure your scripts exit cleanly and produce readable output. A graceful exit means no unnecessary errors, no cluttered logs, and consistent behavior for downstream steps. These practices help your Python code run smoothly within the workflow, exiting without unintended exceptions, outputting only the data you want, and maintaining clean, predictable logs that integrate seamlessly with subsequent steps.

Format Lists for Output

If you’re printing a list or multiple elements, consider joining them into a single string:

limited_usernames_str = ''.join(limited_usernames) print(limited_usernames_str)

This gives you a flat, clean output without Python list formatting artifacts like brackets or commas.

Set Variables and Output Readably

You can set variables within the script to structure your logic before outputting results. For example:

ADDRESSES = ["1600 Pennsylvania Avenue", "10 Downing Street", "75 Rue de Varenne"] 
print(f"Got {len(ADDRESSES)} addresses")
for address in ADDRESSES:
print(address)

This approach helps you provide helpful context, control output structure, and keep logs clean, all while exiting without error.

Importing a Workspace Variable in a Python Step

You can use workspace variables in Python steps just like other dynamic inputs in a Torq workflow. This lets you reference shared, environment-specific values such as API tokens, org-wide configurations, or custom constants without hardcoding them.

This is useful for:

  • Keeping sensitive info centralized and reusable

  • Making workflows more portable across environments

How to Use a Workspace Variable

To access a workspace variable inside a Python script:

  1. Use the syntax {{ $.workspace_variables.VARIABLE_NAME }}.

  2. Paste it directly into your Python code where the value is needed.

Example

Let’s say you have a workspace variable named API_KEY. You can use it like this in your Python step:

api_key = "{{ $.workspace_variables.API_KEY }}" 
print(f"My API key is: {api_key}")

Exporting a List from a Python Script

If you need to pass a list created in a Python script to other steps in your workflow, you can do so by using the Set a Variable step right after your Python step. This lets you easily reuse structured list data across your workflow, such as for loops, filtering, or sending notifications.

  1. Create your list in a Python step: Write and print your list in the Python scripting step. For example:

    usernames = ["alice", "bob", "carol"] 
    print(usernames)
  2. Add a “Set a Variable” step: Drag the Set a Variable step onto your canvas after the Python step.

  3. Configure the variable:

    • Choose a name for the variable (e.g., user_list).

    • Set the data type to Array.

    • Use the Python step’s output (e.g., {{ $.python_step.stdout }}) as the value.

  4. Install packages if needed: If your Python script relies on additional packages, use the REQUIREMENTS variable to list them.

Checking the File Format of Python Step Output

When your Python script generates output that’s best handled as a file (e.g., CSV, PDF, or image), you can use the Return Response as File option in Torq to treat the output accordingly. For details on handling files in Torq workflows, refer to the relevant KB article.

  1. Enable File Output: In your Python step’s Execution Options, set “Return Response as File” to Yes.

  2. View the Output: After the step executes, the result will include a file URL, typically in one of the following formats:

    • Internal: tqfile://steps/XXXXXXX

    • Shareable: https://link.torq.io/***dEjnLCXnv7

  3. Check File Metadata: Open the Execution Log to see the file’s metadata, including the ContentType (e.g., application/pdf, image/png, text/csv).

  4. Access File in Next Step: Use the following expression in downstream steps to work with the file:

    {{ file $.step_name.api_object.url }}

    Use the file function when working with internal links; it isn’t required for shareable links.

Use Cases

  • Exporting reports as Excel or CSV files

  • Generating PDFs with summaries or charts

  • Handling binary outputs like images or logs

This approach is ideal for workflows with large or structured data output, and ensures smooth file handling from generation to downstream usage.

Related Resources

Using Nested JSON in Python Scripts within Workflows

Using nested JSON in Torq’s Python scripting steps is straightforward if you apply the right formatting and escaping rules. Make sure to escape JSON only when there’s a risk that the structure could break (for example, if it contains special characters).

If your JSON is already valid and properly formatted, you don’t need to escape or unescape it, just parse it directly in your script.

  1. Escape Your JSON String:

    • To prevent syntax errors or code injection, your JSON string must be properly escaped.

    • Use the jsonEscape function or the Escape JSON string step in the String Utils section to prepare your data.

  2. Load JSON in Python: Once escaped, use json.loads() to convert the JSON string into a Python object for manipulation. For example:

    import json  

    json_data = json.loads('''{{ $.your_json_data }}''')

    # Access nested values like:
    # json_data['key']['nested_key']
  3. Replace Placeholder: Be sure to replace your_json_data with the actual path to your JSON data (e.g., another step’s output).

Once loaded, you can use standard Python operations to loop through arrays, extract keys, or transform the data into other formats such as CSV.

Related Resources

Triggering Torq Webhook with Authentication from Python

You can trigger a Torq Webhook directly from a Python script. This is useful for testing, integrating external systems, or extending workflow functionality. Torq Webhook authentication headers are fully configurable, allowing you to define any header key-value pair as your auth method.

The example below shows how to configure your Webhook URL, authentication headers, and JSON payload in Python. If your Webhook does not require authentication, simply remove the headers=headers part of the requests.post() line.

import requests import json  

# Define the URL to which the JSON data will be sent
url = "{{ $.workflow_parameters.url_for_torq_webhook }}"

# Define the JSON payload you want to send
data = {{ $.workflow_parameters.json_to_send }}

# Define the Header Auth payload you want to send
headers = {
'{{ $.workflow_parameters.torq_auth_header_name }}':
'{{ $.workflow_parameters.torq_auth_header_secret }}'
}

# Send a POST request with the JSON data
response = requests.post(url, headers=headers, json=data)

# Capture and print the response status code
status_code = response.status_code
print(json.dumps({'Status Code': status_code}))

Resolving null Reference Errors in Inline Python Scripts

If you encounter the error NameError: name 'null' is not defined in an inline Python script step, it means Python is trying to interpret null. Unlike JSON, Python doesn’t recognize null, it uses None to represent a null or empty value. Replacing null with None in your script will resolve the issue and allow the workflow to run correctly.

This error also occurs if you directly reference the output of a step inside a Python script to create a JSON variable. For example:

json_data = {{ $.collect_ip_reputation.result }} print(json.dumps(json_data), end=' ')

The following error message will be displayed: NameError: name 'null' is not defined.

Fix

The simplest way to resolve this error when working with JSON data is to load the data into your Python script as a multi-line string, then parse it properly using Python’s json.loads(). This makes sure JSON values like null are properly converted into Python’s None, ensuring clean, valid JSON parsing within your Torq workflow.

import json  
string_json_data = '''
{{ $.collect_ip_reputation.result }}
'''
json_data = json.loads(string_json_data)
print(json.dumps(json_data), end='')

Handling the Unexpected Newline in Python Print Statements

When writing Python scripts in Torq workflows, you may sometimes notice an extra newline character (\\n) appearing in your output. This happens because Python’s built-in print() function automatically appends a newline at the end of its output. While this is convenient in many cases, it can disrupt formatting, especially if you build strings from multiple elements or need compact output.

Solution: Control Newlines with end

To prevent the default newline, you can use the end argument in print(). For example:

usernames = ["Alice", "Bob", "Charlie"]  

# Default behavior (adds a newline)
print(usernames)

# Suppressing the newline
print(usernames, end='')

Here, end='' overrides the default newline, so the output prints inline.

Alternative: Join Elements with join()

If you need to combine list elements into a single string, the join() method is often a better choice. For example:

limited_usernames = ["David", "Emily", "Fred"] 

# Join elements into a single string
limited_usernames_str = ''.join(limited_usernames) print(limited_usernames_str)

This approach gives you more control over separators (e.g., commas, spaces, or no separator at all) and avoids unwanted line breaks.

Extra Tip: Debugging with pprint

If your goal is debugging rather than formatting output, consider using Python’s pprint library. It provides a more detailed representation of data structures, though it may not be ideal for final output formatting.

Did this answer your question?