mdxui

Workflows

Service delivery workflows and activity orchestration

Workflows

Workflows orchestrate multiple activities into end-to-end service delivery processes.


From Activities to Workflows

Individual activities combine into workflows:

Activity: Single action on single object
  ↓
Workflow: Sequence of activities across objects

Example:

Activity: invoice.approv.ing.as
└── Approve a single invoice

Workflow: InvoiceProcessing
├── invoice.receiv.ing.as (receive invoice)
├── invoice.verif.ing.as (verify details)
├── invoice.approv.ing.as (approve payment)
├── payment.schedul.ing.as (schedule payment)
└── vendor.notif.ing.as (notify vendor)

Workflow Structure

Definition

interface Workflow {
  $type: 'Workflow'
  $id: string
  name: string

  // Trigger
  trigger: WorkflowTrigger

  // Steps
  steps: WorkflowStep[]

  // Actors
  actors: Record<string, Worker>

  // Context
  context: string
  variables: Record<string, any>
}

Triggers

Workflows start from events:

type WorkflowTrigger =
  | EventTrigger      // When event occurs
  | ScheduleTrigger   // On schedule
  | ManualTrigger     // Human initiates
  | WebhookTrigger    // External system calls

interface EventTrigger {
  type: 'event'
  event: string           // Event type
  filter?: EventFilter    // Optional conditions
}

// Example: Start workflow when invoice approved
const trigger: EventTrigger = {
  type: 'event',
  event: 'InvoiceApproved',
  filter: {
    amount: { gte: 10000 }  // Only large invoices
  }
}

Steps

Workflows execute as sequences of steps:

interface WorkflowStep {
  name: string
  activity: string        // Which activity to perform
  actor: string          // Which worker performs it
  input: StepInput       // Where data comes from
  output?: string        // Where to store result
  condition?: Condition  // When to execute
  onError?: ErrorHandler // What to do if fails
}

const steps: WorkflowStep[] = [
  {
    name: 'verify-invoice',
    activity: 'invoice.verif.ing.as',
    actor: 'agent.accounting',
    input: { invoice: '$.trigger.invoice' },
    output: 'verification'
  },
  {
    name: 'approve-invoice',
    activity: 'invoice.approv.ing.as',
    actor: 'human.manager',
    input: {
      invoice: '$.trigger.invoice',
      verification: '$.verification'
    },
    condition: {
      field: '$.verification.valid',
      equals: true
    },
    output: 'approval'
  },
  {
    name: 'schedule-payment',
    activity: 'payment.schedul.ing.as',
    actor: 'agent.payments',
    input: {
      invoice: '$.trigger.invoice',
      approval: '$.approval'
    },
    onError: {
      retry: 3,
      escalate: 'human.accountant'
    }
  }
]

Workflow Patterns

Sequential Workflow

Steps execute one after another:

Step 1 → Step 2 → Step 3 → Complete
const customerOnboarding: Workflow = {
  $type: 'Workflow',
  $id: 'wf_onboarding',
  name: 'Customer Onboarding',
  trigger: {
    type: 'event',
    event: 'CustomerSignedUp'
  },
  steps: [
    {
      name: 'send-welcome-email',
      activity: 'email.send.ing.as',
      actor: 'agent.marketing',
      input: { customer: '$.trigger.customer' }
    },
    {
      name: 'create-account',
      activity: 'account.creat.ing.as',
      actor: 'agent.systems',
      input: { customer: '$.trigger.customer' }
    },
    {
      name: 'schedule-onboarding-call',
      activity: 'meeting.schedul.ing.as',
      actor: 'agent.success',
      input: {
        customer: '$.trigger.customer',
        account: '$.createAccount.account'
      }
    },
    {
      name: 'assign-success-manager',
      activity: 'manager.assign.ing.as',
      actor: 'human.csm-lead',
      input: { customer: '$.trigger.customer' }
    }
  ],
  actors: {
    'agent.marketing': marketingAgent,
    'agent.systems': systemsAgent,
    'agent.success': successAgent,
    'human.csm-lead': csmLead
  },
  context: 'customer-success'
}

Parallel Workflow

Steps execute concurrently:

        ┌─→ Step 2a ─┐
Step 1 ─┼─→ Step 2b ─┼→ Step 3 → Complete
        └─→ Step 2c ─┘
