Choosing Where Your Requests Go
Sym makes it easy to route different flows to different channels.
This is a mini-guide
This page is intended to practically introduce a handful basic Sym concepts, all of which are covered elsewhere in greater detail.
This page includes references to:
Overview
When you make a Sym request in Slack by running /sym
, three things will happen before the request shows up for approval:
- You will see a prompt asking you to select a Flow
- Depending on which Flow you choose, you will be prompted for input
- Depending on a combination of your chosen Flow + input, your request will be routed to a specific Slack channel
For the purposes of this guide, all Python implementation files will be referred to as impl.py
. You can (of course) name your files anything you'd like, but impl.py
is Sym's standard example filename.
Concepts
Every Flow must reference an impl.py
impl.py
Every sym_flow
resource must reference an impl.py
file that contains your custom logic for the Flow. The same impl.py
may be referenced by multiple Flows.
resource "sym_flow" "this" {
name = "approval"
label = "Approval"
# This is the contents of this Flow's Python Implementation file
implementation = file("${path.module}/impl.py")
...
}
Workflow Handlers contain your Flow logic
Workflow Handlers are specially-decorated and -named functions that execute at specific times during a Flow's lifecycle. While your impl.py
files may contain various helper functions, all logic that directly impacts a Flow will be contained in a Handler.
The only required Handler is a Reducer called get_approvers(event)
, which takes an event
representing the Flow being executed, and returns information about the Flow's approval path.
The simplest implementation of get_approvers(event)
is to explicitly declare a destination channel for all executions of a given Flow. In the below example, we are also declaring that users may not approve their own requests.
from sym.sdk.annotations import reducer
from sym.sdk.integrations import slack
@reducer
def get_approvers(event):
return slack.channel("#sym-requests", allow_self=False)
Pass variables from Terraform to your impl.py
impl.py
In some cases, you might want to extract information from your Flow's event
and use it to make variable decisions. For example, if you want to check the urgency of a request, and in cases of "Emergency," route the request to a different channel, you might want to introduce Flow Variables.
For Flow Variables, we recommend the following pattern:
Define your flow_variables
in a .tfvars
file
flow_variables
in a .tfvars
fileflow_variables = {
request_channel = "#sym-requests"
emergency_channel = "#sym-emergencies"
}
Declare your flow_variables
in a variables.tf
file
flow_variables
in a variables.tf
filevariable "flow_variables" {
description = "Configuration values for the Flow, available in its implementation for hooks and reducers."
type = map(string)
default = {}
}
Reference your variables
in your sym_flow
variables
in your sym_flow
Note that below, we are also introducing a prompt_field
called "Urgency" through which a Flow user can declare an "Emergency."
resource "sym_flow" "aws_sso" {
name = "approval"
label = "Approval"
implementation = file("${path.module}/impl.py")
# This ensures your vars are available to this Flow's impl.py
vars = var.flow_variables
params {
strategy_id = sym_strategy.this.id
prompt_field {
name = "reason"
label = "Why do you need access?"
type = "string"
required = true
}
prompt_field {
name = "urgency"
label = "Urgency"
type = "string"
required = true
allowed_values = ["Normal", "Emergency"]
}
}
}
Use your Flow Variables to make decisions in your impl.py
impl.py
Now that we have our "Urgency" prompt and our Flow Variables, we can use both to construct a more nuanced get_approvers(event)
function:
from sym.sdk.annotations import reducer
from sym.sdk.integrations import slack
@reducer
def get_approvers(event):
# Make sure our Flow Variables are available
fvars = event.flow.vars
# Logic to route requests based on "Urgency"
if event.payload.fields.get("urgency") == "Normal"
return slack.channel(fvars["request_channel"], allow_self=False)
elif event.payload.fields.get("urgency") == "Emergency"
return slack.channel(fvars["emergency_channel"], allow_self=True)
Congratulations! Now you know how to manage the Slack destination for requests for your Sym Flows. π
Updated about 1 month ago