Workflows & Recipes

Aexol workflows define state machines with transitions, making it easy to model business processes, application flows, and complex state management.

Basic Syntax

A workflow consists of states and transitions between them:

workflow OrderFlow {
  initial: pending
  pending -> processing
  processing -> shipped
  shipped -> delivered
}
✨ Edit in Studio

Initial State

Use initial to explicitly set the starting state. If omitted, the first state listed becomes the initial state:

workflow TaskFlow {
  initial: todo
  todo -> in_progress
  in_progress -> done
  done -> archived
}
✨ Edit in Studio

Transition Conditions

Add when clauses to make transitions conditional:

workflow OrderFlow {
  initial: pending
  pending -> processing when payment_confirmed
  pending -> cancelled when timeout
  processing -> shipped when items_packed
}
✨ Edit in Studio

Multiple Transitions and Bidirectional Flows

workflow DocumentFlow {
  initial: draft
  draft -> review
  review -> draft              // Can return to draft
  review -> approved
  approved -> published
  published -> archived
  archived -> draft            // Can revive from archive
}
✨ Edit in Studio

Workflows with Types

Combine workflows with type definitions for complete business logic:

enum OrderStatus {
  pending
  processing
  shipped
  delivered
  cancelled
}

type Order {
  id: string
  customerId: string
  status: OrderStatus
  items: OrderItem[]
  total: number
}

workflow OrderFlow {
  initial: pending
  pending -> processing
  pending -> cancelled
  processing -> shipped
  processing -> cancelled
  shipped -> delivered
}
✨ Edit in Studio

Code Generation

Aexol generates type-safe state machine classes from your workflow definitions in TypeScript, Python, Rust, Go, and JavaScript. Each generated class includes:

  • An enum with all states
  • canTransitionTo(state) — check if a transition is valid
  • transitionTo(state) — execute a transition
  • getCurrentState() — read current state
  • Automatic initial state from your initial declaration

Use Studio or the Remote MCP endpoint to generate code from any workflow.


Recipes

Ready-to-use patterns for common scenarios.

Todo App

type Task {
  id: string
  title: string
  description: string
  status: TaskStatus
  assigneeId: string
}

enum TaskStatus {
  todo
  in_progress
  done
}

workflow TaskFlow {
  initial: todo
  todo -> in_progress when started
  in_progress -> done when completed
  in_progress -> todo when reverted
}

visitor TaskManager {
  "create tasks"
  "view tasks"
  "edit tasks"
  "assign tasks"
}
✨ Edit in Studio

E-Commerce Order Flow

type Order {
  id: string
  customerId: string
  items: OrderItem[]
  total: number
  status: OrderStatus
}

enum OrderStatus {
  pending
  payment_received
  processing
  shipped
  delivered
  cancelled
}

workflow OrderProcessing {
  initial: pending
  pending -> payment_received when payment_confirmed
  payment_received -> processing
  processing -> shipped when items_packed
  shipped -> delivered when customer_confirms
  pending -> cancelled when timeout
  payment_received -> cancelled when refund_requested
}
✨ Edit in Studio

Document Approval

type Document {
  id: string
  title: string
  content: string
  authorId: string
  status: DocumentStatus
  reviewers: string[]
}

enum DocumentStatus {
  draft
  pending_review
  approved
  rejected
  published
}

workflow DocumentApproval {
  initial: draft
  draft -> pending_review when submitted
  pending_review -> approved when all_reviewers_approve
  pending_review -> rejected when reviewer_rejects
  rejected -> draft when author_revises
  approved -> published when author_publishes
}
✨ Edit in Studio

Support Ticket System

type Ticket {
  id: string
  customerId: string
  subject: string
  description: string
  priority: Priority
  status: TicketStatus
  assignedTo: string
}

enum Priority { low medium high urgent }

enum TicketStatus {
  open
  assigned
  in_progress
  waiting_customer
  resolved
  closed
}

workflow TicketLifecycle {
  initial: open
  open -> assigned when agent_assigned
  assigned -> in_progress when agent_starts
  in_progress -> waiting_customer when info_needed
  waiting_customer -> in_progress when customer_responds
  in_progress -> resolved when issue_fixed
  resolved -> closed when customer_confirms
  resolved -> in_progress when customer_reopens
}
✨ Edit in Studio

Payment Processing

type Payment {
  id: string
  orderId: string
  amount: number
  currency: string
  status: PaymentStatus
}

enum PaymentStatus {
  pending
  processing
  succeeded
  failed
  refunded
  disputed
}

workflow PaymentFlow {
  initial: pending
  pending -> processing when payment_submitted
  processing -> succeeded when payment_confirmed
  processing -> failed when payment_declined
  failed -> pending when retry_allowed
  succeeded -> refunded when refund_issued
  succeeded -> disputed when customer_disputes
}
✨ Edit in Studio

CI/CD Pipeline

type Build {
  id: string
  commitHash: string
  branch: string
  status: BuildStatus
}

enum BuildStatus {
  queued
  building
  testing
  deploying
  succeeded
  failed
  cancelled
}

workflow CICDPipeline {
  initial: queued
  queued -> building when runner_available
  building -> testing when build_succeeds
  building -> failed when build_fails
  testing -> deploying when tests_pass
  testing -> failed when tests_fail
  deploying -> succeeded when deploy_succeeds
  deploying -> failed when deploy_fails
  queued -> cancelled when user_cancels
}
✨ Edit in Studio

Best Practices

  • Use descriptive state namesawaiting_payment not state1
  • Set initial states explicitly — makes intent clear
  • Model all valid transitions — don't leave implicit gaps
  • Keep workflows focused — split large workflows into smaller ones
  • Align workflows with enums — workflow states should mirror enum values when used together
  • Use agents for automationagent NotificationService { "send email" ... }

See Also