Reference action outputs, webhook payloads, secrets, and more.
Expressions is how you reference and manipulate data inline in action inputs, run-if conditions, loop expressions, and output schemas.
Tracecat supports the following expression contexts:
Prefix
Expression syntax
Description
ACTIONS
ACTIONS.<action_slug>.result.<jsonpath>
Reference the result of an action
TRIGGER
TRIGGER.<jsonpath>
Reference data passed via webhook or UI
SECRETS
SECRETS.<name>.<key>
Reference a secret
FN
FN.<fn_name>(<arg1>, <arg2>, ...)
Call an inline function
To use an expression, you must use the ${{ <context>.<expression> }} syntax:
${{ <context>.<expression> }}
Expressions are evaluated into values at the start of each action run.
You can reference outputs from a previous action in the same workflow using the ACTIONS context.
Actions are referenced by a sluggified version of their name.
1
Rename action
For example, let’s assume you renamed the core.http_request action in Your first workflow from HTTP Request to Get weather.
You can rename the action under the General section in the action inputs panel.
2
Reference action output
You can then reference the Get weather action’s output in the next action by using the ACTIONS.get_weather.result expression.
For example, you can use the core.transform.reshape action as a pass-through action to extract and organize the weather data.
Check out the workflow triggers tutorial for a detailed guide setting up webhooks for workflows.
Workflows can be triggered via webhook, manual UI trigger, or the Execute child workflow action.
Use the TRIGGER context to reference the data from the trigger as a JSON object.
1
Send webhook
For example, if you send a POST request to the workflow’s webhook URL with the following payload:
{"lat": 40, "long": 70}
2
Reference webhook payload
You can reference the lat and long values in an action’s inputs using the TRIGGER context.
Given a workflow with a live webhook, the following curl command will send the JSON payload {"data": {"name": "John", "age": 30}} and trigger the workflow:
Tracecat comes with a built-in secrets manager.
This allows you to store and retrieve sensitive data scoped to a workspace without exposing the value in plaintext.
Secrets are encrypted at rest and stored in the database.
Secrets stored in the secrets manager can be accessed using the SECRETS prefix:
${{ SECRETS.<name>.<key> }}
Tracecat will automatically replace the expression with the secret value at runtime.
Retrieved secrets are deleted from memory after the workflow run completes.
Check out the full list of supported functions in the functions cheatsheet.
Tracecat supports inline functions in the FN context.
Here are some examples of functions you can use with FN:
For the following function examples, we’ll use the Example alert JSON as sample data.
Feel free to copy and paste this into your own workflow to follow along.
# --- JSON Processing ---# Parse a JSON string into an objectresult: ${{ FN.deserialize_json(ACTIONS.get_alert.result.raw_data) }}# Convert an object to a JSON stringresult: ${{ FN.serialize_json(ACTIONS.transform_data.result) }}# Format JSON for readabilityresult: ${{ FN.prettify_json(ACTIONS.get_alert.result.alert) }}# Safely access a potentially missing propertyresult: ${{ FN.lookup(ACTIONS.get_alert.result.alert.user, "department") }}# Convert a list of objects into an object indexed by a given key ("timestamp")result: ${{ FN.index_by_key(ACTIONS.get_alert.result.alert.events, "timestamp") }}# Convert a list of objects into an object with key ("timestamp") and value ("action")result: ${{ FN.index_by_key(ACTIONS.get_alert.result.alert.events, "timestamp", "action") }}# Merge multiple objectsresult: >- ${{ FN.merge([ ACTIONS.get_user_info.result, ACTIONS.get_device_info.result, {"alert_id": ACTIONS.get_alert.result.alert.id} ]) }}# --- Date/Time Processing ---# Convert ISO string to datetimeresult: ${{ FN.to_datetime(ACTIONS.get_alert.result.alert.created_at) }}# Format a datetimeresult: ${{ FN.format_datetime(ACTIONS.get_alert.result.alert.created_at, "%Y-%m-%d %H:%M:%S") }}# Convert datetime to timestamp (seconds since epoch)result: ${{ FN.to_timestamp(ACTIONS.get_alert.result.alert.created_at) }}# Calculate time difference in hoursresult: >- ${{ FN.hours_between( ACTIONS.get_alert.result.alert.additional_context.last_successful_login, ACTIONS.get_alert.result.alert.created_at ) }}# --- Text Processing ---# Extract text using regexresult: ${{ FN.regex_extract("<timestamp>(.*?)</timestamp>", ACTIONS.get_alert.result.alert.raw_logs) }}# Transform textresult: ${{ FN.uppercase(ACTIONS.get_alert.result.alert.title) }}# --- IP Addresses ---# Check IP address versionresult: ${{ FN.check_ip_version(ACTIONS.get_alert.result.alert.source_ip) }}# Check if an IP is publicresult: ${{ FN.ipv4_is_public(ACTIONS.get_alert.result.alert.source_ip) }}# Check if an IP is privateresult: ${{ FN.ipv4_is_private(ACTIONS.get_alert.result.alert.source_ip) }}
Check out the docs on Data manipulation to learn more about the different data types and how to manipulate them.