Sym SDK Overview
Use Python to extend and customize your Sym Flows.
Overview
From routing requests, to deciding who can approve them, to running side-effecting Lambdas in your VPC, the Sym SDK gives you the tools to extend and automate your Sym Flows with custom logic and third-party integrations
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.
Integrations, like PagerDuty, AWS Lambda, and Slack, are all covered in the Integrations section of our docs; Handlers are covered below.
The SDK's reference docs can be found at our here.
Integrations
The SDK exposes a set of integrations that 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.
For information on integrating specific services, see our Integrations Overview.
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 types of Handlers are reducers, hooks, and prefetch
Reducers are prefixed with get_
, and take in an Event
and return a single value.
Prefetch Reducers let you dynamically query for the data to show in a request field.
Hooks are prefixed with on_
or after_
, and allow you to alter control flow inserting custom logic before or after an Event
is processed.
The SDK's reference docs live elsewhere
Go here to see the full reference for the Sym SDK.
Handlers in context
Handlers fire at specific moments in a Sym Flow, giving you the power to define things like:
- Where requests are routed
- Scenarios in which requests are automatically approved or rejected
- How to handle third-party identity lookups
- What to do after a request cycle is completed
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, you will always need a way to let Sym know how to route a request. You may also want to inject some logic around whether a user is on-call in PagerDuty, or in a specific Okta group. This is exactly what the get_approvers
reducer is for:
from sym.sdk.annotations import reducer
from sym.sdk.integrations import pagerduty, okta, slack
@reducer
def get_approvers(event):
"""Returns a set of approvers, given a user and a target."""
if pagerduty.is_on_call(event.user, schedule_name="prod_on_call_schedule"):
# This is a self-approval in a DM
return slack.user(event.user)
if event.payload.fields["urgency"] == "High":
# This is a self-approval in a channel
return slack.channel("#break-glass", allow_self=True)
on_call_mgrs = okta.users_in_group(group_id="00g12345689")
# This would create a group DM for on-call managers
return slack.group(on_call_mgrs)
Prefetch Reducers
Prefetch Reducers are the Sym SDK's method for dynamically populating fields in Slack and enabling typeahead for your users. Like normal Reducers, Prefetch Reducersr will take an Event
. They also require an attribute representing a prompt_field
to be displayed in Slack.
Then, you can fill in your own code or invoke a Lambda to fetch a set of options and return them to the prompt_field
in Slack.
import requests
from sym.sdk.annotations import prefetch
from sym.sdk.field_option import FieldOption
@prefetch(field_name="targets")
def get_targets(event):
# Make an API Call or even invoke an AWS Lambda
response = requests.get(url="https://yourapi.foo/get-targets")
targets = response.json()["results"]
# Return a list of FieldOption
return [
FieldOption(value=target["name"], label=target["name"].upper())
for target
in targets
]
On-Hooks
On-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, you may want to auto-approve any requests that come from an on-call engineer:
from sym.sdk.annotations import hook
from sym.sdk.integrations import pagerduty
from sym.sdk.templates import ApprovalTemplate
# Hooks are optional, and can change control flow by returning Events
@hook
def on_request(event):
# Auto-approve urgent requests for access by the person on call
if event.payload.fields["urgency"] == "Urgent" and pagerduty.is_on_call(event.user):
return ApprovalTemplate.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, 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(event):
"""Executed after an approved event has been fired."""
message = f"{event.user.username} has been approved for {event.payload.fields["target"].name}!"
slack.send_message(slack.channel("#private-audit-log"), message)
Implementation guides and examples
See any of the guides below for guides and examples of Sym's SDK in action.
Guide | Description | Type |
---|---|---|
Customizing Flow Logic | Learn how to customize Flow logic, including the basics of Hooks and Reducers. | General information |
Working With Flow Fields and Data | Learn how to use field and Flow data from Terraform in your Python code. | General information |
Reducers: Routing and Identity | Learn about Reducers, which are helpful for routing Flows and managing use identity. | SDK Reference |
Hooks: Flow Control and Automation | Learn about Hooks, which help you control and automate your Flows. | SDK Reference |
Prefetch: Typeahead Fields | Learn about the special prefetch Reducer, which can be used to create custom typeahead fields. | SDK Reference |
Choosing Where Your Requests Go | Learn how to conditionally route your requests. | Implementation example |
Automating and Fast-Tracking Approvals | Learn how to automate, fast-track, and otherwise redirect requests. | Implementation example |
Defining Who Can Approve Requests | Learn how to manage who's allowed to approve and deny requests. | Implementation example |
More Implementation Examples | A grab bag of additional example snippets. | Implementation examples |
Updated about 1 month ago