The documentation you're currently reading is for version 2.3.2. Click here to view documentation for the latest stable version.

Create and Contribute a Pack

Packs have a defined structure that is prescribed by BWC. It is required to follow this structure while creating your own pack and is also helpful to know while debugging issues with packs.

Anatomy of a Pack

Canonical pack as laid out on the file system.

# contents of a pack folder
actions/                 #
rules/                   #
sensors/                 #
aliases/                 #
policies/                #
tests/                   #
etc/                     # any additional things (e.g code generators, scripts...)
config.schema.yaml       # configuration schema
packname.yaml.example    # example of config, used in CI
pack.yaml                # pack definition file
requirements.txt         # requirements for Python packs
requirements-tests.txt   # requirements for python tests
icon.png                 # 64x64 .png icon

At the topmost level are the main folders actions, rules, sensors, aliases and policies as well as some shared files:

  • pack.yaml - Metadata file that describes and identifies the folder as a pack.
  • config.schema.yaml - Schema that defines configuration elements used by a pack.
  • requirements.txt - File containing a list of python dependencies.

Site-specific pack configuration files are stored at /opt/stackstorm/configs/. See configuration schema for more information.

# contents of actions/

The actions folder contains action script files and action metadata files. See Actions and Workflows for specifics on writing actions. Since metadata files and workflow definitions can both be written as YAML, it’s good practice to put the workflow definitions in a separate directory. Note that the lib sub-folder is always available for access for an action script.

# contents of rules/

The rules folder contains rules. See Rules for specifics on writing rules.

# contents of sensors/

The sensors folder contains sensors. See Sensors for specifics on writing sensors and registering TriggerTypes.

# contents of aliases/

The aliases folder contains Action Aliases. See Action Alias for specifics on writing Action Aliases.

# contents of policies/

The policies folder contains Policies. See Policies for specifics on writing Policies.

Creating Your First Pack

In the example below, we will create a simple pack named hello_st2. The full example is also available at st2/contrib/hello_st2.

  1. Create the pack folder structure and related files. Let’s keep the metadata files such as pack.yaml, config.schema.yaml, and requirements.txt empty for now:
# Use the name of the pack for the folder name.
mkdir hello_st2
cd hello_st2
mkdir actions
mkdir rules
mkdir sensors
mkdir aliases
mkdir policies
touch pack.yaml
touch requirements.txt

Note: All folders are optional. If a folder is present, it is inspected for content. So it is safe to skip a folder or keep it empty. Only create the config.schema.yaml file if it is required. An empty schema file is not valid.

  1. Create pack definition file, pack.yaml:
ref: hello_st2
name: Hello StackStorm
description: A simple pack containing examples of sensor, rule, and action.
    - example
    - test
version: 0.1.0
author: st2-dev


A note on metadata: BWC enforces certain rules about metadata. The version value in pack.yaml must conform to semver:0.2.5, not 0.2. The name value in pack.yaml must only contain letters, digits, and underscores, unless you set the ref value explicitly in pack.yaml. Finally the email attribute in pack.yaml must contain a properly formatted email address.

3. Create the action. Action consists of meta data, and entrypoint. The following example simply echoes a greeting.

Copy the following content to actions/greet.yaml:

name: greet
pack: hello_st2
runner_type: "local-shell-cmd"
description: Greet StackStorm!
enabled: true
        type: string
        description: Greeting you want to say to StackStorm (i.e. Hello, Hi, Yo, etc.)
        required: true
        position: 1

Copy the following content to actions/

echo "$1, StackStorm!"
  1. Create a sensor. The sample sensor below publishes an event to BWC every 60 seconds.

Copy the following content to sensors/sensor1.yaml

class_name: "HelloSensor"
entry_point: ""
description: "Test sensor that emits triggers."
    name: "event1"
    description: "An example trigger."
      type: "object"

Copy the following content to sensors/

import eventlet

from st2reactor.sensor.base import Sensor

class HelloSensor(Sensor):
    def __init__(self, sensor_service, config):
        super(HelloSensor, self).__init__(sensor_service=sensor_service, config=config)
        self._logger = self.sensor_service.get_logger(name=self.__class__.__name__)
        self._stop = False

    def setup(self):

    def run(self):
        while not self._stop:
            self._logger.debug('HelloSensor dispatching trigger...')
            count = self.sensor_service.get_value('hello_st2.count') or 0
            payload = {'greeting': 'Yo, StackStorm!', 'count': int(count) + 1}
            self.sensor_service.dispatch(trigger='hello_st2.event1', payload=payload)
            self.sensor_service.set_value('hello_st2.count', payload['count'])

    def cleanup(self):
        self._stop = True

    # Methods required for programmable sensors.
    def add_trigger(self, trigger):

    def update_trigger(self, trigger):

    def remove_trigger(self, trigger):
  1. Create a rule. The sample rule below is triggered by event from the sensor and invokes the action from the samples above.

Copy the following content to rules/rule1.yaml

name: on_hello_event1
pack: hello_st2
description: Sample rule firing on hello_st2.event1.
enabled: true
    type: hello_st2.event1
    ref: hello_st2.greet
        greeting: Yo
  1. Create an action alias. The sample action alias below aliases the greet action and makes it accessible from ChatOps.

Copy the following content to aliases/alias1.yaml

name: greet
pack: hello_st2
description: "Greet StackStorm"
action_ref: "hello_st2.greet"
  - "greet {{greeting}}"
  1. Create a policy. The sample policy below limits concurrent operation of the greet action.

Copy the following content to policies/policy1.yaml

name: greet.concurrency
pack: hello_st2
description: Limits the concurrent executions of the greet action.
enabled: true
resource_ref: hello_st2.greet
policy_type: action.concurrency
    threshold: 10

8. Install the pack. We encourage using git, if you do so, st2 pack will greatly simplify your pack management. However you can define your own tools and workflow for editing and versioning packs; you’ll be placing the files to /opt/stackstorm/packs and [re-]loading the content.

8.1 Use git and pack install (recommended):

# Get the code under git
cd hello_st2
git init && git add ./* && git commit -m "Initial commit"
# Install from local git repo
st2 pack install file:///$PWD

When you make code changes, run st2 pack install again: it will do the upgrade. Once you push it to GitHub, you will install and update it right from there:

st2 pack install

8.2 Copy over and register (if you have special needs and know what you’re doing).

mv ./hello_st2 /opt/stackstorm/packs
st2ctl reload

Congratulate yourself: you have created your first pack. Commands like st2 pack list, st2 action list, st2 rule list and st2 trigger list will show you the loaded content. To check if the sensor triggering action is working, run st2 execution list, there should be an entry for executing hello_st2.greet every minute.

Take it from there. Write an awesome automation, or an inspiring integration pack with your favorite tool. Happy hacking!

Submitting a Pack to the Community

Now that you forged this awesome pack in BWC it’s time, and a good form, to share your awesomeness with the community. StackStorm Exchange is the place for you and everyone else to share and pull integration packs.

To feature your pack on the StackStorm Exchange, submit a GitHub pull request to StackStorm Exchange Incubator repository. Our team will review the PR, accept it to the incubator, graduate it to the main “Exchange”, and help you promote it.

Contributors License Agreement

By contributing you agree that these contributions are your own (or approved by your employer) and you grant a full, complete, irrevocable copyright license to all users and developers of the project, present and future, pursuant to the license of the project.

Questions? Problems? Suggestions? Engage!