Workflows

Workflows define the approval and authorization processes for Thand Agent role requests. They are built on the Serverless Workflow Specification and provide a declarative way to define complex access control processes with approval chains, notifications, monitoring, and revocation.

Overview

Thand workflows orchestrate the complete lifecycle of access requests:

  1. Validation - Verify request validity and user permissions
  2. Approval - Route requests through approval chains with notifications
  3. Authorization - Grant temporary access to requested resources
  4. Monitoring - Track usage and detect policy violations
  5. Revocation - Remove access when complete or violated

Workflows leverage the Serverless Workflow DSL for standardized process definition while providing custom Thand-specific tasks for access control operations.

Workflow Concepts

What is a Workflow?

A Thand workflow is a serverless workflow specification that defines:

  • Process Flow: Step-by-step access request handling
  • Custom Tasks: Thand-specific operations (validate, approve, authorize, etc.)
  • Integrations: External system interactions (Slack, email, webhooks)
  • Conditions: Dynamic routing based on request properties
  • Events: Lifecycle notifications and monitoring hooks

Workflow vs Role Relationship

Workflows and roles work together:

  • Roles define what access is possible and who can request it
  • Workflows define how access requests are processed and approved
# Role references workflow
roles:
  aws-admin:
    workflows:
      - security-approval  # References workflow name

# Workflow defines the process
workflows:
  security-approval:
    workflow:
      do:
        - validate: { thand: validate }
        - approve: { thand: approvals }
        - grant: { thand: authorize }

Workflow Structure

Basic Configuration

version: "1.0"
workflows:
  workflow-name:
    description: Human readable description
    authentication: provider-name  # Auth provider for this workflow
    enabled: true
    
    workflow:
      document:
        dsl: "1.0.0-alpha5"
        namespace: "thand"
        name: "workflow-name"
        version: "1.0.0"
      
      # Workflow definition using Serverless Workflow DSL
      do:
        - step-name:
            thand: task-name  # Custom Thand task
            # or
            call: external-function  # External API call
            with:
              parameter: value
            then: next-step

Complete Workflow Example

version: "1.0"
workflows:
  manager-approval:
    description: Manager approval workflow with Slack notifications
    authentication: google-oauth
    enabled: true
    
    workflow:
      document:
        dsl: "1.0.0-alpha5"
        namespace: "thand"
        name: "manager-approval"
        version: "1.0.0"
      
      use:
        secrets:
          - slack-credentials
        
      do:
        # Step 1: Validate the request
        - validate:
            thand: validate
            with:
              validator: static  # or 'llm' for AI validation
            then: notify-manager
        
        # Step 2: Send approval request to manager
        - notify-manager:
            thand: approvals
            with:
              approvals: 1
              notifier:
                provider: slack
                to: "#security-team"
                message: >
                  User ${ .user.name } is requesting ${ .role.name } access.
                  Reason: ${ .reason }
            on:
              approved: authorize
              denied: deny-notification
            then: deny-notification
        
        # Step 3: Grant access if approved
        - authorize:
            thand: authorize
            then: monitor
        
        # Step 4: Monitor usage
        - monitor:
            thand: monitor
            with:
              monitor: llm
              threshold: 10
            then: revoke
        
        # Step 5: Revoke access
        - revoke:
            thand: revoke
            with:
              reason: "Session complete"
            then: finished
        
        # Denial path
        - deny-notification:
            call: slack.postMessage
            with:
              provider: slack
              to: "#security-team"
              message: "Access request denied for ${ .user.name }"
            then: end
        
        # Completion notification
        - finished:
            call: slack.postMessage
            with:
              provider: slack
              to: "#security-team"
              message: "Access revoked for ${ .user.name }"
            then: end

Serverless Workflow Integration

Thand workflows are built on the Serverless Workflow Specification v1.0.0-alpha5. This provides:

Standard DSL Features

  • Flow Control: Sequential, parallel, and conditional execution
  • Event Handling: CloudEvents integration for external triggers
  • Error Handling: Try-catch patterns and retry logic
  • Data Manipulation: JSONPath and expression evaluation
  • External Integrations: HTTP, gRPC, OpenAPI, and AsyncAPI calls

Key DSL Components

Component Purpose Example
do Sequential task execution do: [validate, approve, authorize]
call External API/function calls call: slack.postMessage
for Iteration over collections for: { each: .approvers, do: notify }
fork Parallel execution fork: { parallel: [notify-slack, notify-email] }
switch Conditional branching switch: [{ when: .approved, then: grant }]
try Error handling try: authorize, catch: rollback

