4. Workflow definitions
Structure
{
"name": "engagement_approval",
"version": 3,
"inputParameters": ["engagement_id"],
"tasks": [
{ "taskReferenceName": "load", "type": "CALL_TOOL",
"inputParameters": { "tool": "engagements.get_engagement",
"arguments": { "id": "${workflow.input.engagement_id}" } } },
{ "taskReferenceName": "review", "type": "LLM_CHAT",
"inputParameters": { "instructions": "${instructions.engagement_review@2}",
"context": "${load.output}" } },
{ "taskReferenceName": "notify", "type": "HTTP",
"inputParameters": { "uri": "${workflow.env.teams_bridge}/card",
"body": { "summary": "${review.output.text}", "run": "${workflow.id}" } } },
{ "taskReferenceName": "gate", "type": "HUMAN" },
{ "taskReferenceName": "commit", "type": "SWITCH", "on": "${gate.output.decision}",
"cases": {
"approve": [ { "taskReferenceName": "approve", "type": "CALL_TOOL",
"inputParameters": { "tool": "engagements.approve_engagement",
"arguments": { "id": "${workflow.input.engagement_id}" } } } ],
"flag": [ { "taskReferenceName": "flag", "type": "CALL_TOOL",
"inputParameters": { "tool": "engagements.flag_engagement",
"arguments": { "id": "${workflow.input.engagement_id}",
"reason": "${gate.output.reason}" } } } ] } }
],
"outputParameters": { "decision": "${gate.output.decision}" },
"timeoutSeconds": 604800,
"failureWorkflow": "ops_escalation"
}
This is the workflow from page 3. The engine treats every domain the same; only the tool names differ.
Top-level fields
| Field | Meaning |
|---|---|
name | Identifier. Runs are started by this name. |
version | Whole number. A registered version never changes; a change is a new version. |
inputParameters | Names of the inputs a start request must supply. |
inputTemplate | Default input values, merged under the start request's input. |
inputSchema, outputSchema, enforceSchema | JSON Schema for input and output. When enforceSchema is true, mismatches reject the start or fail the run. |
tasks | The steps, in order. See below. |
outputParameters | What the run returns, built from task outputs. |
variables | Initial values for run variables, changed later by SET_VARIABLE tasks. |
timeoutSeconds, timeoutPolicy | Limit for the whole run. Policy TIME_OUT_WF fails the run; ALERT_ONLY records a metric. |
failureWorkflow, failureWorkflowVersion | A workflow to start when this one fails, times out, or is terminated. |
restartable | When false, the run cannot be restarted or rerun. Default true. |
statusListenerEnabled | When true, the engine publishes a status event on every change. See page 11. |
maskedFields | Paths in inputs and outputs to redact before writing history. |
rateLimitConfig | Maximum concurrent runs per key. |
owner | The team responsible. |
Task fields
Every task has:
| Field | Meaning |
|---|---|
taskReferenceName | Unique name within the definition. Other tasks refer to its output by this name. |
type | One of the task types on page 5. |
inputParameters | The task's input, built from references. |
name | For worker tasks: the task type name whose settings apply. |
optional | When true, a failure of this task does not fail the run. |
autonomy | When true, a write-tier tool call may run without a preceding human gate. Requires owner rights. |
cacheConfig | {key, ttlInSecond}: reuse a previous output for the same key. |
Type-specific fields: on and cases for SWITCH; forkTasks for FORK_JOIN; loopCondition and loopOver for DO_WHILE; subWorkflowParam for SUB_WORKFLOW; duration or until for WAIT.
References
A reference is a string of the form ${...}. The engine replaces it with the value before running the task.
| Reference | Value |
|---|---|
${workflow.input.x} | Field x of the start input |
${taskRef.output.y} | Field y of the output of task taskRef |
${workflow.variables.z} | Run variable z |
${workflow.id} | The run id |
${workflow.env.NAME} | A configuration value from App Configuration |
${workflow.secrets.NAME} | A secret from Key Vault, resolved at the moment of use and never written to history |
${instructions.name@version} | An instruction text from the instruction registry |
References follow dotted paths only. SWITCH and DO_WHILE conditions support equality and presence checks only. There is no expression language.
Task definitions
Timeouts, retries, and limits apply to a task type everywhere it is used. They are stored once, as a task definition, not in each workflow. See page 9 for the fields. Every worker task type must have one.
Registration checks
Registration is POST /api/metadata/workflow. The engine rejects the definition when any check fails:
- Task reference names are unique.
- Every reference
${ref.output...}names a task that runs earlier on every path. - Every worker task type has a task definition.
- Every tool name and agent name exists on the gateway for the workflow's trust tier.
- Every
CALL_TOOLnaming a write-tier or high-risk tool is preceded on every path by aHUMANtask, unless the task setsautonomy: trueand the owner has that right.
A rejected definition returns the list of failed checks.
Source control and registration
Each definition is a file in the workflows repository. On every change, the pipeline validates all definitions, registers changed ones, and updates the gateway's permission policy from the tools they name. Page 17 describes the pipeline.