Compound Action Syntax Reference
Executables
action
(Execute HTTP Requests or Native Actions)
Description: Actions are fundamental tasks the bot can perform, like creating a ticket or searching for a user. They are the basic capabilities that allow the bot to interact with external systems or perform operations.
Schema:
- action:
action_id: ACTION_UUID
output_key: OUTPUT_VARIABLE
input_args:
input1: INPUT_VARIABLE_1
input2: INPUT_VARIABLE_2
progress_updates:
on_pending: PENDING_MESSAGE_STRING
on_complete: COMPLETION_MESSAGE_STRING
Fields:
-
action_id:
The unique identifier for the action to be executed.
-
Type:
uuid
- Mandatory: Yes
-
Type:
-
output_key:
A variable to store the result of the action.
-
Type:
any
- Mandatory: Yes
-
Type:
-
input_args:
A dictionary mapping input arguments to their values, allowing for dynamic inputs to the action.
-
Type:
dictionary
{}
- Accepts bender syntax Bender v2 101 Handbook - Mandatory: No
-
Type:
-
progress_updates:
An object containing messages to update the user on the action's progress, including messages for pending and completed states.
-
Type:
dictionary
{on_pending: text, on_complete: text}
- Mandatory: No
-
Type:
Example Usage 1:
- action:
action_id: fetch_user_details# Example UUID for fetching user details
output_key: user_details
input_args:
user_id: data.user_id # Assuming user_id is stored in data
progress_updates:
on_pending: "Fetching user details, please wait..."
on_complete: "User details fetched successfully."
This action fetches user details based on a given user ID. While the action is in progress, it informs the user that their request is being processed. Once completed, it confirms the successful retrieval of user details.
Additionally, the API response will be stored in the user_details
variable, ready for use in subsequent steps of the Compound Action.
Result:
user_details: {
"user_id": "abc123",
"user_name": "John Doe",
"email": "john.doe@example.com"
}
script
(Execute Scripts)
Description: The script
expression allows users to write and execute custom code within the compound action, offering a flexible way to perform complex operations or data manipulations. This is particularly useful for tasks that require custom logic or processing that isn't covered by standard actions.
Supported Languages: APIthon (Python)
Schema:
script:
code: "input_var_1 + input_var_2"
input_args:
input_var_1: INPUT_ARG_VALUE_1
input_var_2: ...
...
output_key: SCRIPT_RESULT
script:
action_id: my_python_script
input_args:
input_var_1: INPUT_ARG_VALUE_1
input_var_2: ...
...
output_key: SCRIPT_RESULT
Fields:
-
code:
The Python code to be executed.
-
Type:
string
- Mandatory: Yes
-
Type:
-
output_key:
A variable to store the result of the script's execution.
-
Type:
any
- Mandatory: Yes
-
Type:
-
input_args:
A dictionary mapping input argument variables to their values, allowing for dynamic inputs to the script.
-
Type:
dictionary
- Mandatory: No
-
Type:
Example Usage 1: Clean a list of objects
- script:
output_key: cleaned_events
input_args:
events: data.gcal_output.items
code: "[{'htmlLink': event.get('htmlLink'), 'description': event.get('description'), 'summary': event.get('summary')} for event in events]"
This compound action takes a list of events and extracts only the htmlLink
, description
, and summary
fields for each event, creating a simplified list of event details.
Result:
cleaned_events: [
{
"htmlLink": "https://example.com/event1",
"description": "Team meeting",
"summary": "Discuss project updates"
},
{
"htmlLink": "https://example.com/event2",
"description": "Client call",
"summary": "Review contract details"
}
]
Description: The script processes each event in the input list, extracting the htmlLink
, description
, and summary
fields, and stores the cleaned list of events in cleaned_events
.
Example Usage 2: Add two numbers using a script.
- script:
output_key: addition_result
input_args:
a = 1
b = 2
code: "a + b"
This Script performs a simple addition of two numbers (1 and 2) and stores the result (3) in additional_result
Result:
stats: 3
Example Usage 3: Process a list of numbers and get statistics from the list using a multiline Python script.
- script:
output_key: stats
input_args:
numbers: [1, 2, 3, 4, 5, 6]
code: >
sum_numbers = sum(numbers)
count_numbers = len(numbers)
average = sum_numbers / count_numbers
stats = {'sum': sum_numbers, 'count': count_numbers, 'average': average}
This compound action calculates the sum, count, and average of a list of numbers. It demonstrates how to perform multiple operations within a script, showcasing the use of variables and basic arithmetic operations to compute statistics, which are then stored as a dictionary in stats
.
Result:
stats: {
"sum": 21,
"count": 6,
"average": 3.5
}
The script calculates the sum (21
), count (6
), and average (3.5
) of the given list of numbers [1, 2, 3, 4, 5, 6]
and stores these statistics in a dictionary under stats
. This result demonstrates how multi-line Python scripts can be utilized within compound actions to perform complex data processing and aggregation tasks.
Calls and Controlling Flow
switch
(Conditional Statements)
Description: The switch
expression functions like an if/else or switch/case statement in traditional programming, allowing for multiple conditions to be evaluated. If a condition is true, the compound action will execute the steps defined under that condition. If no conditions are true, the compound action will execute the steps defined under default
, if any.
Schema:
- switch:
cases:
- condition: BOOLEAN_CONDITION
steps:
- EXPRESSION_1
- condition: SECOND_BOOLEAN_CONDITION
steps:
- EXPRESSION_1
- EXPRESSION_2
default:
- EXPRESSION_2
Fields:
-
cases
: A list of conditions and their corresponding steps.
-
Type:
list[conditions]
- Mandatory: Yes
-
Type:
-
condition
: The boolean expression that needs to be evaluated.
-
Type:
boolean
- Mandatory: Yes
-
Type:
-
steps
: The steps to be executed if the condition is true.
-
Type:
list[expression]
- Mandatory: No
-
Type:
-
default
: The steps to be executed if none of the conditions are true. If omitted, defaults to no operation (noop).
-
Type:
list[expression]
- Mandatory: No
-
Type:
Example Usage 1:
- switch:
cases:
- condition: mapped_value.record_id == data.requestor_info.requestor_record_id
steps: []
default:
- action:
action_id: send_plaintext_chat_notification
output_key: requested_for_notification
input_args:
user_record_id: mapped_value.record_id
message:
RENDER():
template: "Hey {{ mapped_value.first_name }},\n{{ data.requestor_info.requestor.full_name }} just added you to the {{ data.group.name }} mailing list. You can now receive emails sent to this group.\nThis request is tracked in {{ data.resolve_ticket.ticket.id }}."
In this example, we check if the record_id
from mapped_value
matches the requestor_record_id
from data.requestor_info
. If they match, no steps are executed (steps: []
signifies an empty action). However, if the condition is not met (meaning the record_id
does not match), the compound action defaults to sending a plaintext chat notification using the send_plaintext_chat_notification
action. The message dynamically includes names and group information, informing the user that they have been added to a mailing list and providing a ticket ID for reference. This example demonstrates how switch
can be used for conditional logic and actions within a compound action.
Example Usage 2:
- switch:
cases:
- condition: data.user.access_level == 'admin'
steps:
- action:
action_id: send_admin_welcome
output_key: admin_welcome_notification
input_args:
user_id: data.user.id
message: "Welcome, Admin! You have full access to the admin dashboard."
- condition: data.user.access_level == 'member'
steps:
- action:
action_id: send_member_welcome
output_key: member_welcome_notification
input_args:
user_id: data.user.id
message: "Welcome, Member! Explore your member benefits in your profile."
default:
- action:
action_id: send_generic_access_notification
output_key: generic_access_notification
input_args:
user_id: data.user.id
message: "You're set! Start exploring your new account."
This compound action sends different welcome messages based on the user's access level. Admins receive a message about accessing the admin dashboard, members are informed about their benefits, and all other users receive a generic welcome message.
Example usage 3:
- switch:
cases:
- condition: data.temperature <= 5
steps:
- action:
action_id: alert_cold_temperature
output_key: cold_temp_alert
input_args:
message: "Alert: Temperature is very cold! Ensure heating systems are operational."
- condition: data.temperature > 5 and data.temperature <= 25
steps:
- action:
action_id: log_moderate_temperature
output_key: moderate_temp_log
input_args:
message: "Temperature is moderate. No action required."
default:
- action:
action_id: alert_high_temperature
output_key: high_temp_alert
input_args:
message: "Alert: High temperature detected! Ensure cooling systems are operational."
This compound action categorizes temperature readings into three categories: Cold (≤ 5°C), Moderate (> 5°C and ≤ 25°C), and Hot (> 25°C). Depending on the category, it triggers different actions: sending alerts for cold and hot temperatures, and logging a message for moderate temperatures.
for
(iteration/looping)
Description: The for
expression functions as a foreach loop, allowing users to iterate through each element of an iterable. This is particularly useful for executing a set of steps or actions on each item within a collection, such as a list or array.
Schema:
- for:
each: ITERATED_VARIABLE_NAME
index: INDEX_OF_ITERABLE_NAME
in: ITERABLE_VARIABLE_NAME
output_key: VARIABLE_NAME_2
steps:
- EXPRESSION_1
- EXPRESSION_2
Fields:
-
each
: The variable name that represents the current item in the iteration.
-
Type:
string
- Mandatory: Yes
-
Type:
-
index
: The variable name that represents the index of the current item in the iteration.
-
Type:
string
- Mandatory: Yes
-
Type:
-
in
: The name of the iterable variable that the loop will iterate over.
-
Type:
string
- Mandatory: Yes
-
Type:
-
output_key
: A variable to store the results of the loop's execution.
-
Type:
list[expression]
- Mandatory: Yes
-
Type:
-
steps
: The list of compound action expressions to be executed on each element of the loop.
-
Type:
list[expression]
- Mandatory: No
-
Type:
Example usage 1:
Given the payload:
{
"users": [
{
"id": "user1",
"age": 35
},
{
"id": "user2",
"age": 42
},
{
"id": "user3",
"age": 29
}
]
}
Implementing the compound action:
- for:
each: user
index: user_index
in: data.users
output_key: requested_for_notifications
steps:
- action:
action_id: action_1
output_key: action_1_output
In this compound action, for each user
in the list data.users
, the specified action (action_1
) is executed. The loop iterates over all users, performing the action for each one. The results of these actions are then collected and stored in the variable requested_for_notifications
. This example demonstrates how to apply actions to a collection of items, such as sending notifications to a list of users or processing a batch of data records.
Example usage 2: Adjusting User Ages and Sending Notifications
For each user in an array, subtract 10 from their age and then send a notification message with the adjusted age.
Implementing the compound action:
- for:
each: user
index: user_index
in: data.users
output_key: adjusted_ages_notifications
steps:
- script:
code: "return user['age'] - 10"
input_args:
user: user
output_key: adjusted_age
- action:
action_id: send_age_adjustment_notification
output_key: age_notification_user_index
input_args:
user_id: user.id
message: "Your adjusted age is {{adjusted_age}}."
In this compound action, we iterate over an array of users, each represented as an object with an age
attribute. For each user, the first step is a script that calculates the user's age subtracted by 10. The result of this calculation is stored in the variable adjusted_age
.
The second step is an action that sends a notification to each user, informing them of their adjusted age. The message dynamically includes the calculated adjusted_age
for each user. The output_key
for the notification action includes the user_index
to ensure that each notification's output is uniquely identified.
parallel
(parallel processing)
Description: Parallel processing enables the execution of multiple expressions concurrently. This feature is essential for optimizing compound actions by allowing independent tasks to run simultaneously, thus reducing the overall execution time.
Schema 1:
- parallel:
for:
in: ITERABLE
output_key: OUTPUT_VARIABLE
steps:
- compound action_EXPRESSION_1
- compound action_EXPRESSION_2
Schema 2:
- parallel:
branches:
- compound action_EXPRESSION_1
- compound action_EXPRESSION_2
Fields:
-
for
: Specifies a loop to execute expressions in parallel for each item in an iterable.
-
Mandatory:
No (One of
for
orbranches
is required) - Type: For (iteration/looping)
-
Mandatory:
No (One of
-
branches
: A list of expressions to be executed in parallel.
-
Mandatory:
No (One of
for
orbranches
is required) -
Type:
list[expression]
-
Mandatory:
No (One of
-
in
: The iterable variable name for the
for
loop.-
Mandatory:
Yes (if using
for
) -
Type:
string
-
Mandatory:
Yes (if using
-
output_key
: A variable to store the results of the parallel execution.
-
Mandatory:
Yes (if using
for
) -
Type:
string
-
Mandatory:
Yes (if using
Example usage 1: Fetching User Details in Parallel
Given a list like the one below:
{
"user_ids": ["user1", "user2", "user3"]
}
We can iterate over the list and fetch details for each user in parallel:
- parallel:
for:
each: user_id
in: data.user_ids
output_key: user_details
steps:
- action:
action_id: fetch_user_details
input_args:
user_id: user_id
``
**Result:**
```yaml
user_details: [
{ "user_id": "user1", "details": {...} },
{ "user_id": "user2", "details": {...} },
{ "user_id": "user3", "details": {...} }
]
This result shows the details fetched for each user ID, demonstrating the concurrent execution's efficiency.
Example usage 2: Running Multiple Independent Actions in Parallel
- parallel:
branches:
- action:
action_id: log_event
input_args:
event_name: "user_login"
- action:
action_id: send_email
input_args:
email: data.requestor_email
subject: "Login Notification"
body: "You have logged in successfully."
‘This compound action concurrently executes two actions: logging an event and sending an email notification. It demonstrates the use of parallel branches
to run independent tasks simultaneously.
Result: The actions complete concurrently, with no explicit result output due to the nature of the actions (logging and sending an email). This example illustrates improving compound action efficiency by parallelizing independent operations.
return
(return a value as a message in chat)
Description: The Return
expression facilitates an early exit from a compound action without throwing an error. It's particularly useful for concluding a compound action with a specific output, especially when conditional logic determines that no further actions are necessary. Unlike an error-based exit (handled by a Raise
expression), Return
exits gracefully, providing a way to output data in a structured format using the output_mapper
, which follows the Bender v2 101 Handbook Syntax.
Schema:
- return:
output_mapper:
key1: MAPPED_VALUE1
key2: MAPPED_VALUE2
Fields:
-
output_mapper
: A dictionary that represents a mapping between output variables and their values, utilizing Bender v2 syntax for structured and typed data transformation.
- Mandatory: No
- Type: dictionary
Example usage 1: Given a previous action statement that looks like this:
- action:
action_id: abc123abc123abc123abc123
output_key: action_output
We could have a return statement that returns the output of that action:
- return:
output_mapper:
a: data.action_output
Example usage 2: Displaying a List of Users
Given a list of objects like the one below:
{
"users": [
{"id": "user1", "name": "alice", "age": 30},
{"id": "user2", "name": "bob", "age": 25},
{"id": "user3", "name": "charlie", "age": 35}
]
}
We can return a new list with only the id
and name
- return:
output_mapper:
MAP():
id: item.id
name: item.name.$TITLECASE()
items: data.users
Citations
To generate citations, your response must either be an object (as result
) or a list of objects (as results
).
-
Each object MUST have an
id
(this is what’s used to distinguish the record). -
It can optionally have a
friendly_id.
Examples
-
Returning a list of objects (specifying the id)
- return: output_mapper: results: MAP(): converter: MERGE(): - id: item.system_id friendly_id: item.user_facing_name - item items: data.list_of_objects
-
Returning a single object
- return: output_mapper: result: MERGE(): - id: data.result.sys_id friendly_id: data.result.name - data.result
Error Handling
raise
Description: The Raise
expression is used to stop a compound action by raising an error, effectively serving as an early exit mechanism when an error condition is met. It's particularly useful for handling situations where the compound action cannot or should not continue due to issues like permissions, invalid data, or other critical errors.
Schema:
raise:
output_key: OUTPUT_VARIABLE
message: ERROR_MESSAGE_STRING
Fields:
-
output_key
: A variable that represents the action’s output. This is used to store or reference the error in the compound action.
-
Type:
any
- Mandatory: Yes
-
Type:
-
message
: The error message that will be displayed or logged when the error is raised.
-
Type:
string
- Mandatory: No
-
Type:
Example usage 1: Permission Check
Give the following payload:
{
"user_role": "guest"
}
We can right a switch
statement to check if the user's role != "admin"
If this evaluates to true, we want to raise
an error.
- switch:
condition: data.user_role != 'admin'
steps:
- raise:
message: 'This compound action has failed because you do not have permission'
output_key: auth_error_key
Result: An error is raised, stopping the Compound Action, with the following message:
This compound action has failed because you do not have permission
try_catch
Description: The try_catch
expression allows for the execution of a compound action expression with an error handling mechanism. If the try
block encounters an error, the catch
block is executed, allowing for graceful error handling and recovery. This is particularly useful for managing errors in compound actions where certain actions might fail under known or unknown conditions.
Schema:
try_catch:
try:
- compound action_EXPRESSION
catch:
on_status_code:
- STATUS_CODE
steps:
- compound action_EXPRESSION_1
- compound action_EXPRESSION_2
Fields:
-
try
: The block of one or more expressions to attempt to run.
- Mandatory: Yes
-
Type:
dictionary
-
catch
: Defines actions to take if an error occurs in the
try
block.- Mandatory: Yes
-
Type:
dictionary
-
onstatuscode
: Specifies the status codes that will trigger the
catch
block. If not specified, all errors trigger thecatch
block.- Mandatory: No
-
Type:
int
/string
/array
Example usage 1: Handling a Potential Failure in an Action
try_catch:
try:
- action:
action_id: may_fail_action
output_key: action_result
catch:
switch:
cases:
- condition: error_data.action_result and error_data.action_result.status_code == E400
steps:
- action:
action_id: notify_admin
input_args:
message: "That flakey action is failing again"
error: error_data.action_result
default:
- raise:
message: "The action has failed. The IT team is aware this is failing for some cases, please be patient. Someone will look at the open ticket."
This compound action attempts to execute an action that may fail (may_fail_action
). If the action fails, the compound action checks if the error's status code is E400. If it is, it notifies an admin with details of the failure. If the error is for any other reason, it raises a generic error message to inform the user that the issue is known and being addressed.
Expected Result:
-
If
may_fail_action
fails with a status code of E400, an admin is notified about the specific failure. -
If
may_fail_action
fails with any other status code, a generic error message is raised, indicating that the failure is known and will be addressed.