External Documentation

For complete DSL reference, see:

Custom Thand Tasks

Thand provides custom workflow tasks for access control operations. These tasks are invoked using the thand: keyword:

do:
  - step-name:
      thand: task-name
      with:
        parameter: value

Available Thand Tasks

Task Purpose Documentation
validate Validate access requests Tasks Documentation
approvals Handle approval workflows Tasks Documentation
authorize Grant temporary access Tasks Documentation
monitor Monitor access usage Tasks Documentation
revoke Remove granted access Tasks Documentation
notify Send notifications Tasks Documentation

For detailed documentation of each task, see the Tasks Reference.

Configuration Management

File Structure

Workflows can be organized multiple ways:

Single File

# workflows.yaml
version: "1.0"
workflows:
  approval1: { ... }
  approval2: { ... }

Multiple Files by Purpose

config/workflows/
├── approval.yaml      # Approval workflows
├── emergency.yaml     # Emergency/break-glass workflows
├── automated.yaml     # Automated workflows
└── monitoring.yaml    # Monitoring workflows

Multiple Files by Environment

config/workflows/
├── dev.yaml
├── staging.yaml
└── prod.yaml

Loading Configuration

Configure workflow loading in the main config:

# Load from directory
workflows:
  path: "./config/workflows"

# Load from URL
workflows:
  url:
    uri: "https://config.company.com/workflows.yaml"
    headers:
      Authorization: "Bearer YOUR_API_TOKEN"

# Load from Vault
workflows:
  vault: "secret/agent/workflows"

# Inline definitions
workflows:
  simple-approval:
    description: Simple approval
    workflow:
      do:
        - validate: { thand: validate }
        - approve: { thand: approvals }

Workflow Patterns

Basic Approval Pattern

workflows:
  basic-approval:
    workflow:
      do:
        - validate: { thand: validate, then: approve }
        - approve: { thand: approvals, then: authorize }
        - authorize: { thand: authorize, then: end }

Multi-Step Approval

workflows:
  multi-approval:
    workflow:
      do:
        - validate: { thand: validate, then: manager-approval }
        - manager-approval:
            thand: approvals
            with:
              approvals: 1
              notifier: { provider: email, to: "manager@company.com" }
            on:
              approved: security-approval
              denied: denied
        - security-approval:
            thand: approvals
            with:
              approvals: 1
              notifier: { provider: slack, to: "#security" }
            on:
              approved: authorize
              denied: denied
        - authorize: { thand: authorize, then: end }
        - denied: { call: notify-denial, then: end }

Time-Based Approval

workflows:
  time-limited:
    workflow:
      schedule:
        after: "PT2H"  # ISO 8601 duration (2 hours)
      do:
        - validate: { thand: validate, then: authorize }
        - authorize: { thand: authorize, then: scheduled-revoke }
        - scheduled-revoke:
            wait:
              duration: "PT2H"
            then: revoke
        - revoke: { thand: revoke, then: end }

Emergency/Break-Glass Workflow

workflows:
  emergency-access:
    workflow:
      do:
        - validate: { thand: validate, then: immediate-grant }
        - immediate-grant: { thand: authorize, then: alert-security }
        - alert-security:
            fork:
              parallel:
                - slack-alert: { call: slack.postMessage }
                - email-alert: { call: email.send }
                - webhook-alert: { call: security.webhook }
            then: enhanced-monitoring
        - enhanced-monitoring:
            thand: monitor
            with:
              monitor: llm
              threshold: 5  # Lower threshold for emergency access
            then: auto-revoke
        - auto-revoke: { thand: revoke, then: end }

Conditional Workflows

workflows:
  conditional-approval:
    workflow:
      do:
        - validate: { thand: validate, then: route-request }
        - route-request:
            switch:
              - when: '${ .role.name == "admin" }'
                then: security-approval
              - when: '${ .duration > "PT4H" }'
                then: manager-approval
              - when: '${ .user.department == "security" }'
                then: auto-approve
            default: standard-approval
        
        - security-approval: { thand: approvals, then: authorize }
        - manager-approval: { thand: approvals, then: authorize }
        - auto-approve: { thand: authorize, then: end }
        - standard-approval: { thand: approvals, then: authorize }
        - authorize: { thand: authorize, then: end }

Integration Examples

Slack Integration

