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:

Copy
Copied
- 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
  • output_key:  A variable to store the result of the action.
    • Type:   any
    • Mandatory:  Yes
  • input_args:  A dictionary mapping input arguments to their values, allowing for dynamic inputs to the action.
  • 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

Example Usage 1:

Copy
Copied
- 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:

Copy
Copied
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:

Copy
Copied
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
  • output_key: A variable to store the result of the script's execution.
    • Type:   any
    • Mandatory:  Yes
  • input_args: A dictionary mapping input argument variables to their values, allowing for dynamic inputs to the script.
    • Type:   dictionary
    • Mandatory:  No

Example Usage 1: Clean a list of objects

Copy
Copied
- 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 htmlLinkdescription, and summary fields for each event, creating a simplified list of event details.

Result:

Copy
Copied
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 htmlLinkdescription, and summary fields, and stores the cleaned list of events in cleaned_events.


Example Usage 2: Add two numbers using a script.

Copy
Copied
- 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:

Copy
Copied
 stats: 3

Example Usage 3: Process a list of numbers and get statistics from the list using a multiline Python script.

Copy
Copied
- 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:

Copy
Copied
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:

Copy
Copied
- 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
  • condition : The boolean expression that needs to be evaluated.
    • Type:   boolean
    • Mandatory:  Yes
  • steps : The steps to be executed if the condition is true.
    • Type:   list[expression]
    • Mandatory:  No
  • 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

Example Usage 1:

Copy
Copied
- 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:

Copy
Copied
- 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:

Copy
Copied
- 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:

Copy
Copied
- 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
  • index : The variable name that represents the index of the current item in the iteration.
    • Type:   string
    • Mandatory:  Yes
  • in : The name of the iterable variable that the loop will iterate over.
    • Type:   string
    • Mandatory:  Yes
  • output_key : A variable to store the results of the loop's execution.
    • Type:   list[expression]
    • Mandatory:  Yes
  • steps : The list of compound action expressions to be executed on each element of the loop.
    • Type:   list[expression]
    • Mandatory:  No

Example usage 1:

Given the payload:

Copy
Copied
{
  "users": [
    {
      "id": "user1",
      "age": 35
    },
    {
      "id": "user2",
      "age": 42
    },
    {
      "id": "user3",
      "age": 29
    }
  ]
}

Implementing the compound action:

Copy
Copied
- 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:

Copy
Copied
- 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:

Copy
Copied
- parallel:
    for:
      in: ITERABLE
      output_key: OUTPUT_VARIABLE
      steps:
        - compound action_EXPRESSION_1
        - compound action_EXPRESSION_2

Schema 2:

Copy
Copied
- 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.
  • branches : A list of expressions to be executed in parallel.
    • Mandatory:  No (One of  for  or  branches  is required)
    • Type:   list[expression]
  • in : The iterable variable name for the  for  loop.
    • Mandatory:  Yes (if using  for )
    • Type:   string
  • output_key : A variable to store the results of the parallel execution.
    • Mandatory:  Yes (if using  for )
    • Type:   string

Example usage 1: Fetching User Details in Parallel

Given a list like the one below:

Copy
Copied
{
  "user_ids": ["user1", "user2", "user3"]
}

We can iterate over the list and fetch details for each user in parallel:

Copy
Copied
- 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

Copy
Copied
- 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:

Copy
Copied
- 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:

Copy
Copied
- action:
		action_id: abc123abc123abc123abc123
		output_key: action_output

We could have a return statement that returns the output of that action:

Copy
Copied
- return:
    output_mapper:
        a: data.action_output

Example usage 2: Displaying a List of Users

Given a list of objects like the one below:

Copy
Copied
{
  "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

Copy
Copied
- 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)
    Copy
    Copied
    - return:
        output_mapper:
          results:
            MAP():
              converter:
    	          MERGE():
    		          - id: item.system_id
    			          friendly_id: item.user_facing_name
    		          - item
              items: data.list_of_objects

Alt text

  • Returning a single object
    Copy
    Copied
    - 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:

Copy
Copied
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
  • message : The error message that will be displayed or logged when the error is raised.
    • Type:   string
    • Mandatory:  No

Example usage 1: Permission Check

Give the following payload:

Copy
Copied
{
  "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.

Copy
Copied
- 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:

Copy
Copied
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:

Copy
Copied
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 the  catch  block.
    • Mandatory:  No
    • Type:   int / string / array

Example usage 1: Handling a Potential Failure in an Action

Copy
Copied
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.