Python SDK

Use Python to create guardrails and routing logic for your Flows

Overview

Sym provides a comprehensive SDK that you can use to craft complex workflows-as-code that align perfectly with your business processes.

The Sym SDK has two main components:

  • Integrations that interact with third party services.
  • Workflow handlers that you can use to inject custom logic into your process.

The SDK's API-level documentation can be found at our SDK Docs.

Distribution

The Sym SDK is distributed as a Python 3 library on pip

$ pip install sym-sdk
Collecting sym-sdk
  Downloading sym_sdk-0.1.1-py3-none-any.whl (146 kB)
     |████████████████████████████████| 146 kB 6.4 MB/s
Installing collected packages: sym-sdk
Successfully installed sym-sdk-0.1.1

Integrations

The SDK exposes a set of integrations, which allow your workflow to connect to external services such as Slack and PagerDuty. Use integrations to check and manage memberships, send additional messages, or call out to external services. Learn more here.

Workflow Handlers

Under the hood, each Sym Flow consists of a series of discrete steps that can be interrupted or redirected with custom logic wrapped in Handler functions. The two types of Handlers are reducers and hooks.

Reducers take in an Event and return a single value, and are prefixed with get_.

Hooks prefixed with on_ allow you to alter control flow by overriding default implementations of Template steps.

Hooks prefixed with after_ allow you to subscribe to Events so as to enact various side-effects.

📘

Handlers are defined in the sym.sdk.annotations module.

Reducers

A Reducer injects key logic into Flows by taking an Event as input, and returning a single value.

For example, when using the sym:approval Template, you need a way to let Sym know who to route a specific request to. This is exactly what the get_approvers reducer does! To implement it, you write a Python function which takes in an Event (containing the requesting user and requested Target), and return a set of User-like objects (such as email addresses, Slack handles, Slack channels or Okta groups).

from sym.sdk.annotations import reducer
from sym.sdk.integrations import pagerduty, okta, slack

# Reducers can be mandatory, and provide dynamic config values

@reducer 
def get_approvers(evt):
    """Returns a set of approvers, given a user and a target."""
   
    # The import here uses credentials defined in an Integration in Terraform
    if pagerduty.is_on_call(evt.user, schedule="id_of_eng_on_call"):
        # This is a self-approval in a DM
        return slack.user(evt.user)

    if evt.payload.fields["urgency"] == "High":
        # This is a self-approval in a channel
        return slack.channel("#break-glass", allow_self=True)

    on_call_mgrs = okta.group("OnCallManagers").members()
    # This would create a group DM for on-call managers
    return slack.group(on_call_mgrs)

On-Hooks

Hooks are executed before the default implementation of an Event handler in a Template. They offer an opportunity to bypass, short-circuit, or alter control flow, by emitting Events.

For example, when using the sym:approval Template, you may want to auto-approve any requests that come from interns (what could go wrong!).

from sym.sdk.annotations import hook
from sym.sdk.integrations import okta
from sym.sdk.templates.approval import events

# Hooks are optional, and can change control flow by returning Events

@hook
def on_request(evt):
    """Executed after a request is made, before the default handler."""
    if "Intern" in okta.user(evt.user).profile["job_title"]:
        return events.approve()

After-Hooks

After Hooks are executed after the default implementation of an Event handler in a Template. They offer an opportunity to execute additional side-effects, such as logging or notifications.

For example, when using the sym:approval Template, you may want to log every approval to a private Slack channel.

from sym.sdk.annotations import hook
from sym.sdk.integrations import slack

# After-hooks are optional, and let you execute side-effects after an Event

@hook
def after_approve(evt):
    """Executed after an approved event has been fired."""
    message = f"{evt.user.name} has been approved for {evt.target.name}!"
    slack.send_message("#private-audit-log", message)

Did this page help you?