Parameters
A template sees content and parameters, nothing else. parameters is an object: pass what the template needs from anywhere in the workflow.
"parameters": {
"environment": "@appsetting('ENVIRONMENT_NAME')",
"region": "@parameters('region')",
"limits": "@parameters('limits')", // an object: parameters.limits.discountPercent
"tenant": "@triggerOutputs()?['headers']?['x-tenant']",
"mode": "@triggerOutputs()?['queries']?['mode']",
"receivedAt": "@utcNow()"
}Objects stay objects and arrays stay lists. Don't pass secrets this way: action inputs are kept in the run history.
Workflow variables
Variables of every type map straight onto parameters and keep their type in the template:
| Variable type | In the template |
|---|---|
| string | {{ parameters.currency }} |
| integer | {% for line in content.lines limit: parameters.maxLines %} |
| float | subtotal | Times: parameters.taxRate | Round: 2 |
| boolean | {% if parameters.expedite %} |
| array | a list: Join, Size, First, for |
| object | parameters.shipTo.city |
"Initialize_the_quote_settings": {
"type": "InitializeVariable",
"inputs": { "variables": [
{ "name": "currency", "type": "string", "value": "@{toUpper(coalesce(triggerOutputs()?['queries']?['currency'], 'CAD'))}" },
{ "name": "maxLines", "type": "integer", "value": "@int(coalesce(triggerOutputs()?['queries']?['maxLines'], '10'))" },
{ "name": "taxRate", "type": "float", "value": "@float(coalesce(triggerOutputs()?['queries']?['taxRate'], '0.15'))" },
{ "name": "expedite", "type": "boolean", "value": "@equals(triggerOutputs()?['headers']?['x-expedite'], 'true')" },
{ "name": "excludedSkus", "type": "array", "value": "@split(triggerOutputs()?['queries']?['exclude'], ',')" },
{ "name": "shipTo", "type": "object", "value": "@triggerBody()?['shipTo']" }
] }
},
"Quote_the_order": {
"type": "ServiceProvider",
"inputs": {
"parameters": {
"inputFormat": "json", "outputFormat": "json", "content": "@triggerBody()",
"templateSource": "deployed", "templateName": "quote.liquid",
"parameters": {
"currency": "@variables('currency')", // {{ parameters.currency }}
"maxLines": "@variables('maxLines')", // {% for line in content.lines limit: parameters.maxLines %}
"taxRate": "@variables('taxRate')", // subtotal | Times: parameters.taxRate
"expedite": "@variables('expedite')", // {% if parameters.expedite %}
"excludedSkus": "@variables('excludedSkus')", // a list
"shipTo": "@variables('shipTo')" // parameters.shipTo.city
}
},
…
}
},
"Set_total": {
"type": "SetVariable",
"inputs": { "name": "total", "value": "@body('Quote_the_order')?['result']?['total']" } // a number, not text
}Results back into variables
- Typed values: in JSON mode,
resultfields are numbers, Booleans, arrays and objects, so Set variable, Increment and Append to array take them directly. - Route on an answer: a text template can return one word (
auto,review,reject) that a Switch acts on. Trim it withtrim()in case of a stray line break. - Pick the template at run time:
templateNameandoutputFormataccept expressions, such as@variables('templateName').
Loops
Transform each item of a batch, collect the results in variables, then render the collected array:
"For_each_order": {
"type": "Foreach",
"foreach": "@triggerBody()?['orders']",
"runtimeConfiguration": { "concurrency": { "repetitions": 1 } },
"actions": {
"Summarize_the_order": { … "content": "@items('For_each_order')",
"parameters": { "position": "@add(variables('orderCount'), 1)" } … },
"Append_to_summaries": { "type": "AppendToArrayVariable",
"inputs": { "name": "summaries", "value": "@body('Summarize_the_order')?['result']" } },
"Increment_batchTotal": { "type": "IncrementVariable",
"inputs": { "name": "batchTotal", "value": "@body('Summarize_the_order')?['result']?['total']" } }
}
},
"Write_the_report": { … "content": "@variables('summaries')", "outputFormat": "text" … }Keep the loop sequential when its iterations change the same variables. Sample 08 runs all of this.