const contentProduction: Workflow = {
  $type: 'Workflow',
  name: 'Blog Post Production',
  trigger: {
    type: 'event',
    event: 'BlogTopicApproved'
  },
  steps: [
    {
      name: 'research-topic',
      activity: 'topic.research.ing.as',
      actor: 'agent.researcher',
      input: { topic: '$.trigger.topic' },
      output: 'research'
    },
    // Parallel: Create content assets
    {
      name: 'write-article',
      activity: 'article.writ.ing.as',
      actor: 'agent.writer',
      input: { research: '$.research' },
      output: 'article',
      parallel: 'content-creation'
    },
    {
      name: 'generate-images',
      activity: 'image.generat.ing.as',
      actor: 'agent.designer',
      input: { topic: '$.trigger.topic' },
      output: 'images',
      parallel: 'content-creation'
    },
    {
      name: 'create-social-snippets',
      activity: 'social.draft.ing.as',
      actor: 'agent.social',
      input: { research: '$.research' },
      output: 'social',
      parallel: 'content-creation'
    },
    // Join: Combine all assets
    {
      name: 'assemble-post',
      activity: 'post.assembl.ing.as',
      actor: 'agent.editor',
      input: {
        article: '$.article',
        images: '$.images',
        social: '$.social'
      },
      waitFor: 'content-creation',  // Wait for parallel group
      output: 'post'
    },
    {
      name: 'review-post',
      activity: 'post.review.ing.as',
      actor: 'human.editor',
      input: { post: '$.post' }
    }
  ],
  actors: { /* ... */ },
  context: 'content'
}

Conditional Workflow

Steps execute based on conditions:

        ┌─→ Step 2a → Step 3a ─┐
Step 1 ─┤                       ├→ Step 4 → Complete
        └─→ Step 2b → Step 3b ─┘
const ticketResolution: Workflow = {
  $type: 'Workflow',
  name: 'Support Ticket Resolution',
  trigger: {
    type: 'event',
    event: 'TicketCreated'
  },
  steps: [
    {
      name: 'classify-ticket',
      activity: 'ticket.classif.ing.as',
      actor: 'agent.triage',
      input: { ticket: '$.trigger.ticket' },
      output: 'classification'
    },
    // If simple: Agent resolves
    {
      name: 'auto-resolve',
      activity: 'ticket.resolv.ing.as',
      actor: 'agent.support',
      input: {
        ticket: '$.trigger.ticket',
        classification: '$.classification'
      },
      condition: {
        field: '$.classification.complexity',
        equals: 'simple'
      },
      output: 'resolution'
    },
    // If complex: Human resolves
    {
      name: 'assign-to-human',
      activity: 'ticket.assign.ing.as',
      actor: 'agent.triage',
      input: { ticket: '$.trigger.ticket' },
      condition: {
        field: '$.classification.complexity',
        equals: 'complex'
      }
    },
    {
      name: 'human-resolve',
      activity: 'ticket.resolv.ing.as',
      actor: 'human.support',
      input: { ticket: '$.trigger.ticket' },
      condition: {
        field: '$.classification.complexity',
        equals: 'complex'
      },
      output: 'resolution'
    },
    // Always: Send follow-up
    {
      name: 'send-followup',
      activity: 'email.send.ing.as',
      actor: 'agent.support',
      input: {
        ticket: '$.trigger.ticket',
        resolution: '$.resolution'
      }
    }
  ],
  actors: { /* ... */ },
  context: 'support'
}

Loop Workflow

Steps repeat until condition met:

Step 1 → Step 2 → Step 3 → Condition?
           ↑                   │
           └─── If false ──────┘
const designIteration: Workflow = {
  $type: 'Workflow',
  name: 'Logo Design Iteration',
  trigger: {
    type: 'event',
    event: 'LogoProjectStarted'
  },
  steps: [
    {
      name: 'generate-concepts',
      activity: 'logo.design.ing.as',
      actor: 'agent.designer',
      input: { brief: '$.trigger.brief' },
      output: 'concepts'
    },
    {
      name: 'review-concepts',
      activity: 'design.review.ing.as',
      actor: 'human.creative-director',
      input: { concepts: '$.concepts' },
      output: 'feedback'
    },
    {
      name: 'check-approval',
      activity: 'design.approv.ing.as',
      actor: 'human.client',
      input: {
        concepts: '$.concepts',
        feedback: '$.feedback'
      },
      output: 'approval'
    },
    {
      name: 'iterate',
      activity: 'logo.design.ing.as',
      actor: 'agent.designer',
      input: {
        concepts: '$.concepts',
        feedback: '$.feedback'
      },
      output: 'concepts',
      condition: {
        field: '$.approval.approved',
        equals: false
      },
      loop: 'review-concepts',  // Jump back to review step
      maxIterations: 5
    },
    {
      name: 'deliver-assets',
      activity: 'assets.deliver.ing.as',
      actor: 'agent.delivery',
      input: { concepts: '$.concepts' },
      condition: {
        field: '$.approval.approved',
        equals: true
      }
    }
  ],
  actors: { /* ... */ },
  context: 'agency'
}