workflows:
  slack-workflow:
    workflow:
      use:
        secrets: [slack-credentials]
      do:
        - notify:
            call: slack.postMessage
            with:
              provider: slack
              channel: "#approvals"
              message: |
                :warning: Access Request
                User: ${ .user.name }
                Role: ${ .role.name }
                Reason: ${ .reason }
              blocks:
                - type: section
                  text: "New access request requires approval"
                - type: actions
                  elements:
                    - type: button
                      text: "Approve"
                      action_id: "approve_request"
                    - type: button
                      text: "Deny"
                      action_id: "deny_request"

Email Integration

workflows:
  email-workflow:
    workflow:
      do:
        - notify:
            call: email.send
            with:
              provider: email
              to: ["manager@company.com", "security@company.com"]
              subject: "Access Request: ${ .role.name }"
              template: "access-request"
              data:
                user: ${ .user }
                role: ${ .role }
                reason: ${ .reason }

Webhook Integration

workflows:
  webhook-workflow:
    workflow:
      do:
        - external-approval:
            call: http
            with:
              method: POST
              url: "https://approval.company.com/api/requests"
              headers:
                Authorization: "Bearer YOUR_API_TOKEN"
                Content-Type: "application/json"
              body:
                user: ${ .user.email }
                role: ${ .role.name }
                duration: ${ .duration }
                reason: ${ .reason }

Security Considerations

Authentication

Workflows can specify required authentication:

workflows:
  secure-workflow:
    authentication: saml-sso  # Require SAML authentication
    workflow:
      # ... workflow definition

Secrets Management

Use secrets for sensitive data:

workflows:
  workflow-with-secrets:
    workflow:
      use:
        secrets:
          - api-keys
          - database-credentials
      do:
        - api-call:
            call: http
            with:
              headers:
                Authorization: "Bearer ${ $api-keys.token }"

Input Validation

Always validate inputs in workflows:

workflows:
  validated-workflow:
    workflow:
      do:
        - validate:
            thand: validate
            with:
              validator: static  # or 'llm'
              rules:
                - max_duration: "PT8H"
                - allowed_roles: ["developer", "admin"]

Troubleshooting

Common Issues

1. Workflow Not Found

Error: workflow 'approval' not found

Solution: Verify workflow name matches role configuration and workflow definition.

2. Task Execution Failed

Error: thand task 'validate' failed: invalid request

Solution: Check task parameters and input data format.

3. External Call Failed

Error: call to 'slack.postMessage' failed: unauthorized

Solution: Verify API credentials and permissions.

4. Workflow Timeout

Error: workflow execution timed out

Solution: Check for infinite loops and add appropriate timeouts.

Debugging Workflows

Enable workflow debugging:

logging:
  level: debug
  workflows:
    trace: true

Use workflow testing:

# Test workflow execution
agent workflow test --workflow approval --input request.json

# Validate workflow syntax
agent workflow validate --file workflows.yaml

Best Practices

1. Workflow Design

Keep Workflows Simple

# Good - clear, linear flow
do:
  - validate: { thand: validate }
  - approve: { thand: approvals }
  - authorize: { thand: authorize }

# Avoid - overly complex branching

Use Meaningful Names

# Good - descriptive step names
- manager-approval: { thand: approvals }
- security-review: { thand: approvals }

# Avoid - unclear names
- step1: { thand: approvals }
- approval: { thand: approvals }

2. Error Handling

Implement Proper Error Handling

workflows:
  robust-workflow:
    workflow:
      do:
        - validate:
            try:
              thand: validate
            catch:
              - log-error: { call: logger.error }
              - notify-admin: { call: slack.postMessage }
              - fail: { raise: { error: validation-failed } }

3. Performance

Optimize Approval Flows

# Use parallel notifications when possible
- notify-approvers:
    fork:
      parallel:
        - slack-notify: { call: slack.postMessage }
        - email-notify: { call: email.send }

4. Security

Principle of Least Privilege

workflows:
  secure-workflow:
    authentication: multi-factor  # Require strong auth
    workflow:
      do:
        - validate:
            thand: validate
            with:
              validator: llm  # Use AI for enhanced validation
              strict_mode: true

Examples

For complete workflow examples and templates, see the Workflow Examples page which includes:

  • Basic Approval Workflow - Simple manager approval
  • Multi-Stage Approval - Complex approval chains
  • Emergency Access Workflow - Break-glass patterns
  • Automated Workflows - AI-driven approvals
  • Integration Examples - Slack, email, and webhook workflows
  • Conditional Workflows - Dynamic routing based on request properties
  • Time-Based Workflows - Scheduled and time-limited access

Each example includes complete YAML configurations with detailed explanations.


Table of contents