Skip to main content

Built-In Activities

Normally, activities are tasks should be put below steps, the tasks (activities) execution sequence is from top to the bottom.

Chat Interaction​

This chat interaction will appear in the chatbox with the text you have input, and with the form you applied, the form showing style depends on whether Popout or Embed you input.

  • ticket_id(Required) : The ticket to send a chat message to, the default value is $Ctx_CW_Ticket_Id
  • text(Required) : The text message to send to the user
  • form_name : The static name of a form for the user to fill out
  • form_display_mode : This determines how the form is displayed in the chat, Popout or Embed
  • form_def : JSON string which defines default values for the form

For example:

steps:
# Get the list of users
- task: exchange_get_all_mailboxes

- task: inline_powershell
alias: o365_users
inputs:
allStaff: =exchange_get_all_mailboxes.mailboxes
script: |
$formDefProps = @{
user = [Array]$(ConvertFrom-Json $allStaff) | Sort -Property text;
};
Write-Host $formDefProps
return @{ formDef = $(ConvertTo-Json -Depth 5 $formDefProps); }

- task: chat_interaction
alias: userselect
inputs:
text: 'Select the user to proceed:'
form_name: 'pick_user_form'
form_display_mode: 'Embed'
form_def: =inline_powershell.formDef

The data for the form in chat_interaction is transferred from form_def property during runtime since it resolves previous inline_powershell output value formDef.

example format for dropdown:

{

// Set default value for a text field
"text_field_reference_name": "default value",

// Basic example of populating a dropdown
"dropdown_field_reference_name": ["Option 1", "Option 2"],

// Example populating a dropdown with a list of values
"dropdown_field_reference_name": [{ "text": "Option 1", "value": "option_1" },
{ "text": "Option 2", "value": "option_2" }],

// Example populating dropdown, with a default value selected
"dropdown_default_value_ref_name": [{ "text": "Option 1", "value": "option_1", "selected": true },
{ "text": "Option 2", "value": "option_2", "selected": false }],

// Example populating dropdown, with multiple default values selected
"dropdown_default_value_ref_name": [{ "text": "Option 1", "value": "option_1", "selected": true },
{ "text": "Option 2", "value": "option_2", "selected": true }],

// Note: All dropdown examples work with multi-select lists


// Example populating a repeating section
// Note: repeating sections can only be populated with values for text fields only
// At the current time, you cannot populate dropdown options for tag fields inside a repeating section
"repeating_section_ref_name": [{ "field1_ref_name": "Default 1", "field2_ref_name": "Default 2" },
{ "field1_ref_name": "Default 1", "field2_ref_name": "Default 2" }],

// Example populating multiple listbox
- task: inline_powershell
inputs:
script: |
$formDefProps = @{
multibox = @(@{ text = "something"; value = "something else"; selected = $true},
@{ text = "something 1"; value = "something else 1"; selected = $true})
};
return @{ formDef = ConvertTo-Json $formDefProps }

- task: chat_interaction
inputs:
text: 'check the multiplebox'
form_name: 'test_form'
form_display_mode: 'PopOut'
form_def: =inline_powershell.formDef
}


- task: chat_interaction
alias: userselect
inputs:
text: 'Select the user to proceed:'
form_name: 'pick_user_form'
form_display_mode: 'Embed'
form_def: "{ 'dropdown_field_1': ['Option 1', 'Option 2']}"

Get Approval​

Get Approval will pause a package execution and force engineers to select an approver who they have obtained approval from before the package continues execution.

  • ticket_id(Required) : The ticket to send a chat message to, the default value is $Ctx_CW_Ticket_Id
  • form_name : The static name of a approver form to fill out. The form should contain 'approver' dropdown input
  • form_display_mode : This determines how the form is displayed in the chat, Embed

For Example:

steps:
- task: get_approval
alias: approver
inputs:
form_name: 'select_the_approver'
form_display_mode: 'Embed'

- task: chat_interaction
inputs:
text: 'Complete executing package'

Loop​

