symflow generate


You can generate the Terraform and Python files needed to configure a Sym Flow with symflow generate!

This command must be run inside of the directory created by symflow init, and it will prompt you for the information needed to set up your Sym Flow. Most resources will differ based on the chosen type of Flow, but commonly there will be:


The Terraform configuration of a sym_flow can be broken down into two parts:

The basics

resource "sym_flow" "basic_approval" {
  name  = "basic-approval"
  label = "Approval-Only"

  implementation = file("${path.module}/impls/")
  environment_id =

  vars = {
    auto_approve = "[email protected]"

The basic configuration of a sym_flow includes:

nameA unique, human-readable identifier for the Flow. This can be used to run the Flow directly in Slack (e.g. /sym req approval)Yes
labelThe display name for the Flow. This is what you'll see in Slack.No
implementationThe path to a file where the Sym Python SDK will be used to customize the workflow. More on that later!Yes
environment_idWhat Environment this Flow belongs to. This can be helpful to separate Flows you're still iterating on and testing from Flows that are stable and used every day by your organization. Think "main" vs. "sandbox" or "prod" vs. "staging".Yes
varsA string to string map of values to pass to impl.pyNo
`name`, `label`, and `environment` are surfaced in the Slack modal.

name, label, and environment are surfaced in the Slack modal.

The prompt fields

Different types of access requests need different types of data. That's why Flows support custom fields in the request modal! We've kept it fairly basic here with just two generic questions— "what do you need access to" and "why"— but fields can be as specific as needed. Check out Prompt Fields for more information.

resource "sym_flow" "basic_approval" {

  params {
    # The prompt_field block defines a custom form field for the Slack modal that
    # requesters fill out to make their requests.
    prompt_field {
      name     = "resource-identifier"
      label    = "What do you need access to?"
      type     = "string"
      required = true

    prompt_field {
      name     = "reason"
      label    = "Why do you need access?"
      type     = "string"
      required = true
A Slack modal with input boxes for what to request access to and why

prompt_fields become form fields for your request modal!


A folder that houses all the files. symflow generate will generate a new file per Flow, but you may choose to reuse implementations across Flows if you so choose.

The Python Implementation

Now that the sym_flow resource is configured, all that's left is to write its This is where Sym's Python SDK can be used to customize your Flow's logic.

The first thing we'll need in the is a get_approvers reducer. This is the only required part of an, and it tells Sym where to send access requests in Slack:

# First, we'll import everything we need for this
from sym.sdk.annotations import reducer
from sym.sdk.integrations import slack

# Then, we add our first reducer! `get_approvers` will be used any time a request
# is made in Sym.
def get_approvers(event):
    """Route Sym requests to a specified channel."""

    # Make sure that this channel has been created in your workspace!
    return"#sym-requests", allow_self=True)

While get_approvers is the only required function in the, there are many other hooks that you can implement.

If you generated a Flow that requires Sym to interact with your AWS account, such as okta or aws-iam, then a file will be generated for you. This file contains the AWS resources needed to allow Sym to perform actions in your AWS account. For more details, see Connecting Sym to AWS.

If you generated a Flow that interacts with a third-party service that requires authentication, such as okta, then a file will be generated for you. This file contains the Terraform module needed to allow Sym to read secrets from your AWS Secrets Manager. For more details, see Manage Secrets with AWS Secrets Manager.

Testing in Slack

Almost there! All the Terraform configuration is now written, all that's left to do is test it out. We'll start by applying the Terraform:

$ terraform init

Initializing the backend...
Initializing provider plugins...
Terraform has been successfully initialized!

$ terraform apply

sym_integration.slack: Creating...
sym_integration.slack: Creation complete after 1s [id=2127a917-f92b-491a-ba63-6556734b152c]
sym_error_logger.slack: Creating...
sym_error_logger.slack: Creation complete after 0s [id=358fa690-c5bb-457e-9527-ef5aad12a542]

Once the terraform apply is done:

  1. Go to the Slack workspace you installed Sym in
  2. Type /sym anywhere

You should see your very first Sym Flow:

A Slack modal displaying an Approval-Only Sym Flow

Next steps

Nice job! You should have a Sym Flow up and running. Now that you've got the basics down, there are a ton of ways to tailor Sym to your organization's needs. To learn more, check out:

  • Integrated Services - Learn how Sym can automatically grant or escalate access to external services like AWS, Okta, and Aptible.
  • Approval workflows-as-code - Learn how to customize the to fit your specific rules using our Python SDK.
  • Reporting and audit - Learn how to get structured logs for all access requests and set your organization up for audit success via our Reporting framework.


Check out our Examples Repo for end-to-end examples

If you're looking for some fully-baked samples of working Sym Flows, head over to our Examples Repo!