Workflow orchestration · for whoever designs a process that agents and people share
Every step needs an answer to who owns it when it stalls.
Automating one step is easy. Processes break between steps: an approval nobody picks up, a failed result that moves on as if done, a retry that messages the customer twice. Check your workflow for all three, then copy it as code.
- Includes the rule the engine enforces when you build a workflow
- Gives you the workflow as code
- Free, no sign-up
Find the steps with no owner
An example claims workflow is loaded. Switch the settings on each step and watch the gaps close. Copy the code when it reads zero.
workflow('claim-payout', 'Claim payout')
.step('intake')
.assignment({ tags: ['claims-intake'] })
.targetUser({ tag: 'claims-intake' })
.timeout(600000)
.maxRetries(1)
.route('result.success === false', 'human-fix')
.defaultNext('assess')
.done()
.step('assess')
.assignment({ tags: ['claims-assess'] })
.targetUser({ tag: 'claims-assess' })
.timeout(1800000)
.defaultNext('review')
.done()
.step('review')
.assignment({ tags: ['claims-l2'] })
.targetUser({ tag: 'claims-l2' })
.defaultNext('approve')
.done()
.step('approve')
.assignment({ tags: ['team-lead'] })
.targetUser({ tag: 'team-lead' })
.timeout(28800000)
.defaultNext('notify')
.done()
.step('notify')
.assignment({ tags: ['notify'] })
.targetUser({ tag: 'notify' })
.timeout(300000)
.maxRetries(1)
.route('result.success === false', 'human-fix')
.defaultNext(null)
.done()
.step('human-fix')
.assignment({ tags: ['claims-l2'] })
.targetUser({ tag: 'claims-l2' })
.timeout(14400000)
.defaultNext(null)
.done()
.build();What orchestration adds to automation
Automation runs one step. Orchestration decides what runs next, what happens when a step fails, and who picks it up. These are the five settings above, and what each one prevents.
| Setting | What it prevents | In code |
|---|---|---|
| A deadline on every person’s step | An approval left open for ever, with nobody told | .timeout(ms) |
| Escalation to the next tier | A late step failing the whole run when someone else could answer | .escalateTo(stepId) |
| A branch for a failed agent result | success: false being counted as done | .route('result.success === false', …) |
| A retry only where it is safe | A second message or payment after a slow first one | .maxRetries(n) |
| A qualified person, not a named one | A step waiting on someone who is off today | .targetUser({ tag }) |
When a simpler tool is enough
One step
A scheduled job
Nothing waits on a person, so nothing can stall. Your framework’s retry covers it.
Agents only
Your agent framework
Steps between agents in one process belong there. Bring in routing when a person must take over.
People in the loop
A routed workflow
Each person’s step goes to someone qualified and on shift, with a deadline and a next tier.
Limits worth knowing: escalation cannot start inside a parallel group, the retry count is shared by the whole run, and side effects such as sending an email stay in your code — the workflow decides who acts and when.