Zum Inhalt springen
Developer Preview — APIs and language features may change before 1.0

Decisions

Dieser Inhalt ist noch nicht in deiner Sprache verfügbar.

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.

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.

machine ticket_router
accepts
priority as text, is required
responds with
queue as text
sla_hours as number
behaves
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}
verifies
test "urgent goes to the critical queue"
given {priority: "urgent"}
expect {queue: "critical", sla_hours: 1}
test "unknown priority lands in the backlog"
given {priority: "someday"}
expect {queue: "backlog", sla_hours: 72}

decide supports both symbolic and natural-language operators. These are equivalent:

// Symbolic
when input.amount > 10000
when steps.score.value != "pass"
when input.count >= 5 && input.active
// Natural language
when input.amount is greater than 10000
when 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

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
behaves
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
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"}
ensures
permissions
allowed to
model
verifies
test "small low-risk expense auto-approves"
assuming evaluate {risk_level: "low"}
given {amount: 200, department: "engineering"}
expect {approved: true, approver: "auto-approved"}
test "large expense needs the CFO"
assuming evaluate {risk_level: "low"}
given {amount: 50000, department: "engineering"}
expect {approved: false, approver: "CFO review required"}

For branches that need multiple steps, dispatch to a named flow with run flow(name):

machine order_processor
accepts
quantity as number, is required
items as list
responds with
status as text
behaves
compute check_inventory
{in_stock: input.quantity <= 100}
decide fulfillment_path
when check_inventory.in_stock
run ship_direct
otherwise
run backorder
flows
flow ship_direct
ask create_shipment, from: "@mashin/actions/http/post"
url: "https://fulfillment.internal/shipments"
body: {items: input.items}
compute result
{status: "shipped"}
flow backorder
ask notify, from: "@mashin/actions/http/post"
url: "https://fulfillment.internal/backorders"
body: {message: "Backorder needed"}
compute result
{status: "backordered"}
ensures
permissions
allowed to
network.http to "fulfillment.internal"
verifies
test "in-stock orders ship directly"
assuming create_shipment {id: "shp_1"}
given {quantity: 5, items: ["widget"]}
expect {status: "shipped"}

For simple value selection, a ternary in compute is shorter:

// Simple: use ternary
compute label
{tier: input.amount > 1000 ? "premium" : "standard"}
// Complex: use decide
decide 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.

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 model permission.

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.