Workflow Execution

Execution Engine

class WorkflowEngine {
  async execute(workflow: Workflow, triggerData: any): Promise<WorkflowResult> {
    const context = {
      trigger: triggerData,
      variables: workflow.variables
    }

    for (const step of workflow.steps) {
      // Check condition
      if (step.condition && !this.evaluateCondition(step.condition, context)) {
        continue  // Skip this step
      }

      // Wait for parallel group if needed
      if (step.waitFor) {
        await this.waitForParallelGroup(step.waitFor)
      }

      // Get actor
      const actor = workflow.actors[step.actor]

      // Resolve input
      const input = this.resolveInput(step.input, context)

      // Execute activity
      try {
        const result = await actor.do({
          activity: step.activity,
          input
        })

        // Store output
        if (step.output) {
          context[step.output] = result
        }

        // Emit step completed event
        await this.emit({
          $type: 'WorkflowStepCompleted',
          workflow: workflow.$id,
          step: step.name,
          result
        })

      } catch (error) {
        // Handle error
        if (step.onError) {
          await this.handleError(step, error, context)
        } else {
          throw error
        }
      }
    }

    return {
      status: 'completed',
      context
    }
  }
}

State Management

Workflows maintain state across steps:

interface WorkflowState {
  $id: string
  workflow: string
  status: 'running' | 'completed' | 'failed' | 'paused'

  // Current position
  currentStep: number
  completedSteps: string[]

  // Data
  context: Record<string, any>
  trigger: any

  // Timestamps
  startedAt: Date
  updatedAt: Date
  completedAt?: Date

  // Monitoring
  events: WorkflowEvent[]
  errors: WorkflowError[]
}

// Persist state for long-running workflows
await db.workflowStates.save(state)

// Resume workflow
const state = await db.workflowStates.get(workflowId)
await workflowEngine.resume(workflow, state)

Service Workflows

Agency Service Workflow

Complete creative service delivery:

const websiteProject: Workflow = {
  $type: 'Workflow',
  name: 'Website Project Delivery',
  trigger: {
    type: 'event',
    event: 'ProjectStarted'
  },
  steps: [
    // Discovery
    {
      name: 'collect-requirements',
      activity: 'requirements.gather.ing.as',
      actor: 'human.project-manager',
      input: { project: '$.trigger.project' },
      output: 'requirements'
    },
    // Design
    {
      name: 'create-wireframes',
      activity: 'wireframe.creat.ing.as',
      actor: 'agent.designer',
      input: { requirements: '$.requirements' },
      output: 'wireframes'
    },
    {
      name: 'design-mockups',
      activity: 'mockup.design.ing.as',
      actor: 'agent.designer',
      input: { wireframes: '$.wireframes' },
      output: 'mockups'
    },
    {
      name: 'review-design',
      activity: 'design.review.ing.as',
      actor: 'human.client',
      input: { mockups: '$.mockups' },
      output: 'designApproval'
    },
    // Development
    {
      name: 'build-frontend',
      activity: 'frontend.build.ing.as',
      actor: 'agent.frontend',
      input: { mockups: '$.mockups' },
      output: 'frontend',
      parallel: 'development'
    },
    {
      name: 'build-backend',
      activity: 'backend.build.ing.as',
      actor: 'agent.backend',
      input: { requirements: '$.requirements' },
      output: 'backend',
      parallel: 'development'
    },
    {
      name: 'write-content',
      activity: 'content.writ.ing.as',
      actor: 'agent.writer',
      input: { requirements: '$.requirements' },
      output: 'content',
      parallel: 'development'
    },
    // Integration & QA
    {
      name: 'integrate-site',
      activity: 'site.integrat.ing.as',
      actor: 'agent.integrator',
      input: {
        frontend: '$.frontend',
        backend: '$.backend',
        content: '$.content'
      },
      waitFor: 'development',
      output: 'site'
    },
    {
      name: 'test-site',
      activity: 'site.test.ing.as',
      actor: 'agent.qa',
      input: { site: '$.site' },
      output: 'testResults'
    },
    // Launch
    {
      name: 'deploy-site',
      activity: 'site.deploy.ing.as',
      actor: 'agent.devops',
      input: { site: '$.site' },
      condition: {
        field: '$.testResults.passed',
        equals: true
      },
      output: 'deployment'
    },
    {
      name: 'handoff-client',
      activity: 'project.handoff.ing.as',
      actor: 'human.project-manager',
      input: {
        site: '$.site',
        deployment: '$.deployment'
      }
    }
  ],
  actors: {
    'human.project-manager': projectManager,
    'human.client': client,
    'agent.designer': designerAgent,
    'agent.frontend': frontendAgent,
    'agent.backend': backendAgent,
    'agent.writer': writerAgent,
    'agent.integrator': integratorAgent,
    'agent.qa': qaAgent,
    'agent.devops': devopsAgent
  },
  context: 'agency'
}