The loop activity allows a package to execute the same step multiple times in a single package execution. There are 2 inputs it accepts:

  • condition: Value should be 'True' if the loop should continue. Any other value will terminate the looping behavior
  • activity: The static name of the activity or activity alias you are looping to

Example 1

This type of loop is a traditional for loop with a terminating check (i > 5) and position counter (pos). There are 3 components needed for this setup:

  • Counter Activity: The first activity which keeps track of the loop position. I Have used an inline_powershell activity to demonstrate this.
  • Activities: Any activities you want to execute multiple times go here
  • Loop Activity: The loop activity at the end of the loop

You can use loop_start.pos as an input parameter so your activities know what iteration of the loop they are currently in.

Here's the sample code:

     #Keep track of the position in the loop by using a self-referencing input parameter
# Output a property to tell the loop activity whether we should continue executing
- task: inline_powershell
alias: 'loop_start'
inputs:
pos: =loop_start.pos
script: |
$i = If($pos -ne $null) { [int]$pos + 1 } Else { 0 }
$continue = If($i -gt 5) { "False" } Else { "True" }

return @{ pos = $i; continue = $continue }

- task: inline_powershell
inputs:
pos: =loop_start.pos
script: |
Write-Host "This is loop number $pos"

- task: loop
inputs:
condition: =loop_start.continue
activity: 'loop_start'

Example 2 This example is a simple feedback loop for user input. It allows the user to keep performing some action until they want to stop. In this scenario, the form has 2 fields:

  • Are you finished?: The user will select if they want to continue trying options, or if they are done.
  • Options: A dropdown of options

Here's the sample code:

- task: chat_interaction
alias: 'loop_start'
inputs:
text: 'Try these steps to see if they fix the problem!'
form_name: 'loop_test'
form_display_mode: 'Embed'

- task: inline_powershell
alias: 'usercheck'
inputs:
finished: =chat_interaction.form.finished
script: |
return @{ skip = If($finished -eq 'True') { "False" } Else { "True" } }

- task: inline_powershell
skip: =usercheck.skip
inputs:
pos: =loop_start.pos
opt: =chat_interaction.form.options
script: |
Write-Host "Do things for the user with selected option: $opt"

- task: loop
inputs:
condition: =chat_interaction.form.finished
activity: 'loop_start'

Stop​

  • condition : 'True' to stop package execution. Anything else will continue execution.

Wait​

  • minutes: Number of minutes to wait for before continuing package execution.
  • seconds: Number of seconds to wait for before continuing package execution.

Get Package Data​

Get package data activity is usually coupled with other package, which uses the data stored in the database by other package, for example, re-enable terminated user package uses the data stored by staff offboarding package.

  • key : Unique key used to retrieve data for this package. If you do not specify a key, all data for this package will be returned.
  • package_internal_id: Package to retrieve data for. If you do not specify, this will default to the current executing package.
    ##Get staff offboarding data, if exists.
- task: inline_powershell
alias: format_key alias: format_key
inputs:
clientid: $Ctx_CW_Client_Id
username: =get_upn.username
script: |
return @{ key = $($clientid.ToString()+"_$username")}

##Get data from the Staff Offboarding (Cloud Hyrbid) package
- task: get_package_data
inputs:
key: =format_key.key
package_internal_id: 'FB362A66-1794-43A0-90C9-87138EF9DEF4'

Store Package Data​

Whenever the package is executing, it will store whatever you put into, for example, JSON or text string, whatever you want, it will be stored. It means text data. You can also put in a key (id like username of someone), for example:

## Store the Terminated User Data
- task: inline_powershell
document: |
Store the terminated user information if we need to re-enable the user in the future.
Information stored:
- Username
- Licenses
- Groups
alias: terminate_data
inputs:
clientid: $Ctx_CW_Client_Id
selecteduser: =terminate_form.form.employee
licenses: =azure_get_licenses.licenses
groups: =ad_disable_user.groupsRemoved
cloudgroups: =azure_get_member_groups.cloud_groups
originalou: =ad_move_user_to_ou.OriginalOU
script: |
[array]$tempcloud = $(ConvertFrom-Json $cloudgroups)
[array]$temponprem = $(ConvertFrom-Json $groups)
$data = @{
clientid = $clientid;
user = $selecteduser;
licenses = $licenses;
groups = if($temponprem.Count -ge 1){$($temponprem -join ',')}else{$null};
cloudgroups = if($tempcloud.Count -ge 1){$($tempcloud.text -join ',')}else{$null};
ou = $originalou;
datetime_utc = [string]$(Get-date $([datetime]::UtcNow) -Format "dd/MM/yyyy hh:mm:ss tt")
} | ConvertTo-Json -Depth 5
Write-Host $data
[string]$key = $clientid.ToString() + "_" + $selecteduser
Write-Host $key
return @{ data = $data; key = $key}

