Skip to content

Writing Workflows

Workflows are Python scripts in the workflows/ directory with @stage-decorated functions.

Basic Structure

# workflows/my_flow.py
from restful import stage, WorkflowContext

@stage("Step 1 — Fetch")
def fetch(ctx: WorkflowContext):
    response = ctx.clients.sfm.get(instance_rest.BlueprintTemplates)
    templates = response.json()["BlueprintTemplate"]
    ctx.set("template_count", str(len(templates)))

@stage("Step 2 — Process")
def process(ctx: WorkflowContext):
    count = int(ctx.get("template_count"))
    if count > 0:
        # Create infrastructure
        ctx.clients.sfm.post(instance_rest.Infrastructures, payload={
            "Name": f"auto-infra-{count}",
        })

Passing Data Between Stages

Use ctx.set() and ctx.get() to pass data:

@stage("Extract")
def extract(ctx: WorkflowContext):
    response = ctx.clients.sfm.get(endpoint)
    ctx.set("infra_id", response.json()["Id"])

@stage("Use")
def use(ctx: WorkflowContext):
    infra_id = ctx.get("infra_id")
    ctx.clients.sfm.get(InfraDetails, params={"id": infra_id})

All variable values are strings. Variables persist to .restful/variables.json after the workflow completes.

Using Multiple APIs

@stage("Cross-API operation")
def cross_api(ctx: WorkflowContext):
    # SFM API
    nodes = ctx.clients.sfm.get(Nodes)

    # Netbox API
    devices = ctx.clients.netbox.get(Devices)

Each API configured in the workspace config is available as ctx.clients.<alias>.

Running

# All stages sequentially
python -m restful workflow run my_flow

# Single stage (useful for development)
python -m restful workflow run my_flow --stage "Step 1 — Fetch"

Tips

  • Keep stages focused — one API operation per stage
  • Use descriptive stage names that read as steps in a process
  • Set variables for any data you need across stages
  • Stages run in decorator order, top to bottom