Unpredictable Process Patterns
Design workflows for business processes where the sequence of steps cannot be known at design time.
Sequential graphs — where you draw every step and decision in the canvas — work well for repeatable, predictable processes. But many real business processes are unpredictable: the number of steps varies per case, external events can change the path mid-flight, and a rigid graph would need to be redesigned every time business rules change.
This page covers five patterns for handling unpredictable processes, with concrete canvas designs for each.
The Core Shift
Sequential (predictable):
You design the path → the engine follows it
Event-driven autonomous (unpredictable):
You design the goal + available actions → the agent decides the path at runtime
The less predictable the process, the simpler the graph and the richer the system prompt.
Choosing a pattern
| Question | Answer → Pattern |
|---|---|
| Can I list all possible paths at design time? | Yes → Classify + Branch |
| Steps vary per case; process is single-domain | → Single Autonomous Agent |
| Multiple departments must act independently | → Event-Reactive Chain |
| Need multiple specialist teams + coordination | → Supervisor + Specialists |
| Humans review; number of rounds is unknown | → Human-in-Loop with Re-entry |
Pattern 1 — Single Autonomous Agent
Best for: single-domain processes where the agent decides what to do based on what it finds.
Canvas:
[start] → [agent: Process Handler] → [end]
The entire process logic lives in the system prompt. The agent runs multiple tool-call rounds internally until it determines the process is complete.
System prompt structure:
You are handling: {input}
Goal: <one clear outcome statement>
Available actions (use the tools):
- api_caller: check order/account/case details
- emit_event: signal what happened
- email_draft: compose responses
- trigger_workflow: hand off to a specialist if out of scope
Process:
1. Gather all relevant context using your tools
2. Make a decision
3. Act on the decision
4. Emit exactly ONE terminal event indicating the outcome
Do not ask for more information — use your tools to find it.
When to use:
- Customer support triage and resolution
- Document processing with variable number of checks
- Data enrichment pipelines
Pattern 2 — Classify + Branch
Best for: processes with known possible outcomes but unknown which applies at trigger time.
Canvas:
[start]
│
▼
[agent: Context Gatherer]
│
▼
[classify: Determine Action]
categories: approve | reject | escalate | request_info
│ │ │ │
▼ ▼ ▼ ▼
[agent [agent [agent [agent
Approve][Reject] Escalate] Request]
│ │ │ │
└───────┴─────────┴─────────────┘
│
▼
[agent: Notify + Log]
│
▼
[end]
The classify node sends the gathered context to an LLM with a list of category labels. The LLM picks one, and the runtime follows the matching edge. You don't decide which branch fires — the LLM does at runtime.
When to use:
- Invoice approval (amount-based routing to different approver tiers)
- Support ticket routing (billing / technical / account / general)
- Contract review (standard / non-standard / requires-legal)
Classify node categories tip: list all branches, including edge cases. The LLM will pick the closest match, so having needs_clarification and out_of_scope as explicit categories prevents bad routing.
Pattern 3 — Supervisor + Specialists
Best for: cross-domain processes requiring different specialist teams, where which teams are needed varies per case.
Canvas:
[start]
│
▼
[agent: Supervisor]
│ (uses trigger_workflow tool to dispatch)
│
├──▶ trigger_workflow("hr-handler") if employee-related
├──▶ trigger_workflow("it-handler") if IT access needed
├──▶ trigger_workflow("legal-review") if contract involved
└──▶ trigger_workflow("finance-approval") if spend over threshold
│
▼
[agent: Consolidator]
│ (collects specialist outputs, writes final summary)
▼
[end]
Supervisor system prompt:
You are coordinating the processing of: {input}
Analyze what is needed and trigger the relevant specialist workflows.
You may trigger multiple workflows. Each runs independently and in parallel.
Available specialists (trigger_workflow tool):
- hr-handler: new employee records, role changes, offboarding
- it-handler: system access, equipment, software licenses
- legal-review: contracts, NDAs, compliance sign-off
- finance-approval: any spend above £5,000
- notify-team: always trigger this last to send the summary
Rules:
- Only trigger specialists that are actually needed for this specific case
- Always trigger notify-team at the end
- If uncertain whether a specialist is needed, trigger them — better too much than missed
When to use:
- New employee onboarding (variable mix of HR/IT/Finance/Legal)
- Vendor onboarding (procurement + legal + IT + security)
- Project kickoff (resource allocation + tooling + compliance + comms)
Pattern 4 — Event-Reactive Chain
Best for: long-running processes where external events arrive asynchronously over hours or days.
Instead of one workflow with a loop, each possible "next step" is a separate short workflow that reacts to the event that just happened. The process lives in the event flow, not in any single workflow.
Design (draw on paper, not as one canvas):
customer_support_ticket_created
│
▼ subscribed workflow
[Triage Agent]
agent decides: can_resolve | needs_info | escalate
│
├──▶ emit: resolution_attempted
│ │
│ ▼ (customer confirms/disputes — arrives hours later)
│ customer_confirmed ──▶ [Close Ticket Workflow]
│ customer_disputed ──▶ [Re-escalate Workflow]
│
├──▶ emit: info_requested
│ │
│ ▼ (customer replies next day)
│ customer_replied ──▶ [Triage Agent] again
│
└──▶ emit: escalation_needed
│
▼
[Specialist Workflow]
Each box is a separate workflow subscribed to its trigger event. The process can run for days because it's not a single long-running workflow — it's a series of short reactive ones. Each workflow does one thing, emits one event, and terminates.
When to use:
- Customer support (variable back-and-forth with customer)
- Contract negotiation (multi-round revision cycles)
- Approval chains where each approver may request changes
Pattern 5 — Human-in-Loop with Re-entry
Best for: review processes where the number of revision cycles is unknown.
Canvas:
[start]
│
▼
[agent: Prepare]
│ (drafts the document/decision/output)
▼
[user_approval: Review]
│ reviewer sees the draft and decides
│
├─ approve ──────────────────────────▶ [agent: Finalize] → [end]
│
└─ reject/request_changes
│
▼
[agent: Revise]
│ (incorporates reviewer feedback from approval_comment)
▼
[classify: Is revision complete?]
│ │
ready not_ready
│ │
▼ ▼
[user_approval] [agent: Flag Issue]
(loops back) (escalates to supervisor)
The user_approval node pauses execution. The reviewer sees agent_output_preview in their Inbox, decides (approve / reject / modify), and adds a comment. The workflow resumes and routes based on the decision.
Reading reviewer feedback in the agent node:
When the workflow resumes, state.approval_decision contains the decision and state.approval_comment contains the reviewer's notes. The Revise agent reads state.approval_comment to understand what needs changing.
When to use:
- Content review (blog posts, documentation, proposals)
- Legal document review with markup cycles
- Budget proposals requiring finance sign-off
System prompt design for unpredictable agents
The quality of the system prompt determines whether the agent handles unpredictability well. Follow this structure:
1. ROLE: Who the agent is and what domain it owns
"You are the HR coordinator responsible for employee lifecycle changes."
2. GOAL: One clear, outcome-focused statement
"Resolve the employee request or escalate it with a documented reason."
3. CONTEXT: What information is available
"The request is in the workflow input as JSON.
Use api_caller to fetch additional employee history if needed."
4. ACTIONS: List every tool with when to use it
"- api_caller: fetch employee record, check leave balance, verify manager
- emit_event: signal outcome (always exactly one terminal event)
- email_draft: compose any notifications
- trigger_workflow: escalate to legal if contract involved"
5. RULES: Constraints and guardrails
"- Never modify payroll data
- Always emit exactly one terminal event per run
- If you cannot determine the correct action, emit: needs_human_review"
6. OUTPUT: What constitutes completion
"Run ends when you have emitted a terminal event."
Anti-patterns to avoid
| Anti-pattern | Problem | Solution |
|---|---|---|
| Long sequential graph for a variable process | Graph must be redesigned when process changes | Use autonomous agent + tools |
while_loop node for iteration | Not yet executed at runtime | Use event-reactive chain (Pattern 4) |
| One giant workflow for all departments | Single point of failure; hard to debug | Supervisor + specialist pattern |
Hardcoded routing in if_else | Breaks when business rules change | Use classify node — LLM decides |
No correlation_id on events | Cannot trace what belongs to which case | Always pass correlation_id through emit_event |
| Agent without tool authority | Agent decides but can't act | Give agent emit_event + api_caller at minimum |
Related
- Event-Driven Workflows — the Event Bus and subscription system
- Saga Orchestration — automatic compensation when steps fail
- Node Types → classify — LLM-based routing
- Node Types → user_approval — human review pause
- Built-in Tools — emit_event, trigger_workflow, api_caller