Support Service Workflow

End-to-end ticket resolution:

const ticketLifecycle: Workflow = {
  $type: 'Workflow',
  name: 'Support Ticket Lifecycle',
  trigger: {
    type: 'event',
    event: 'TicketCreated'
  },
  steps: [
    // Intake
    {
      name: 'acknowledge-ticket',
      activity: 'ticket.acknowledg.ing.as',
      actor: 'agent.support',
      input: { ticket: '$.trigger.ticket' }
    },
    // Triage
    {
      name: 'triage-ticket',
      activity: 'ticket.triag.ing.as',
      actor: 'agent.triage',
      input: { ticket: '$.trigger.ticket' },
      output: 'triage'
    },
    // Resolution attempt
    {
      name: 'attempt-resolution',
      activity: 'ticket.resolv.ing.as',
      actor: 'agent.support',
      input: {
        ticket: '$.trigger.ticket',
        triage: '$.triage'
      },
      output: 'resolution'
    },
    // If unresolved: Escalate
    {
      name: 'escalate-to-specialist',
      activity: 'ticket.escalat.ing.as',
      actor: 'agent.triage',
      input: { ticket: '$.trigger.ticket' },
      condition: {
        field: '$.resolution.resolved',
        equals: false
      }
    },
    {
      name: 'specialist-resolution',
      activity: 'ticket.resolv.ing.as',
      actor: 'human.specialist',
      input: { ticket: '$.trigger.ticket' },
      condition: {
        field: '$.resolution.resolved',
        equals: false
      },
      output: 'resolution'
    },
    // Closure
    {
      name: 'send-resolution',
      activity: 'response.send.ing.as',
      actor: 'agent.support',
      input: {
        ticket: '$.trigger.ticket',
        resolution: '$.resolution'
      }
    },
    {
      name: 'close-ticket',
      activity: 'ticket.clos.ing.as',
      actor: 'agent.support',
      input: {
        ticket: '$.trigger.ticket',
        resolution: '$.resolution'
      }
    },
    // Follow-up
    {
      name: 'send-satisfaction-survey',
      activity: 'survey.send.ing.as',
      actor: 'agent.support',
      input: { ticket: '$.trigger.ticket' }
    }
  ],
  actors: { /* ... */ },
  context: 'support'
}

Workflow Management

Via Management.Studio

Management.Studio
├── WorkflowsPanel
│   ├── ActiveWorkflows (running now)
│   ├── CompletedWorkflows (history)
│   ├── FailedWorkflows (errors)
│   └── ScheduledWorkflows (upcoming)
│
├── DesignerPanel
│   ├── CreateWorkflow
│   ├── EditSteps
│   ├── ConfigureActors
│   └── TestWorkflow
│
└── MonitoringPanel
    ├── ExecutionTimeline
    ├── StepDurations
    ├── BottleneckAnalysis
    └── ErrorAnalysis

Workflow Monitoring

interface WorkflowMetrics {
  // Execution
  totalExecutions: number
  averageDuration: number
  completionRate: number
  failureRate: number

  // Steps
  stepDurations: Record<string, number>
  stepFailures: Record<string, number>
  bottlenecks: string[]  // Slowest steps

  // Actors
  actorUtilization: Record<string, number>
  actorErrors: Record<string, number>

  // Trends
  volumeOverTime: TimeSeries
  durationOverTime: TimeSeries
}

// Monitor in real-time
const metrics = await workflowEngine.getMetrics('wf_onboarding')

Summary

Workflows orchestrate service delivery by:

  1. Combining Activities - Multiple activities into end-to-end processes
  2. Managing Flow - Sequential, parallel, conditional, loop patterns
  3. Coordinating Actors - Both agents and humans working together
  4. Maintaining State - Persistent context across long-running processes
  5. Handling Errors - Retry, escalation, recovery strategies

The paradigm: Services are delivered through workflows that orchestrate activities across agents and humans, transforming traditional service delivery into automated software processes.

On this page