Decisions
The decide step evaluates conditions and routes execution accordingly. Use it when your machine needs to take different paths based on data. Each branch decision is recorded in the behavioral ledger, making your control flow auditable after the fact.
Basic syntax
decide <name> when <condition> <expression or steps> when <condition> <expression or steps> otherwise <expression or steps>Conditions are evaluated top to bottom. The first when that matches executes. If nothing matches, otherwise runs. If there is no otherwise and nothing matches, the step returns null.
Simple branching
machine ticket_router
accepts priority as text, is required
responds with queue as text sla_hours as number
implements decide route when input.priority == "urgent" {queue: "critical", sla_hours: 1} when input.priority == "high" {queue: "priority", sla_hours: 4} when input.priority == "medium" {queue: "standard", sla_hours: 24} otherwise {queue: "backlog", sla_hours: 72}Natural language conditions
decide supports both symbolic and natural-language operators. These are equivalent:
// Symbolicwhen input.amount > 10000when steps.score.value != "pass"when input.count >= 5 && input.active
// Natural languagewhen input.amount is greater than 10000when steps.score.value is not "pass"when input.count is at least 5 and input.active| Symbolic | Natural language |
|---|---|
== | is |
!= | is not |
> | is greater than |
< | is less than |
>= | is at least |
<= | is at most |
&& | and |
|| | or |
Branching on step results
The most common pattern: use the output of an ask step to decide what happens next.
machine approval_workflow
accepts amount as number, is required department as text, is required
responds with approved as boolean approver as text
ensures permissions allowed to llm_call
implements ask evaluate, using: "anthropic:claude-haiku-4-5" with task "Evaluate this expense. Amount: ${input.amount}, Department: ${input.department}. Return risk level." returns risk_level as text assuming risk_level: "low"
decide route_approval when input.amount is greater than 10000 {approved: false, approver: "CFO review required"} when steps.evaluate.risk_level is "high" {approved: false, approver: "Risk committee"} when input.amount is at most 500 {approved: true, approver: "auto-approved"} otherwise {approved: true, approver: "manager"}Branching to named flows
For branches that need multiple steps, dispatch to a named flow with run flow(name):
machine order_processor
implements compute check_inventory {in_stock: input.quantity <= 100}
decide fulfillment_path when check_inventory.in_stock run flow(ship_direct) otherwise run flow(backorder)
flows flow ship_direct ask create_shipment, from: "@mashin/actions/shipping/create" items: input.items compute result {status: "shipped"}
flow backorder ask notify, from: "@mashin/actions/notifications/send" message: "Backorder needed" compute result {status: "backordered"}decide vs. compute ternary
For simple value selection, a ternary in compute is shorter:
// Simple: use ternarycompute label {tier: input.amount > 1000 ? "premium" : "standard"}
// Complex: use decidedecide route when input.amount > 10000 {tier: "enterprise", handler: "account_manager"} when input.amount > 1000 {tier: "premium", handler: "priority_support"} otherwise {tier: "standard", handler: "general_support"}Use decide when: there are more than two branches, each branch needs multiple fields, or you want branches visible in the ledger trace. Use ternary when: it is a simple two-way value choice on a single field.
Governance
Decide steps are pure control flow. They do not require permissions and do not make external calls. However, every branch decision is recorded in the behavioral ledger with the condition that was evaluated and which branch was taken. This makes control flow auditable.
Steps inside branches inherit normal governance. An ask step inside a when clause still requires llm_call permission.
Try it
Build a machine that takes a customer order with amount, customer_tier, and item_count. Use a decide step to route: VIP customers with large orders get express handling, small orders get auto-processing, and everything else goes to standard review.
Next steps
- Effects - Calling external machines from branches
- Flows - Multi-flow machines in depth
- decide reference - Full specification