This reference documentation covers the Symphony Workflow Automation Definition Language (SWADL) defined as a JSON schema.
SWADL is based on YAML, written in files usually suffixed with .swadl.yaml. If you are not familiar with YAML, you can read about its syntax on Wikipedia.
In SWADL, at the top level, you mainly define the activities part of the workflow.
Key | Type | Required |
---|---|---|
id | String | Yes |
variables | Map | No |
activities | List | Yes |
Example:
id: myWorkflow
variables:
myVar: "aValue"
activities:
- send-message:
id: myActivity
Workflow's id should start with a letter and should not contain empty spaces. It is required. The id will appear in logs and audit trails.
Workflow's properties section with one single field for the moment. This sections is not required. The default value will be applied in the workflow in case they are not defined.
A boolean property indicating if the current workflow need to deploy when it is true
, otherwise not.
Variables are accessible and editable within the entire workflow. A map of key/value entries is expected. Simple types such as numbers, string and booleans as well as lists and maps are supported.
Variables can be accessed elsewhere in the workflow with the ${variables.VARIABLE_NAME}
syntax. They are also
accessible from custom activities and script activities.
While variables can be defined in SWADL, each instance of a workflow holds its own copy of the variables. Activities can change variables and those changes will be visible by other activities.
Examples:
variables:
var1: 123
var2: "my text"
var3: my text
aMap:
key1: value1
key2: value2
list1:
- item1
- item2
A list of activities to be executed by the workflow. By default, the execution is sequential but complex logic can be orchestrated with if/else conditions (if) as well as on/activity-completed events.
Built-in activities are provided to support most of the public APIs of Symphony.
Activities have common keys listed below:
Key | Type | Required |
---|---|---|
id | String | Yes |
on | Map | No |
if | String | No |
else | Map | No |
Activities also produce outputs that are accessible via ${ACTIVITY_ID.outputs.OUTPUT_NAME}
. For each activity
referenced below, its outputs are described too with a reference to the underlying BDK object.
The welcome-bot example shows how outputs can be used.
Activity's identifier should be unique across workflows. As it can be used as a variable identifier only alphanumeric
characters are allowed (_
can be used as a separator). variables cannot be used as an activity id.
Example:
activities:
- send-message:
id: myActivity
# outputs of this activity can be referenced as ${myActivity.outputs.message}
Events that can trigger the activity execution. The first activity of a workflow is expected to have an event.
on
can contain either a specific event directly or a list of events as part of the one-of
or all-of
keys.
Only one key (specific event), one-of
or all-of
is allowed by activity.
Key | Type | Required |
---|---|---|
Typed Event | Map | No |
one-of | List | No |
all-of | List | No |
timeout | String | No |
Examples:
activities:
- send-message:
id: myActivity
on:
# because there are no attributes for this event, an empty map {} is used
user-joined-room: { }
activities:
- send-message:
id: myActivity
on:
one-of:
- user-joined-room: { }
- user-left-room: { }
The last captured event coming from Datafeed in a workflow is bound to a variable accessible via ${event}
.
This event
variable holds
the initiator
of the event and the source, i.e. the payload
listed here.
Checkout the welcome bot example to see how the ${event}
can be used.
Timeout while waiting for an event, expressed as an ISO 8601 duration. Upon expiration, another activity can be triggered with an activity-expired event.
Default value for form-replied is 24 hours. No default value for other events.
Example: PT60S for a 60 seconds timeout.
Used to receive at least one of the listed events. Multiple events can be listed but a given time only one will trigger the activity. It can be either one of them.
Used to receive all listed events. Multiple events can be listed. The process will hold until all events have happened to trigger the activity.
Note: Currently this list supports to have only one activity-completed /activity-failed type event. This limitation will be fixed in a newer version later.
Conditional execution of the activity based on a boolean expression. Workflow variables can be used within the expression. This condition applies to all the events that can start the activity.
The first activity of a workflow cannot have an if
condition (to avoid triggering workflows and then have to evaluate
the first condition and stop the workflow without any activity being executed).
activities:
- send-message:
id: myActivity
if: ${variables.myVar == '123'}
Default execution of the activity when if
conditions are used for previous activities. This is an empty object. This
is combined with an activity-completed
event to properly chain the else
activity with the activity before the if
branch of the workflow.
Example:
activities:
- send-message:
id: myActivity
on:
activity-completed:
activity-id: BEFORE_IF_ACTIVITY_ID
else: { }
Below are all the supported events under the on
or the one-of
keys.
An event can have an optional id in order to reference it in subsequent activities.
Generated when a message is sent in an IM, MIM, or chatroom of which the workflow bot is a member, including messages sent by the user him/herself.
Key | Type | Required |
---|---|---|
content | String | No |
requires-bot-mention | Boolean | No |
id | String | Yes |
Example:
activities:
- send-message:
id: myActivity
on:
message-received:
id: msgReceivedEvent #optional
content: /run
Message content to listen to. Can be a simple string, usually a /command to trigger a workflow. It can also be a
template like /run {myArg}
where myArg
will be bound to ${event.args.myArg}
.
Templates are handled as Ant-matching expressions, similar to Spring Boot controllers. Multiple patterns can be used,
for instance /run {myArg1} {myArg2}
with whitespace being used as a separator. User mentions or tags can be captured
too.
Example:
activities:
- send-message:
id: myActivity
on:
message-received:
id: msgReceivedEvent #optional
# dash for the hashtag is escaped otherwise it is a comment in YAML
# $ for the cash tag is escaped otherwise it is a variable handled as an expression by Camunda
content: /go {arg1} @{user} \#{hash} \${cash}
# to write it as a string with quotes, the escaping is a bit different
# content: "/go {arg1} @{user} \\#{hash} \\${cash}"
to:
stream-id: A_STREAM
content: Received ${event.args.arg1}, ${event.args.user}, ${event.args.hash}, ${event.args.cash}
The contact sharing workflow from the examples uses templated content
to
match messages. It uses a function named mentions
to retrieve the mentioned user ids. Similar functions
from MessageParser
are exposed too.
Examples:
${mentions(event)}
returns the list of mentioned user ids from amessage-received
event${mentions(event)[0]}
to get the first mentioned user id from amessage-received
event${cashTags(event)}
returns the first cashtag from amessage-received
event${hashTags(event)}
returns the first hashtag from amessage-received
event${emojis(event)}
returns a map of the emojis from amessage-received
event
If true, the event is only triggered if the bot is mentioned.
Unique id should start with a letter and should not contain empty spaces. It is optional. It allows to reference the event in subsequent activities.
Generated when a user replies to a bot message that contains an interactive form with UX components such as text fields, radio buttons, checkboxes, person selectors and more.
As multiple users can reply to a form sent to a room, the activity waiting for a form-replied
can be executed multiple
times (it can be seen as a sub execution of the current workflow). This also means that every activity defined after
this activity or with a activity-completed
event on this activity will run within its own sub execution.
In 1-1 conversations or if the form has to be replied only once, exclusive attribute on the form-replied
event can be set to true
. In that case, the activity is executed in the main process of the current workflow and flow
controls can be used as normal.
nb: Loops are only supported with forms that require only one reply.
Key | Type | Required |
---|---|---|
form-id | String | Yes |
exclusive | String | No |
id | String | Yes |
Example:
activities:
- send-message:
id: sendForm
on:
message-received:
id: msgReceivedEvent #optional
content: "/message"
content: |
<messageML>
<form id="sendForm">
<text-field name="aField" placeholder="Anything you want to say" required="true"/>
<button name="send-answers" type="action">Send</button>
<button type="reset">Clear</button>
</form>
</messageML>
- send-message:
id: pongReply
on:
form-replied:
id: formRepliedEvent #optional
# form id is the same as the activity's id above and the same as the id in the original form's MessageML
form-id: sendForm
content: ${sendForm.aField}
An advanced usage of forms can be found in the examples: simple poll bot.
The id should be the same as the activity's one that sent the form.
Boolean specifying whether the form can be replied once or multiple replies are expected. It is false
by default.
Unique id should start with a letter and should not contain empty spaces. It is optional. It allows to reference the event in subsequent activities.
Generated when messages are suppressed.
Generated when either the workflow bot shares a wall post written by another user or another user shares a wall post written by the workflow bot.
Generated when an IM or MIM is created with the workflow bot as a member, initiated either by the workflow bot or another user.
Generated when a room is created by the workflow bot.
Generated when a room of which the workflow bot is a member is updated, including rooms updated by the user him/herself.
Generated when a room of which the workflow bot is a member is deactivated, including rooms deactivated by the user him/herself.
Generated when a room of which the workflow bot is a member is reactivated, including rooms reactivated by the user him/herself.
Generated when a user is promoted from a participant to an owner of a room of which the workflow bot is a member, including when the user himself is promoted to an owner or promotes another user.
Generated when a user is demoted from an owner to a participant of a room of which the workflow bot is a member, including when the user himself is demoted to a participant or demotes another user.
Generated when a new user joins or is added to a room of which the workflow bot is a member, including when the user himself joins or is added to a room.
Generated when a user leaves or is removed from a room of which the workflow bot is a member, including when the user himself leaves or is removed from a room.
Generated when a user requests to join a room. Only the user who requested to join the room and the owners of that room will receive this event on their datafeeds.
Generated when a connection request is sent, either by the workflow bot to another user or to the workflow bot by another user.
Generated when a connection request is accepted, either sent by the workflow bot and accepted by another user or sent by another user and accepted by the workflow bot.
Generated when the given activity event timeout has expired. Note this is not a Datafeed real-time event.
This is usually used for forms when a specific activity is triggered upon expiration (to warn the user the form is no longer valid or to collect results).
Key | Type | Required |
---|---|---|
activity-id | String | Yes |
Example:
activities:
- send-message:
id: sendForm
on:
message-received:
content: "/message"
content: |
<messageML>
<form id="sendForm">
<text-field name="aField" placeholder="Anything you want to say" required="true"/>
<button name="send-answers" type="action">Send</button>
<button type="reset">Clear</button>
</form>
</messageML>
- send-message:
id: pongReply
on:
# Short timeout to wait for a reply, 10 seconds only
timeout: PT10S
form-replied:
form-id: sendForm
content: ${sendForm.aField}
- send-message:
id: expiration
on:
activity-expired:
activity-id: pongReply
# If no reply is provided for the form after 10 seconds then this activity is executed
content: Form expired!
The id of the activity which expiration's triggers the event.
Generated when the given activity is completed. Note this is not a Datafeed real-time event.
This is used to connect activities together when a non-sequential ordering is required. For instance to build if/else if/else branching workflows or loops.
If no event are set for a given activity this is the default event that will be used with the activity-id
being the
previously declared activity (hence the sequential ordering by default).
Key | Type | Required |
---|---|---|
activity-id | String | Yes |
if | String | No |
Example:
id: ifElseIfElse
variables:
foo: fuzz
activities:
- send-message:
id: start
on:
message-received:
content: /execute
- send-message:
id: if
# will not be executed because of the if
if: ${variables.foo == 'bar'}
content: If
- send-message:
id: elseif
on:
activity-completed:
activity-id: start
# will be executed because of the if
if: ${variables.foo == 'fuzz'}
content: If else
- send-message:
id: else
on:
activity-completed:
activity-id: start
# will not be executed because the else if was executed
else: { }
content: Else
Example:
id: loop
variables:
execution: 0
activities:
- send-message:
id: start
on:
one-of:
# a slash command is used to trigger the workflow
- message-received:
content: /execute
# but this activity (once the workflow is running) can also start after the loop activity is executed
- activity-completed:
activity-id: loop
# loop 2 times
if: ${variables.execution <= 1}
content: Loop
- execute-script:
id: loop
# we increment the loop counter
script: |
variables.execution++
The completed (without errors) activity triggering this event.
Similar to the if at on
level but applied to a single completed activity.
Generated when the given activity has failed. Note this is not a Datafeed real-time event.
Exceptions raised by activities will trigger this event. This gives a way to let the user know about a failure.
Key | Type | Required |
---|---|---|
activity-id | String | Yes |
Example:
activities:
- send-message:
id: sendHello
on:
message-received:
content: /execute
to:
stream-id: NON_EXISTING_STREAM
content: Hello
- send-message:
id: errorHandling
on:
activity-failed:
activity-id: sendHello
content: Sending a message failed
The failing activity triggering this event.
Timer based event. It is either triggered at a given point in time using the keyword at
or repeated using the
keyword repeat
. Note this is not a Datafeed real-time event.
Key | Type | Required |
---|---|---|
at | String | Yes |
repeat | String | Yes |
Only one of the key at
or repeat
can be set.
ISO 8601 date representing a point in time when the current activity should be executed.
Example: 2021-08-31T-15:50:00
ISO 8601 repeating intervals to repeat the current activity.
It can be used on the first activity of a workflow to make its execution periodic (like a cron job).
Examples:
- R/PT10S to repeat an activity every 10 seconds
- R/1970-01-01T00:00:00Z/P1D to repeat every day at midnight
Generated when an HTTP request is received in order to trigger a workflow. The workflow bot exposes an API that can be called by external users to manually trigger a workflow execution. This event can only be used on the first activity of a workflow.
Key | Type | Required |
---|---|---|
token | String | Yes |
id | String | No |
Example:
id: myWorkflow
activities:
- send-message:
id: sendMsg
on:
request-received:
token: myToken
to:
stream-id: A_STREAM
content: ${event.args.content}
The workflow above is triggered when an HTTP request is sent to the bot. Arguments can be passed along the request and
retrieved in the ${event.args}
variable. For instance:
curl --request POST 'http://127.0.0.1:8080/wdk/v1/workflows/myWorkflow/execute' \
--header 'X-Workflow-Token: myToken' \
--header 'Content-Type: application/json' \
--data-raw '{
"args": {
"content": "Hola from api"
}
}
'
Token to authorize incoming HTTP requests. This token should be passed when calling the HTTP API to trigger the workflow
in the X-Workflow-Token
header. This is a shared secret between the workflow writer and the users that can trigger the
workflow via API.
Unique id should start with a letter and should not contain empty spaces. It is optional. It allows to reference the event in subsequent activities.
If an event is defined with an id, you can access its payload by referencing its id in SWADL.
The key "event" allows to reference the latest happening event.
Example:
activities:
- send-message:
id: myFirstActivity
on:
message-received:
id: messageReceivedEvent
content: /hello
content: Hello!
- send-message:
id: mySecondActivity
on:
message-suppressed:
id: messageSuppressedEvent
content: Message has been Suppressed!
- execute-script:
id: myScript
script: |
assert messageReceivedEvent.source.message.message == '/hello'
println messageSuppressedEvent.source.messageId
assert event.surce.messageId == messageSuppressedEvent.source.messageId
Below are all the supported activities that can be listed under the activities
key. Custom activities can be defined too.
Posts a message to a stream. Probably the most commonly used activity to interact with end-users.
Key | Type | Required |
---|---|---|
to | Map | No |
content | String/Object | Yes |
attachments | List | No |
data | String | No |
Output | Type |
---|---|
msgId | String |
message | V4Message |
messages | List |
failedStreamIds | List |
Example:
activities:
- send-message:
id: myActivity
to:
stream-id: ID_OF_A_STREAM
content: Hello!
The recipient (conversation, IM or chatroom) in which the message should be posted.
If not set, the stream associated with the latest received event is used. This makes replying to a command sent by a user easy.
Key | Type | Required |
---|---|---|
stream-id | String | Yes |
stream-ids | String | Yes |
user-ids | Map | Yes |
If to
is used then one of the key stream-id
or stream-ids
or user-ids
must be set.
Example:
activities:
- send-message:
id: myActivity
on:
message-received:
content: /hello
# to is not set, the message is sent to the same stream as the received /hello message (i.e. the bot simply replies to the user)
content: Hello!
Stream id to send the message to. Both url safe and base64 encoded urls are accepted.
Stream ids to send the blast message to. Both url safe and base64 encoded urls are accepted.
Users to send the message to. An IM will be created or reused.
The content of the message in MessageML format. Must contain at least one space. In case the content is a form, the latter's id should be the same as the send-message activity one.
Content can
be MessageML with
the <messageML>
tags or can be simple text too ( are automatically added if needed).
Content can either be set directly in the SWADL file as plain text (String) or it can be a Freemarker template.
Both inline template and external template file are supported.
When using an inline template, the template content has to be defined as string to the template
field:
Key | Type | Required |
---|---|---|
template | String | Yes |
When using an external file (.ftl), the content has to be defined as follows:
Key | Type | Required |
---|---|---|
template-path | String | Yes |
By default, it will search for the file in the ./workflows
root folder.
When a template is used, any workflow variable can be referenced in it, same format as it is for the any other activity in the SWADL file. Utility functions can also be used inside templates.
Example using Freemarker template:
id: pingPong
variables:
reply: pong
activities:
- send-message:
id: pingPong
on:
message-received:
content: /ping {message}
content:
template: \${variables.reply} - \${wdk.text(event.source.message.message)}
Since the workflow variables and freemarker variables are both referenced with $
sign, so the freemarker template
variables must be escaped by a back slash in front, another example
id: simples
variables:
data:
- roomName: "room1"
index: 1
- roomName: "room2"
index: 2
activities:
- send-message:
id: report
on:
message-received:
content: /list
content:
template: <ul> <#list variables.data as room > <li> \${room.index} - \${room.roomName} </li> </#list> </ul>
In this example, variables.data
is a workflow variable, which is going to be injected as template data to the template
engine by WDK, ${room.index}
and ${room.roomName}
are template variables, they must be escaped with a back slash.
Example using Freemarker template path
id: pingPong
variables:
reply: pong
activities:
- send-message:
id: pingMsg
on:
message-received:
content: /ping {message}
content:
template-path: message-with-params.ftl
message-with-params.ftl
<messageML>${variables.reply}: ${wdk.text(event.source.message.message)}</messageML>
In case the content to send is PresentationML. The text
function might come handy, it uses
the PresentationMLParser
from the BDK to extract the text content of a PresentationML message.
Example:
activities:
- send-message:
id: echo
on:
message-received:
content: /echo
content:
${text(event.source.message.message)}
One or more attachments to be sent along with the message. It can be either an existing attachment from another message or a file local to the bot. Previews are not supported.
Key | Type | Required |
---|---|---|
message-id | String | Yes |
attachment-id | Map | No |
or
Key | Type | Required |
---|---|---|
content-path | String | Yes |
Example: forwarding attachments
Message id having the attachment to forward. Both url safe and base64 encoded urls are accepted.
Attachment id to forward. If not set, all attachments in the provided message are forwarded. Both url safe and base64 encoded urls are accepted.
Path to the file to be attached to the message. The path is relative to the workflows folder.
A structured object can be sent as part of a message in this field. It must be a json string.
Example:
activities:
- send-message:
id: echo
on:
message-received:
content: /echo
content:
${text(event.source.message.message)}
data: "{
\"object001\":
{
\"type\": \"org.symphonyoss.fin.security\",
\"version\": \"1.0\",
\"id\":
[
{
\"type\": \"org.symphonyoss.fin.security.id.ticker\",
\"value\": \"IBM\"
},
{
\"type\": \"org.symphonyoss.fin.security.id.isin\",
\"value\": \"US0378331005\"
},
{
\"type\": \"org.symphonyoss.fin.security.id.cusip\",
\"value\": \"037833100\"
}
]
}
}"
One could also use Utility function to escape the data json string, the same example above can be done like
Example
variables:
data: {
"object001":
{
"type": "org.symphonyoss.fin.security",
"version": "1.0",
"id":
[
{
"type": "org.symphonyoss.fin.security.id.ticker",
"value": "IBM"
},
{
"type": "org.symphonyoss.fin.security.id.isin",
"value": "US0378331005"
},
{
"type": "org.symphonyoss.fin.security.id.cusip",
"value": "037833100"
}
]
}
}
activities:
- send-message:
id: echo
on:
message-received:
content: /echo
content:
${text(event.source.message.message)}
data: ${escape(variables.data)}
Update an existing message into a stream. Returns the new updated message.
Key | Type | Required |
---|---|---|
message-id | String | Yes |
content | String/Object | Yes |
silent | Boolean | No |
Output | Type |
---|---|
message | V4Message |
msgId | String |
Message id of the message to be updated. Both url safe and base64 encoded urls are accepted.
Silent flag in the update message activity. The new updated message will be marked as read when the flag is set to true, unread otherwise. The default value is true.
Pin an existing message into the stream it belongs to. It works for both Instant Messages and Rooms.
Key | Type | Required |
---|---|---|
message-id | String | Yes |
Depending on the stream type the activity will either call the Update Room or the Update IM endpoint.
Unpin any message (if present) from an existing stream. It works for both Instant Messages and Rooms.
Key | Type | Required |
---|---|---|
stream-id | String | Yes |
Depending on the stream type the activity will either call the Update Room or the Update IM endpoint.
Returns a message found by id.
Key | Type | Required |
---|---|---|
message-id | String | Yes |
Output | Type |
---|---|
message | V4Message |
Get messages from an existing stream (IM, MIM, or chatroom). Additionally, returns any attachments associated with the message.
Key | Type | Required |
---|---|---|
stream-id | String | Yes |
since | String | Yes |
limit | Number | No |
skip | Number | No |
Output | Type |
---|---|
rooms | List of V4Message |
Date, in ISO 8601 format, of the earliest possible data of the first message returned.
Example: 2021-08-31T15:50:00Z
Downloads an attachment to file system and returns its path. The stored file is suffixed with the executed activity id and stored under a folder with the executed process id.
An attachment named logo.png will be stored under ./workflows/$PROCESS_ID/$ACTIVITY_ID-logo.png.
nb: The stored files are not cleaned when the workflow stops and it is up to workflow's developer to do it.
Key | Type | Required |
---|---|---|
message-id | String | Yes |
attachment-id | String | Yes |
Output | Type |
---|---|
attachmentPath | String |
API reference (Activity does not return the same outputs as the api response)
Creates a new chatroom.
Key | Type | Required |
---|---|---|
room-name | String | Yes |
room-description | String | Yes |
user-ids | List | Yes |
public | Boolean | No |
Either room-name
and room-description
are set, or user-ids
are.
Output | Type |
---|---|
roomId | String |
Examples:
activities:
- create-room:
id: createPublicRoom
room-name: "A public room"
room-description: "With a description"
public: true
activities:
- create-room:
id: createMim
user-ids:
- 123
- 456
- 789
Room's name. Room names will be considered the same if they only differ in capitalization and whitespace. E.g. "room1" and "R O O M 1" are considered the same. Also, room names must be shorter than 50 characters.
Room's description.
List of user ids as strings. Used to create an IM or MIM room (i.e. no name, nor description can be set).
If true, this is a public chatroom. If false, a private chatroom. Note: Once this value is set for a room, it is read-only and can’t be updated.
Updates the attributes of an existing chat room.
Key | Type | Required |
---|---|---|
stream-id | String | Yes |
room-name | String | Yes |
room-description | String | Yes |
keywords | Map | Yes |
members-can-invite | Boolean | No |
discoverable | Boolean | No |
public | Boolean | No |
read-only | Boolean | No |
copy-protected | Boolean | No |
cross-pod | Boolean | No |
view-history | Boolean | No |
multilateral-room | Boolean | No |
active | Boolean | No |
Output | Type |
---|---|
room | V3RoomDetail |
Example:
activities:
- update-room:
id: activateRoom
stream-id: A_STREAM_ID
active: true
Stream's id to update. Both url safe and base64 encoded urls are accepted.
A list of key-value pairs, describing additional properties of the room.
If true, any chat room participant can add new participants. If false, only owners can add new participants.
If true, this chat room (name, description and messages) non-participants can search for this room. If false, only participants can search for this room.
If true, only stream owners can send messages. Note: Once this value is set for a room, it is read-only and can’t be updated.
If true, users cannot copy content from this room. Note: Once this value is set to true for a room, it is read-only and can’t be updated.
If true, this room is a cross-pod room.
If true, new members can view the room chat history of the room.
If true, this is a multilateral room where users belonging to more than 2 companies can be found.
If false, the room is not active anymore.
Adds new members to an existing room.
Key | Type | Required |
---|---|---|
stream-id | String | Yes |
user-ids | List | Yes |
Example:
activities:
- add-room-member:
id: addRoomMember
stream-id: A_STREAM_ID
user-ids:
- 123
- 456
Removes members from an existing room.
Key | Type | Required |
---|---|---|
stream-id | String | Yes |
user-ids | List | Yes |
Promotes user to owner of the chat room.
Key | Type | Required |
---|---|---|
stream-id | String | Yes |
user-ids | List | Yes |
Demotes room owner to a participant in the chat room.
Key | Type | Required |
---|---|---|
stream-id | String | Yes |
user-ids | List | Yes |
Returns information about a particular stream.
Key | Type | Required |
---|---|---|
stream-id | String | Yes |
Output | Type |
---|---|
stream | V2StreamAttributes |
Example:
${ACTIVITY_ID.outputs.stream.roomAttributes.name}
to access the stream's name.
Returns information about a particular chat room.
Key | Type | Required |
---|---|---|
stream-id | String | Yes |
Output | Type |
---|---|
room | V3RoomDetail |
Example:
${ACTIVITY_ID.outputs.room.roomAttributes.name}
to access the room's name.
Returns a list of all the streams (IMs, MIMs, and chatrooms) for the calling user's company, sorted by creation date ( ascending – oldest to newest).
Key | Type | Required |
---|---|---|
types | List | No |
scope | String | No |
origin | String | No |
privacy | String | No |
status | String | No |
start-date | String | No |
end-date | String | No |
limit | Number | No |
skip | Number | No |
Output | Type |
---|---|
streams | V2AdminStreamList |
A list of stream types that will be returned (IM, MIM, ROOM). If not specified, streams of all types are returned.
The scope of the stream: INTERNAL (restricted to members of the calling user's company) or EXTERNAL (including members of the calling user's company, as well as another firm). If not specified, returns streams of either scope.
The origin of the room: INTERNAL (created by a user of the calling user's company) or EXTERNAL (created by a user of another company). If not specified, returns streams of either origin. Only applies to chatrooms with External scope.
The privacy setting of the room: PRIVATE (members must be added) or PUBLIC (anyone can join). If not specified, returns both private and public rooms. Only applies to chatrooms with internal scope.
The status of the room: ACTIVE or INACTIVE. If not specified, both active and inactive streams are returned.
Restricts result set to rooms that have been modified since this date (ISO 8601). When specified along with end-date, enables the developer to specify rooms modified within a given time range.
Restricts result set to rooms that have been modified prior to this date (ISO 8601). When specified along with start-date, enables the developer to specify rooms modified within a given time range.
Search for rooms, querying name, description, and specified keywords.
Key | Type | Required |
---|---|---|
query | String | Yes |
labels | List | No |
active | Boolean | No |
private | Boolean | No |
creator-id | Number | No |
owner-id | Number | No |
sort-order | Number | No |
limit | Number | No |
skip | Number | No |
Output | Type |
---|---|
rooms | V3RoomSearchResults |
The query which is searched for in room name, description, and optionally keywords. Case-insensitive.
A list of room keywords whose values will be queried.
If true, it restricts the search to active rooms. If false, it restricts the search to inactive rooms. If not specified, it includes both active and inactive rooms. Note that for inactive rooms, only rooms where the calling user is a member will be in the search scope; read the box “Room Search Scope” for further details.
If true, it includes only private rooms in the search results. If false, only public rooms are returned. If not specified, both public and private rooms are returned. Note that for inactive rooms, only discoverable rooms and rooms where the calling user is a member will be in the search scope; read the box “Room Search Scope” for further details.
If provided, restrict the search to rooms created by the specified user.
If provided, restrict the search to rooms owned by the specified user.
If provided, restrict the search to rooms where the specified user is a member.
Sort algorithm to be used. Supports two values: BASIC (legacy algorithm) and RELEVANCE (enhanced algorithm).
Returns a list of all the streams of which the requesting user is a member, sorted by creation date (ascending - oldest to newest).
Key | Type | Required |
---|---|---|
types | List | No |
include-inactive-streams | Boolean | No |
limit | Number | No |
skip | Number | No |
Output | Type |
---|---|
streams | List of StreamAttributes |
A list of stream types that will be returned. If not specified, all types of streams are returned. Allowed values:
- IM
- MIM
- ROOM
- POST
Whether to include inactive conversations. A chatroom is inactive if it has been deactivated by an owner or admin. An IM or MIM is inactive if one of the participating users has been deactivated by an admin. If not specified, only active streams are returned.
Returns a list of all the current members of a stream (IM, MIM, or chatroom).
Key | Type | Required |
---|---|---|
stream-id | String | Yes |
limit | Number | No |
skip | Number | No |
Output | Type |
---|---|
members | V2MembershipList |
Maximum number of elements to be returned - used for pagination. Maximum allowed is 1000.
Paginating can be achieved with loops as shown in this example. Be careful about the amount of data retrieved though! If you have to paginate over all the elements, the content export feature might be more appropriate.
Number of elements to be skipped during return - used for pagination.
Lists the current members of an existing room.
Key | Type | Required |
---|---|---|
stream-id | String | Yes |
Output | Type |
---|---|
members | List of MemberInfo |
Creates a new end user.
Key | Type | Required |
---|---|---|
String | Yes | |
firstname | String | Yes |
lastname | String | Yes |
display-name | String | Yes |
username | String | Yes |
password | Map | No |
recommended-language | String | No |
contact | Map | No |
business | Map | No |
roles | List | No |
entitlements | Map | No |
status | String | No |
Output | Type |
---|---|
user | V2UserDetail |
Examples:
- create user workflow
${ACTIVITY_ID.outputs.user.userAttributes.firstName}
to access the created user's firstname${ACTIVITY_ID.outputs.user.userSystemInfo.id}
to access the created user's id
Email address, must be unique.
User's first name.
User's first name.
User's display name.
Unique identifier for the user.
User's password. The password object is optional. For example, if your organization utilizes SSO, you may not want to specify the password.
Key | Type | Required |
---|---|---|
hashed-password | String | Yes |
hashed-salt | String | Yes |
hashed-km-password | String | No |
hashed-km-salt | String | No |
Passwords and salts are base64-encoded strings.
The recommended language. As an ISO 639-1 code.
Example: en-US
Contact information.
Key | Type | Required |
---|---|---|
work-phone-number | String | No |
mobile-phone-number | String | No |
two-factor-auth-number | String | No |
sms-number | String | No |
Business information.
Key | Type | Required |
---|---|---|
company-name | String | No |
department | String | No |
division | String | No |
title | String | No |
location | String | No |
job-function | String | No |
asset-classes | List | No |
industries | List | No |
functions | List | No |
market-coverages | List | No |
responsibilities | List | No |
instruments | List | No |
Allowed value:
- Analyst
- Other
- Business Development Executive
- Corporate Access
- Developer
- Director
- Economist
- Portfolio Manager
- Project Manager
- Research Analyst
- Sales
- Strategist
- Trader
Allowed values:
- Equities
- Cash Equities
- Securities Lending
- Fixed Income
- Government Bonds
- Prime Brokerage
- Commodities
- Municipal Bonds
- Currencies
- Corporate Bonds
Allowed values:
- Healthcare
- Consumer Non-Cyclicals
- Transportation
- Technology
- Real Estate
- Basic Materials
- Financials
- Energy & Utilities
- Conglomerates
- Consumer Cyclicals
- Services
Allowed values:
- Collateral
- Confirmation
- Trade Processing
- Pre-Matching
- Margin
- Matching
- Claims Processing
- Middle Office
- Liquidity Management
- Allocation
- Trade Management
- Regulatory Outreach
- Settlements
- Post Trade Management
Allowed values:
- EMEA
- NA
- APAC
- LATAM
Allowed values:
- BAU
- Escalation
Allowed values for normal users:
- INDIVIDUAL
- ADMINISTRATOR
- SUPER_ADMINISTRATOR
- L1_SUPPORT
- L2_SUPPORT
- COMPLIANCE_OFFICER,
- SUPER_COMPLIANCE_OFFICER
Allowed values for system users:
- INDIVIDUAL
- USER_PROVISIONING
- SCOPE_MANAGEMENT
- CONTENT_MANAGEMENT
- MALWARE_SCAN_MANAGER
- MALWARE_SCAN_STATE_USER
- AUDIT_TRAIL_MANAGEMENT
A map with boolean values, possible (non-exhaustive) entries are:
- postReadEnabled
- postWriteEnabled
- delegatesEnabled
- isExternalIMEnabled
- canShareFilesExternally
- canCreatePublicRoom
- canUpdateAvatar
- isExternalRoomEnabled
- canCreatePushedSignals
- canUseCompactMode
- mustBeRecorded
- sendFilesEnabled
- canUseInternalAudio
- canProjectInternalScreenShare
- canViewInternalScreenShare
- canCreateMultiLateralRoom
- canJoinMultiLateralRoom
- canUseFirehose
- canUseInternalAudioMobile
- canUseInternalVideoMobile
- canProjectInternalScreenShareMobile
- canViewInternalScreenShareMobile
- canManageSignalSubscription
- canCreateDatahose
- canIntegrateEmail
- canReadDatahose
- canSuppressMessage
- canSwitchToClient20
- canUpdateRoomHistoryProperty
User status: ENABLED or DISABLED.
Updates an existing end user.
Key | Type | Required |
---|---|---|
user-id | String | Yes |
String | No | |
firstname | String | No |
lastname | String | No |
display-name | String | No |
username | String | No |
password | Map | No |
recommended-language | String | No |
contact | Map | No |
business | Map | No |
roles | List | No |
entitlements | Map | No |
status | String | No |
Keys are similar to user creation except they are all optionals expect the user-id
.
Output | Type |
---|---|
user | V2UserDetail |
Creates a new service user.
Key | Type | Required |
---|---|---|
String | Yes | |
display-name | String | Yes |
username | String | Yes |
keys | Map | No |
business | Map | No |
roles | List | No |
entitlements | Map | No |
status | String | No |
Output | Type |
---|---|
user | V2UserDetail |
Example: create system user workflow
For service users, to set up the RSA keys for authentication.
Key | Type | Required |
---|---|---|
current | String | Yes |
previous | String | Yes |
Key | Type | Required |
---|---|---|
action | String | Yes |
key | String | Yes |
expiration | String | No |
A string indicating the action to be performed on the user's RSA.
The following actions can be performed on the user's active RSA key:
- SAVE
- REVOKE
The following actions can be performed onto the user's rotated RSA key:
- REVOKE
- EXTEND
A string containing the user's RSA public key. The key must be 4096 bits. Only PKCS8 format is allowed.
An ISO 8601 timestamp containing the RSA key expiration date. This value is only set for rotated keys.
Updates an existing service user.
Key | Type | Required |
---|---|---|
user-id | String | Yes |
String | No | |
display-name | String | No |
username | String | No |
keys | Map | No |
business | Map | No |
roles | List | No |
entitlements | Map | No |
status | String | No |
Output | Type |
---|---|
user | V2UserDetail |
Adds roles to user accounts.
Key | Type | Required |
---|---|---|
user-ids | List | Yes |
roles | String | Yes |
Remove roles from user accounts.
Key | Type | Required |
---|---|---|
user-ids | List | Yes |
roles | String | Yes |
Returns details for a particular user.
Key | Type | Required |
---|---|---|
user-id | String | Yes |
Output | Type |
---|---|
user | V2UserDetail |
Example:
${ACTIVITY_ID.outputs.user.userAttributes.firstName}
to access the user's firstname
Returns a list of users ID, including user metadata.
Key | Type | Required |
---|---|---|
user-ids | List | Yes |
emails | List | Yes |
usernames | List | Yes |
local | Boolean | No |
active | Boolean | No |
One (and only one) of user-ids
, emails
or usernames
must be set.
Output | Type |
---|---|
users | List of V2UserDetail |
List of user ids. Note that for this activity, you can use either the user-ids, the emails or the usernames to make the call, but only one at a time, you cannot mix and match them.
List of email addresses. Note that for this activity, you can use either the user-ids, the emails or the usernames, but only one at a time, you cannot mix and match them.
List of usernames. If username is specified, local must be set to true. Note that for this activity, you can use either the user-ids, the emails or the usernames, but only one at a time, you cannot mix and match them.
If true then a local DB search will be performed and only local pod users will be returned. If absent or false then a directory search will be performed and users from other pods who are visible to the calling user will also be returned.
If true, it searches for active users only. If false, it searches for inactive users only. If not set, it searches for all users regardless of their status.
Get connection status, i.e. check if the calling user is connected to the specified user.
Key | Type | Required |
---|---|---|
user-id | String | Yes |
Output | Type |
---|---|
connection | UserConnection |
Send a connection request to another user.
Key | Type | Required |
---|---|---|
user-id | String | Yes |
Output | Type |
---|---|
connection | UserConnection |
Accept the connection request for a requesting user.
Key | Type | Required |
---|---|---|
user-id | String | Yes |
Output | Type |
---|---|
connection | UserConnection |
Reject the connection request from a requesting user.
Key | Type | Required |
---|---|---|
user-id | String | Yes |
Output | Type |
---|---|
connection | UserConnection |
Remove a connection with a user.
Key | Type | Required |
---|---|---|
user-id | String | Yes |
Get one or multiple connections statuses.
Key | Type | Required |
---|---|---|
user-ids | List | Yes |
status | String | Yes |
Output | Type |
---|---|
connections | List of UserConnection |
List of user ids that this activity results will be restricted to their connections.
Allowed values:
- PENDING_INCOMING
- PENDING_OUTGOING
- ACCEPTED
- REJECTED
- ALL
Create a group (distribution list). Distribution List Manager role is required to use this activity.
Key | Type | Required |
---|---|---|
name | String | Yes |
type | String | Yes |
owner | Map | Yes |
profile | Map | Yes |
members | List | Yes |
sub-type | String | No |
referrer | String | No |
Output | Type |
---|---|
group | ReadGroup |
Group type identifier (for instance SDL).
Key | Type | Required |
---|---|---|
id | String | Yes |
type | String | Yes |
Owner id if the owner type is tenant (podId) or user (userId), otherwise null.
Owner type. Only TENANT supported now.
Allowed values:
- TENANT
- PLATFORM
- USER
The type of the company new groupType.
Allowed values:
- COMMUNITY
- CHANNEL
Symphony, referring company name, referring channel partner name.
Key | Type | Required |
---|---|---|
user-id | Integer | Yes |
tenant-id | Integer | Yes |
See API for details.
At least display-name
should be set. Job properties are grouped under a job
entry.
Update a group (distribution list). Distribution List Manager role is required to use this activity.
Key | Type | Required |
---|---|---|
group-id | String | Yes |
e-tag | String | Yes |
status | String | Yes |
owner | Map | Yes |
profile | Map | Yes |
members | List | Yes |
name | String | No |
image-path | String | No |
type | String | No |
sub-type | String | No |
referrer | String | No |
Keys are similar to group creation.
E-tag must be passed and can be retrieved from a group with the get-group activity. It is used to avoid concurrent updates.
Output | Type |
---|---|
group | ReadGroup |
Status flag to distinguish between active and deleted objects.
Allowed values:
- ACTIVE
- DELETED
Path to the image file to be used as the group's avatar. The path is relative to the workflows folder.
Retrieve a group (distribution list). Distribution List Manager role is required to use this activity.
Key | Type | Required |
---|---|---|
group-id | String | Yes |
Output | Type |
---|---|
group | ReadGroup |
Retrieve groups of specified type (distribution list). Distribution List Manager role is required to use this activity.
Key | Type | Required |
---|---|---|
type | String | Yes |
status | String | No |
before | String | No |
after | String | No |
limit | String | No |
sort-order | String | No |
Output | Type |
---|---|
groups | GroupList |
Group type id.
Filter by status, active or deleted. If not specified both are returned.
Allowed values:
- ACTIVE
- DELETED
Not supported yet, currently ignored. Cursor that points to the start of the current page of data. If not present, the current page is the first page.
Cursor that points to the end of the current page of data. If not present, the current page is the last page.
Numbers of items to return.
Items sorting direction (ordered by creation date).
Allowed values:
- ASC
- DESC
Add members to a group (distribution list). Distribution List Manager role is required to use this activity.
Key | Type | Required |
---|---|---|
group-id | String | Yes |
members | List | Yes |
Output | Type |
---|---|
group | ReadGroup |
Executes an HTTP request.
Key | Type | Required |
---|---|---|
url | String | Yes |
method | String | No |
body | Object/String | No |
headers | String | No |
encode-query-params | Boolean | No |
Output | Type | |
---- | ---- | |
body | Object/String | |
status | Integer |
If the response body has a application/json
content type then the body
output is parsed into a JSON object (if
possible) otherwise it will a string. Please note that this approach comes with limitations and that
the execute-request
activity should not be used to download large payloads.
Example:
activities:
- execute-request:
id: myRequest
headers:
X-Workflow-Token: A_TOKEN
Content-Type: application/json # optional as it is the default value
Accept: application/json
body:
myName: Bob
method: POST
url: https://api.com/helloWorld # an API that returns {"message": "Hello Bob"}
- send-message:
id: sendMsg
to:
stream-id: A_STREAM
content: ${myRequest.outputs.body.message} # Send a message with content "Hello Bob"
String that contains the host and the path to be targeted.
The query parameters values are, by default, encoded with UTF-8 format by the activity. The encoding can be disabled using encode-query-params.
HTTP method to perform. GET is the default one.
Supported methods are:
- DELETE
- GET
- HEAD
- OPTIONS
- PATCH
- POST
- PUT
HTTP request body. It can be provided as an object (for application/json
or multiplart/form content
type) or as a
string.
When multipart/form
content type is used, only key/value object is supported.
HTTP request headers. A map of key/value entries is expected. Simple types such as numbers, string and booleans as well as lists and maps are supported.
Unless set explicitly the Content-Type
header will be application/json
by default.
If false, the url query parameters will not be encoded. It is set to true by default.
Executes a Groovy script.
Key | Type | Required |
---|---|---|
script | String | Yes |
Example:
activities:
- execute-script:
id: myScript
script: |
// variables can be accessed from a script
variables.foo = "Hello"
// BDK beans are accessible
messageService.send("123", variables.foo)
// output goes to the workflow bot logs
println "Hello"
Script to execute (only Groovy is supported).
OBO or On-Behalf-Of authentication allows an extension application to be able to execute an activity on behalf of an application end-user, when the activity is OBO enabled.
The property obo
is used to define the user executing the activity using either his username or the user id.
Example:
- send-message:
id: sendMessageObo
content: Message sent on behalf of user 734583310035744
to:
stream-id: ${createRoomObo.outputs.roomId}
obo:
user-id: 734583310035744
- create-room:
id: createRoomObo
room-name: OBO created room
room-description: Example of a room created with obo
user-ids:
- 734583310035744
- 625588317732700
obo:
username: [email protected]
The list of OBO enabled activities:
- send-message
- pin-message
- unpin-message
- create-room
- update-room
- add-room-member
- remove-room-member
- promote-room-owner
- demote-room-owner
- get-stream
- get-room
- get-rooms
- get-user-streams
- get-users
- create-connection
- get-connection
- get-connections
- remove-connection
- accept-connection
- reject-connection
WDK provides some utility functions that can be used to process data in SWADL or in templates.
This method is used to convert a String in JSON format to an Object in order to be processed as a JSON. It returns a String if the parameter is a simple String.
Example: in send-message
variables:
aJson: "{\"result\": { \"code\": 200, \"message\": \"success\" } }"
aString: "This is a regular String"
activities:
- send-message: # will send 200
id: processJson
content: ${json(variables.aJson).result.code}
- send-message: # will send the string content
id: processJsonString
content: ${json(variables.aString)}
activities:
- execute-script:
id: scriptJson
script: |
assert wdk.json(variables.aJson).result.code == 200
assert wdk.json(variables.aString) == "This is a regular String"
This method is used to convert a PresentationML String to a text.
Example:
in send-message
variables:
presentationML: "<div data-format=\"PresentationML\" data-version=\"2.0\">started</div>"
activities:
- send-message:
id: extractText
content: ${text(variables.presentationML)}
activities:
- execute-script:
id: extractText
script: |
assert wdk.text(variables.presentationML) == "started"
This method will escape text contents using JSON standard escaping, and return results as a String.
Example:
in send-message
activities:
- send-message:
id: escapeText
content: ${escape(variables.textToEscape)}
activities:
- execute-script:
id: escapeText
script: |
println wdk.escape(variables.textToEscape)
This method will return session's bot information.
Example:
in send-message
activities:
- send-message:
id: sendBotDisplayName
content: ${session().displayName}
activities:
- execute-script:
id: printBotInfo
script:
println wdk.session().id
println wdk.session().displayName
Along side the global variables, WDK provides shared data, which is accessible (read and write via utility functions) among the a workflow process instances, and also among different workflows.
The shared data is organized by its namespace and and its key.
This method will read the value from the given namespace and the key.
Example:
in send-message
activities:
- send-message:
id: sendBotDisplayName
content: ${readShared('namespace', 'key')}
activities:
- execute-script:
id: printBotInfo
script: |
println wdk.readShared('namespace', 'key')
This method will write the shared data to the given namespace and under the given key.
Example:
activities:
- execute-script:
id: printBotInfo
script: |
wdk.writeShared('namespace', 'key', value);
Once a secret is upload to WDK through REST API ("/v1/workflows/secrets"), the secret is readable within SWADL via utility function.
Example:
activities:
- execute-script:
id: printBotInfo
script: |
wdk.secret('keyRef')
activities:
- execute-request:
id: request
headers:
Content-Type: application/json
Accept: application/json
Authorization: ${secret('token')}
method: GET
url: https://some-url