- task: store_package_data
inputs:
key: =terminate_data.key
value: =terminate_data.data

When we run the Staff Offboarding package, it stores some data about that user and for that client, the Staff Offboarding package stores the key as clientid_username. When the staff offboarding package is executed, it will record which group the user has been assigned, what license the user has been assigned, etc. And when the re-enable terminated user package is executed, it will use the get package data with the key clientid_username to see if there is any data in the orchestrator for the user, if the user was terminated previously by using Pia, then there should be some data there with licenses and groups it has. If there is data, the re-enable terminated user package could use that data, if it is json format, it could be converted back to object and re-assign the users with licenses and groups they had when they were terminated. When you store package data, the package internal id is not required, by default the package internal id will be set to the current package you are executing on.

So if you are running the store package data activity on the staff offboarding package, it will store the package data against that staff offboarding package.

Store and get package data that will only store and get package data for the current package, so you have to store the data in the current package, and get the same data out of the package when you run it next time. Otherwise, if you want to store against a different package, or be able to retrieve data from a different package, you need to pass the package internal id. Using the package internal id of the package if you want to reference a different package, but if you want to get and store data for the current package, you don't need to set that property(package internal id) at all.

For example, when you first query the Microsoft API to get the users' the licenses and groups, when you terminate a user, those groups are deleted for that user. After that re-enable disabled user package is executed, there is no way to query the Microsoft API to know which licenses and groups the user previously has been assigned to, that's why we store that data in terminate package, it is just a way of storing. So that later we could access that information, we only use this for storing data which we must store, if we can get the data out of the Microsoft graph api, we will go there directly.

This is not an occasion mechanism, it can be used as occasion mechanism between multiple packages, but that is not its purpose.

The storing data is stored in the database, because it has to be carried into a different package execution. For example, the staff offboarding package might be run today, but the re-enable disabled user package might be run six weeks from now.

  • key(Required) : A unique key to store this information for later retrieval.
  • value(Required) : Value to store.
  • package_internal_id: Package to store data against. If you do not specify, this will default to the current executing package.

Get Machines​

Get machines activity can be used to retrieve the details of the devices which has new agent service installed and are registered on the Orchestrator portal.

    #Get the list of registered system with new agent service installed

- task: get_machines
alias: get_registered_devices
inputs:
client_id: $Ctx_CW_Client_Id
sam_account_name: 'system.admin@pia.com.au'
include_inactive_agents: 'true'
days_since_login: '7'


- task: inline_powershell
inputs:
machines: =get_registered_devices.machines
script: |
Write-Host "Registered Machines Info:"
foreach($m in $(ConvertFrom-Json $machines))
{
Write-Host $m.QualifiedName $m.ComputerName $m.LastLoggedInUser $m.LastCheckedInTime $m.DateRegistered $m.Status $m.LastLoggedInTime
}
  • sam_account_name: Username of the user who has last logged into the system.
  • include_inactive_agents : Flag to whether or not to include inactive machines.
  • include_inactive_agents : Duration between present and last logged in date.

Get Xero API Token​

This activity is not available in the package editor, the reason is because it will be quicker and to make the package definition smaller.

If you use Xero API Token variable, it will automatically add the activity (GetXeroAPITokenActivity) to the package execution one activity ahead of activity where you use the variable. If you use the execution environment(executionEnvironment) attribute, when you setting up an activity, it will automatically add the agent interactive session activity before that activity (preceding that activity), you will see the Ensure agent interactive session in the package execution, but not in the package editor.

