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 objectsExample:
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 → Completeconst 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
└── ErrorAnalysisWorkflow 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:
- Combining Activities - Multiple activities into end-to-end processes
- Managing Flow - Sequential, parallel, conditional, loop patterns
- Coordinating Actors - Both agents and humans working together
- Maintaining State - Persistent context across long-running processes
- 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.