In YAML, we describe this is the task (activity) we want to run, which environment should it be run on? This executionEnvironment and executionEnvironmentKey are just an input which maps to the activity in the activity editor.

Get SharePoint API Token​

This token whenever it is seen as an input to a task, it will automatically add that corresponding activity ahead of the step.

If you use the Sharepoint API Token as input, it will invoke the GetSharePointAPITokenActivity preceding the activity you put the token as input.

Get One Time Access Url​

  • user_email(Required) : Email address of the user to create a URL for
  • redirect_to : URL to redirect the user to after they authenticate to the client portal. E.g. /Tickets/MyTickets
  • session_id : Chat session id used during redirect.
  • message_id : Message id used during redirect.

This activity is to retrieve Microsoft Graph API token - delegated consent. This is a built-in Activity so you can call it to use Microsoft Graph API token - Delegated Consent.

Get MS Graph API Token​

This activity is not available in the package editor, the reason is because it will be quicker and to make the package definition smaller.

This token whenever it is seen as an input to a task, it will automatically add that corresponding activity ahead of the step.

If you use MS Graph API Token variable, it will automatically add the activity to the package execution one activity ahead of activity where you use the variable. If you use the execution environment attribute, when you setting up an activity, it will automatically add the agent interactive session activity before that activity (preceding that activity), you will see the Ensure agent interactive session in the package execution, but not in the package editor.

This token (msgraph_api_token) is a default variable set to Azure AD: Get Group Member Details activity.

If you put azure_get_group_members task (activity) in the package editor, you cannot see the msgraph_api_token, since it has already been put into the activity as default value. However, you can still put the attribute msgraph_token as input to the task (activity) if you want, it is exact the same thing as of not having it.

When we put the token into the variables, and anywhere where it gets used, it will automatically in that package get that token for us, and it shows in live packages when the package is executing, so you could see it.

It will run every time, the first time it runs might be a little bit slower, but there is caching in the system, so it won't talk to the API every time, it will cache the data, it will cache the token and re-get here for the next call.

The reason why it runs every single time before every activity needs is because sometimes the package will need to wait for a user, for example, there might have a chat interaction, but the user might get back to it in a day. So it cannot reuse the same API token for the entire package execution, it has to re-get the token for every activity it is executing just before the existed activity, since the token is short-lived and could be expired. so your instance has an access token, which is sent in the Authorization header of API calls. This is the token that allows the instance to access the Microsoft Graph on the user's behalf. However, this token is short-lived. The token expires an hour after it is issued. If the token is not expired, we will use the existing token, so the activity will get an existing token from memory if it is available. If not, it will get a new token from MS Graph API, and it will update the token cache with the new token. The management of the token is handled by the orchestrator platform, the package developer doesn't need to worry about the token expiry or getting new token.

You cannot use these variables directly, there are activities use these variables as default values.

Some variables don't use activity, for example, if you use IT glue token, it doesn't use activity, the reason is because it is just a secret of configuration. If it is just a configuration, it means nothing else needs to be run during runtime to get that token. So the token or the password or the secrets just read from a config file, which means the margin of that is pretty much zero. But when an activity needs to query the API to get a token and to authenticate and to manage the token to memory, then we use an activity for some but not other APIs.

If you see the CW API Token for any of the ConnectWise activities, it will not put a special activity in front of that activity, it just uses the resolver function to get the token.

# Orchestrator package
conditions:
- name: 'system_ringcentral'
match: 'get oncall number'

steps:
- task: rc_get_call_rule
inputs:
rule_name: 'Forward to On Call Tech'
extensionId: '2058665005'

- task: rc_send_message
inputs:
message: 'The oncall number is: {=rc_get_call_rule.unconditionalForward}'
chat_id: =system_ringcentral.message.body.groupId

for example, if you hover over the task rc_send_message, it contains $RC_Bot_Token as default value of variable rcToken, and urUrl uses $RC_Api_Url.

Get Kaseya API Token​

This token whenever it is seen as an input to a task, it will automatically add that corresponding activity ahead of the step.

If you use the Kaseya API Token as input, it will invoke the GetKaseyaAPITokenActivity preceding the activity you put the token as input.

Get Ring Central API Token​

This token whenever it is seen as an input to a task, it will automatically add that corresponding activity ahead of the step.

There are six Ring Central API Tokens, RC Sandbox API Url , RC API Url , RC Sandbox API Token , RC Prod API Token , RC Prod Bot Token , RC Sandbox Bot Token. Only RC Sandbox API Token and RC Prod API Token will invoke GetRingCentralAPITokenActivity_Sandbox activity and GetRingCentralAPITokenActivity_Prod respectively, the others will use the resolver function to get the token.

Agent Interactive Session​

This activity will firstly check if there is a already linked to the activity agent session which could be used, if there is no activity session, this activity will start a new session, then the activity will invoke the agent procedure to get the client downloaded and running.

Inline PowerShell Activity​

This Inline PowerShell Activity could be referenced from the Package Editor Activities column, powershell scripting language is put into the script property. As a scripting language, PowerShell is commonly used for automating the management of systems. It is also used to build, test, and deploy solutions, often in CI/CD environments. PowerShell is built on the .NET Common Language Runtime (CLR). All inputs and outputs are .NET objects. No need to parse text output to extract information from output. The PowerShell scripting language includes the following features: Extensible through functions, classes, scripts, and modules; Extensible formatting system for easy output; Extensible type system for creating dynamic types;Built-in support for common data formats like CSV, JSON, and XML

  • script(Required): PowerShell script for execution

Schedule For Later​

This activity will run a package later at a designated time (schedule date/time). Terminologies are used on this topic:

  • Original ticket/execution: Related to the first time the package is run.
  • New/later ticket/execution: Related to the next time the package is run on scheduled time.

Its behaviors include:

  • Pia behavior:

    • If the schedule date/time is valid, Pia will create a new ticket and automatically run the scheduled package. The new ticket will have the same Ticket board, Type, Subtype, Item, Clients and Contact as the original ticket. The new ticket will be bundled as a child to the original ticket and will have the following note added: "This ticket was created by Pia to perform a scheduled action. Refer to the Pia Chat window for more information."
    • If the new execution is success, Pia will self close the new ticket, otherwise, the new ticket will not be closed.
  • Underlying workaround:

    • If the schedule date/time in the first execution is valid, a scheduled package will be run on designated time. When time triggered, Pia automatically creates a new ticket, chat session and starts a new package instance. - If the schuduled date/time is not valid (time has passed), the package will execute immediately. In this case, schedule_for_later will treat the current execution as scheduled execution, and current execution is treated as time over.

      - The difference between the **original** execution and **new/later** execution are:

      - All variables of activities before the **schedule_for_later** will be persisted in the new execution.
      - Only activities which sit after the **schedule_for_later** will be run in the new execution.
      - Output: 2 values
      - In current execution (first session): (running_schedule, not_running_schedule) = (false, true)
      - In scheduled execution (next session): (running_schedule, not_running_schedule) = (true, false)

      :::caution

Important: The time format is used for scheduling in UAT environment is Canberra ACT, Australia (GMT+11).

:::

Examples:

steps:
- task: inline_powershell
alias: originalTicket
inputs:
ticketId: $Ctx_CW_Ticket_Id
script: |
return @{ ticketId = $ticketId; }

- task: inline_powershell
alias: getScheduleTime
inputs:
script: |
return @{ value = (Get-Date (Get-date).addminutes(2) -Format "MM/dd/yyyy hh:mm tt"); }


- task: schedule_for_later
inputs:
schedule_date: =getScheduleTime.value
# schedule_date: '10/27/2021 00:26 PM' #(explicit time)


- task: inline_powershell
skip: =schedule_for_later.running_schedule
inputs:
script: |
write-host 'scheduler is set!'


- task: inline_powershell
skip: =schedule_for_later.not_running_schedule
inputs:
originalTicketId: =originalTicket.ticketId
newTicketId: $Ctx_CW_Ticket_Id
script: |
write-host "original id: $originalTicketId"
write-host "new ticket id: $newTicketId"