# Workflow XML reference

## Common node attributes

Every node form accepts these attributes. Any node can also be written as `<node id="…" type="…"><config>…</config></node>`, with settings as named `<value>` children using the config names below.

| Attribute | Config name | Required | Type / values | Default | Meaning |
|---|---|---|---|---|---|
| `id` | — | yes | string | — | Unique identifier for the node, used by edges and expressions. |
| `name` | — | no | string | — | Display name. Defaults to the ID; expressions can also use it. |
| `timeoutSeconds` | — | no | number | — | Most time the node may take, in seconds. |
| `maxRetries` | — | no | integer | — | How many times to retry the node if it fails. |
| `continueOnError` | — | no | `true`, `false` | — | When `true`, the run continues after this node fails; later nodes may then lack its output. |
| `x` | — | no | number | — | Position on the editor canvas; give it with `y`. |
| `y` | — | no | number | — | Position on the editor canvas; give it with `x`. |

## Logic

### `<condition>` · Condition

Tests a condition and continues down the `true` or `false` branch. Use it for a simple either/or decision; use `switch` for more than two outcomes.

Node type `condition`.

| Attribute | Config name | Required | Type / values | Default | Meaning |
|---|---|---|---|---|---|
| `test` | `expression` | yes | string | — | The condition to test, for example `input.age >= 18`. |

### `<logic>` · Logic

Combines several conditions into one result with a gate such as `and` or `or`. Use it when a branch depends on more than one test.

Node type `logic`.

| Attribute | Config name | Required | Type / values | Default | Meaning |
|---|---|---|---|---|---|
| `op` | — | yes | `and`, `or`, `not`, `nand`, `nor`, `xor`, `xnor` | — | How to combine the conditions. |
| `<operand>` | `operands` | no | conditions | — | The conditions to combine, in order. |

### `<switch>` · Switch

Chooses one of several branches: the first case whose condition holds wins, with an optional default. Use it for decisions with more than two outcomes.

Node type `switch`.

| Attribute | Config name | Required | Type / values | Default | Meaning |
|---|---|---|---|---|---|
| `default` | — | no | string | — | Branch to take when no case matches. It must match an edge's `when` label. |
| `<case>` | `cases` | no | repeated element | — | The cases to test, in order; the first that matches wins. |

Each `<case>` accepts:

| Attribute | Config name | Required | Type / values | Default | Meaning |
|---|---|---|---|---|---|
| `test` | `expression` | yes | string | — | The condition for this case, for example `input.value > 10`. |
| `name` | — | yes | string | — | The branch to take; it must match an edge's `when` label. |

### `<transform>` · Transform

Builds new values from inputs and earlier results. Use it to reshape data or compute fields before passing them on.

Node type `transform`. Named `<value>` children set `mapping`.

## Control flow

### `<delay>` · Delay

Waits for a set time before continuing. Use it to space out calls to an external service or to wait before checking a result again.

Node type `delay`.

| Attribute | Config name | Required | Type / values | Default | Meaning |
|---|---|---|---|---|---|
| `jitter` | — | no | integer | — | Optional random variation, in seconds, added to or taken from the wait. |
| `seconds` | — | yes | integer or number or string | — | How long to wait, in seconds: a number or a `{{ … }}` expression that gives one. |

### `<for-each>` · For Each

Runs a nested step once for every item in a list, and collects the results. Use it to process each order, row or file in turn.

Node type `for_each`.

| Attribute | Config name | Required | Type / values | Default | Meaning |
|---|---|---|---|---|---|
| `as` | — | no | string | `item` | Name for the current item inside the nested step. |
| `items` | — | yes | array or string | — | The list to go through: a literal list, or a `{{ … }}` expression such as `{{ nodes.list.output.entries }}`. |
| `maxConcurrency` | — | no | integer | `1` | How many items to process at the same time. |
| `<body>` | — | no | one nested node | — | The step to run for each item. |

### `<join>` · Join

Waits for all incoming branches and combines their results into one. Use it after parallel branches whose results you need together.

Node type `join`.

| Attribute | Config name | Required | Type / values | Default | Meaning |
|---|---|---|---|---|---|
| `onPartialFailure` | — | no | `fail`, `skip` | `fail` | What to do if an incoming branch failed but the run continued: `fail` marks the join as failed; `skip` skips it. A branch that was simply not taken does not count as a failure. |
| `strategy` | — | no | `merge`, `array`, `keyed` | — | `merge` combines the results into one object; `array` lists them; `keyed` stores each under its node's ID, or under the names in `<keys>`. |
| `<keys>` | — | no | named `<value>` children | — | Names to use instead of node IDs with the `keyed` strategy. |

### `<merge>` · Merge

Continues as soon as whichever incoming branches ran have finished, and combines their results. Use it after branches where only some will run, such as the two sides of a condition.

Node type `merge`.

| Attribute | Config name | Required | Type / values | Default | Meaning |
|---|---|---|---|---|---|
| `strategy` | — | no | `merge`, `array`, `keyed` | — | `merge` combines the results into one object; `array` lists them; `keyed` stores each under its node's ID. |
| `<keys>` | — | no | named `<value>` children | — | With the `keyed` strategy, names to use instead of node IDs. |

### `<split>` · Split

Starts every outgoing branch at the same time, each with the same input. Use it for independent work that can run in parallel; bring the branches back together with `join`.

Node type `split`.

## State

### `<set-variable>` · Set Variable

Sets workflow variables from literal values or `{{ … }}` expressions. Use it to keep a value that several later steps need.

Node type `set_variable`. Named `<value>` children set `variables`.

## Validation

### `<assert>` · Assert

Checks that a condition holds. By default a failed check stops the run with your message; set `softFail` to continue and report the result instead. Use it to guard against bad data before later steps act on it.

Node type `assert`.

| Attribute | Config name | Required | Type / values | Default | Meaning |
|---|---|---|---|---|---|
| `test` | `condition` | yes | string | — | The condition to check, for example `input.quantity > 0`. |
| `message` | — | no | string | — | Message used when the check fails. Use `{{ … }}` to include inputs, earlier results or variables. |
| `softFail` | — | no | boolean | `false` | When `true`, a failed check does not stop the run; the node outputs `passed: false` instead. |

## Parsing

### `<csv>` · CSV

Turns CSV text into a list of records, or a list of records into CSV text. Use it after reading a CSV file or response, or before writing one.

Node type `csv_parse`. The element's own text or CDATA sets `source`; do not also set it another way.

| Attribute | Config name | Required | Type / values | Default | Meaning |
|---|---|---|---|---|---|
| `delimiter` | — | no | string | `,` | Character that separates columns. |
| `hasHeaders` | — | no | boolean | `true` | Parse mode: the first row holds the column names. |
| `mode` | — | yes | `parse`, `encode` | — | `parse` turns CSV text into records; `encode` turns records into CSV text. |
| `source` | — | no | text or typed value | — | The data to convert, written directly or as a `{{ … }}` expression such as `{{ nodes.read.output.content }}`. |
| `<columns>` | — | no | `<value>` list | — | Column names. When parsing a file without a header row, they name the fields; when encoding, they set the column order. |

### `<json>` · JSON

Turns JSON text into structured data, or structured data into JSON text. Use it to read an API response or a JSON file, or to prepare JSON to send.

Node type `json_parse`. The element's own text or CDATA sets `source`; do not also set it another way.

| Attribute | Config name | Required | Type / values | Default | Meaning |
|---|---|---|---|---|---|
| `mode` | — | yes | `parse`, `encode` | — | `parse` turns JSON text into data; `encode` turns data into JSON text. |
| `pretty` | — | no | boolean | — | Encode mode: format the JSON with line breaks and indentation. |
| `source` | — | no | text or typed value | — | The data to convert, written directly or as a `{{ … }}` expression such as `{{ nodes.read.output.content }}`. |

### `<regex>` · Regex

Matches, extracts, replaces or splits text using a regular expression. Use it to pull a job number out of a file name or to clean up text.

Node type `regex`.

| Attribute | Config name | Required | Type / values | Default | Meaning |
|---|---|---|---|---|---|
| `flags` | — | no | string | — | Options for the pattern; `i` ignores upper and lower case. |
| `input` | — | yes | string | — | The text to work on, written directly or as a `{{ … }}` expression. |
| `mode` | — | no | `match`, `extract`, `replace`, `split` | `match` | What to do with the matches. |
| `<pattern>` | — | no | text | — | The regular expression. |
| `<replacement>` | — | no | text | — | Replace mode: the replacement text. `$1`, `$2` and so on insert captured groups. |

### `<yaml>` · YAML

Turns YAML text into structured data, or structured data into YAML text. Use it to read or write YAML files.

Node type `yaml_parse`. The element's own text or CDATA sets `source`; do not also set it another way.

| Attribute | Config name | Required | Type / values | Default | Meaning |
|---|---|---|---|---|---|
| `mode` | — | yes | `parse`, `encode` | — | `parse` turns YAML text into data; `encode` turns data into YAML text. |
| `source` | — | no | text or typed value | — | The data to convert, written directly or as a `{{ … }}` expression such as `{{ nodes.read.output.content }}`. |

## Data

### `<run-report>` · Run report

Starts a published report and returns its run ID; the report is produced separately. Use it to generate documents or exports as part of a workflow.

Node type `run_report`.

| Attribute | Config name | Required | Type / values | Default | Meaning |
|---|---|---|---|---|---|
| `occurrenceKey` | — | no | string | — | Inside a loop, a value that is unique for each item, so each item gets its own report run. Leave it out for a single run. |
| `versionId` | — | yes | string | — | The published report version to run. |
| `<parameters>` | — | no | named `<value>` children | — | Values for the report's parameters; text values can use `{{ … }}` expressions. |

## Integration

### `<custom-workflow-action>` · Custom Action

Runs one of your installation's custom actions. Use it to reuse a Lua-backed action your team has defined.

Node type `custom_workflow_action`.

| Attribute | Config name | Required | Type / values | Default | Meaning |
|---|---|---|---|---|---|
| `actionId` | — | yes | string | — | The custom action to run. |
| `<action-config>` | `actionConfig` | no | named `<value>` children | — | Settings for the action, as defined by the action. They are passed unchanged, without resolving `{{ … }}` expressions. |

### `<file-check>` · File Check

Checks whether a file exists in a folder. Use it to decide what to do next depending on whether a file has arrived.

Node type `file_check`.

| Attribute | Config name | Required | Type / values | Default | Meaning |
|---|---|---|---|---|---|
| `controllerId` | — | no | string | — | Older workflows only: routes to a controller when no folder is given. Use `folderId` in new workflows. |
| `folderId` | — | no | string | — | Folder ID (a TypeID starting `fld_`), or a `{{ … }}` expression. Leave it out to use your default folder. |
| `path` | — | yes | string | — | Path of the file to check, or a `{{ … }}` expression. Paths are relative to the folder; `..` segments are rejected. |

### `<file-copy>` · File Copy

Copies a file, within a folder or between folders. Use it to archive or hand files on without changing them.

Node type `file_copy`.

| Attribute | Config name | Required | Type / values | Default | Meaning |
|---|---|---|---|---|---|
| `controllerId` | — | no | string | — | Older workflows only: routes to a controller when no folder is given. Use `folderId` in new workflows. |
| `destinationFolderId` | — | no | string | — | Folder to copy to: its ID (a TypeID starting `fld_`) or a `{{ … }}` expression. Leave it out to use your default folder. |
| `destinationKey` | — | yes | string | — | Path to copy to, or a `{{ … }}` expression. An existing file at that path is overwritten. Paths are relative to the folder; `..` segments are rejected. |
| `sourceFolderId` | — | no | string | — | Folder to copy from: its ID (a TypeID starting `fld_`) or a `{{ … }}` expression. Leave it out to use your default folder. |
| `sourceKey` | — | yes | string | — | Path of the file to copy, or a `{{ … }}` expression. Paths are relative to the folder; `..` segments are rejected. |

### `<file-delete>` · File Delete

Deletes a file from a folder. Use it to clean up after processing.

Node type `file_delete`.

| Attribute | Config name | Required | Type / values | Default | Meaning |
|---|---|---|---|---|---|
| `controllerId` | — | no | string | — | Older workflows only: routes to a controller when no folder is given. Use `folderId` in new workflows. |
| `folderId` | — | no | string | — | Folder ID (a TypeID starting `fld_`), or a `{{ … }}` expression. Leave it out to use your default folder. |
| `ignoreNotFound` | — | no | boolean | `false` | When `true`, succeed even if the file does not exist. |
| `path` | — | yes | string | — | Path of the file to delete, or a `{{ … }}` expression. Paths are relative to the folder; `..` segments are rejected. |

### `<file-list>` · File List

Lists the files in a folder. Use it with `for-each` to process every file that has arrived.

Node type `file_list`.

| Attribute | Config name | Required | Type / values | Default | Meaning |
|---|---|---|---|---|---|
| `controllerId` | — | no | string | — | Older workflows only: routes to a controller when no folder is given. Use `folderId` in new workflows. |
| `folderId` | — | no | string | — | Folder ID (a TypeID starting `fld_`), or a `{{ … }}` expression. Leave it out to use your default folder. |
| `path` | — | no | string | — | Optional path prefix to list under, or a `{{ … }}` expression. Leave it out to list the whole folder. Paths are relative to the folder; `..` segments are rejected. |
| `recursive` | — | no | boolean | — | `true` lists every file under the prefix, at any depth; `false` lists only files directly in it. Left out, most folders list everything, while controller folders list one level. |

### `<file-read>` · File Read

Reads a file from a folder. Use it to load a file's content for later steps, such as parsing CSV or JSON.

Node type `file_read`.

| Attribute | Config name | Required | Type / values | Default | Meaning |
|---|---|---|---|---|---|
| `controllerId` | — | no | string | — | Older workflows only: routes to a controller when no folder is given. Use `folderId` in new workflows. |
| `folderId` | — | no | string | — | Folder ID (a TypeID starting `fld_`), or a `{{ … }}` expression. Leave it out to use your default folder. |
| `path` | — | yes | string | — | Path of the file to read, or a `{{ … }}` expression. Paths are relative to the folder; `..` segments are rejected. |

### `<file-wait>` · File Wait

Waits until a file appears in a folder. Use it when a later step depends on a file that another system delivers.

Node type `file_wait`.

| Attribute | Config name | Required | Type / values | Default | Meaning |
|---|---|---|---|---|---|
| `controllerId` | — | no | string | — | Older workflows only: routes to a controller when no folder is given. Use `folderId` in new workflows. |
| `folderId` | — | no | string | — | Folder ID (a TypeID starting `fld_`), or a `{{ … }}` expression. Leave it out to use your default folder. |
| `key` | — | yes | string | — | Exact path of the file to wait for, or a `{{ … }}` expression. Paths are relative to the folder; `..` segments are rejected. |

### `<file-write>` · File Write

Writes content to a file in a folder. Use it to save a result, such as a CSV export or a generated document.

Node type `file_write`. The element's own text or CDATA sets `content`; do not also set it another way.

| Attribute | Config name | Required | Type / values | Default | Meaning |
|---|---|---|---|---|---|
| `controllerId` | — | no | string | — | Older workflows only: routes to a controller when no folder is given. Use `folderId` in new workflows. |
| `folderId` | — | no | string | — | Folder ID (a TypeID starting `fld_`), or a `{{ … }}` expression. Leave it out to use your default folder. |
| `path` | — | yes | string | — | Path of the file to write, or a `{{ … }}` expression. Paths are relative to the folder; `..` segments are rejected. |
| `<content>` | — | no | text | — | What to write, written directly or as a `{{ … }}` expression. |

### `<graphql>` · GraphQL

Runs a query or change against the CoCoCo API. Use it to read or update any record the workflow's identity has access to.

Node type `graphql`. The element's own text or CDATA sets `query`; do not also set it another way.

| Attribute | Config name | Required | Type / values | Default | Meaning |
|---|---|---|---|---|---|
| `operation` | — | yes | `query`, `mutation` | — | `query` to read data, `mutation` to change it. |
| `<document>` | `query` | no | text | — | The GraphQL document to run. |
| `<variables>` | — | no | named `<value>` children | — | Variables for the document: literals or `{{ … }}` expressions such as `{{ input.jobId }}`. |

### `<http-call>` · HTTP Call

Calls an external web address. Use it to reach another system's API; your installation's HTTP access policy decides which addresses are allowed.

Node type `http_call`.

| Attribute | Config name | Required | Type / values | Default | Meaning |
|---|---|---|---|---|---|
| `method` | — | no | `GET`, `POST`, `PUT`, `DELETE`, `PATCH`, `HEAD` | — | HTTP method. |
| `requestTimeoutSeconds` | `timeoutSeconds` | no | integer | `30` | How long to wait for a response, in seconds; at most 120. |
| `url` | — | yes | string | — | The full address to call. Your installation's HTTP access policy must allow it. |
| `<headers>` | — | no | named `<value>` children | — | Request headers. |
| `<body>` | — | no | one typed value | — | Request body, as text. |

### `<http-request>` · HTTP Request

Sends an HTTP request to a connected device. Use it to talk to a device's own web interface.

Node type `http_request`.

| Attribute | Config name | Required | Type / values | Default | Meaning |
|---|---|---|---|---|---|
| `deviceId` | — | yes | string | — | The device to call, or a `{{ … }}` expression. |
| `method` | — | no | `GET`, `POST`, `PUT`, `DELETE`, `PATCH` | — | HTTP method. |
| `path` | — | no | string | — | Path on the device to request. |
| `<headers>` | — | no | named `<value>` children | — | Request headers. |
| `<query>` | — | no | named `<value>` children | — | Query parameters. |
| `<body>` | — | no | one typed value | — | Request body. |

### `<integration-action>` · Integration Action

Runs an action from an installed integration. Use it to work with a connected system, such as sending an order to an accounting package.

Node type `integration_action`.

| Attribute | Config name | Required | Type / values | Default | Meaning |
|---|---|---|---|---|---|
| `actionName` | — | yes | string | — | The integration action to run. |
| `instanceId` | — | yes | string | — | The installed integration to use (a TypeID). |
| `<action-config>` | `actionConfig` | no | named `<value>` children | — | Settings for the action, as the integration defines them. They are passed unchanged, without resolving `{{ … }}` expressions. |

### `<invoke-edge-app>` · Invoke Edge App

Calls a function in an edge app running on one of your controllers. Use it to trigger work on equipment in the building.

Node type `invoke_edge_app`.

| Attribute | Config name | Required | Type / values | Default | Meaning |
|---|---|---|---|---|---|
| `controllerId` | — | yes | string | — | The controller (a TypeID) where the edge app is installed. |
| `edgeAppHandle` | — | yes | string | — | The edge app to call. |
| `function` | — | yes | string | — | The function to call, as the app exports it. |

### `<ml-predict>` · ML Prediction

Gets a prediction from one of your trained models. Use it to estimate a value, such as a job's run time, or to forecast a series.

Node type `ml_predict`.

| Attribute | Config name | Required | Type / values | Default | Meaning |
|---|---|---|---|---|---|
| `confidenceLevel` | — | no | number | — | Forecasts only: confidence level between 0 and 1 for the prediction range. Leave it out to use the model's own setting; without one, forecasts have no upper and lower bounds. |
| `horizon` | — | no | integer | — | Forecasts only: how many steps ahead to forecast. Leave it out to use the model's own setting. |
| `modelName` | — | yes | string | — | The model to use. |
| `<features>` | — | no | named `<value>` children | — | Inputs for a regression or classification model: a literal or a `{{ … }}` expression for each feature. Forecast models ignore it. |

### `<mqtt-publish>` · MQTT Publish

Publishes a message to your MQTT broker, or to one connected device. Use it to signal equipment or other systems that listen for messages.

Node type `mqtt_publish`. The element's own text or CDATA sets `message`; do not also set it another way.

| Attribute | Config name | Required | Type / values | Default | Meaning |
|---|---|---|---|---|---|
| `deviceId` | — | no | string | — | Optional device to send to, or a `{{ … }}` expression. When given, only that device receives the message. |
| `message` | — | yes | string | — | The message to send, written directly or as a `{{ … }}` expression. |
| `rpc` | — | no | boolean | — | When `true`, wait for the device to reply. |
| `topic` | — | yes | string | — | The topic to publish to. |

### `<message>` · Message

Sends a notification to a person or a group. Use it to tell people something happened or that they need to act.

Node type `message`.

| Attribute | Config name | Required | Type / values | Default | Meaning |
|---|---|---|---|---|---|
| `groupId` | — | no | string | — | Notification group to send to; everyone in it receives the message. Use this or `recipientId`. |
| `recipientId` | — | no | string | — | Person to send to. Use this or `groupId`. |
| `subject` | — | yes | string | — | Subject line. Use `{{ … }}` to include inputs, earlier results or variables. |
| `<body>` | — | no | text | — | Message text. Use `{{ … }}` to include inputs, earlier results or variables. |
| `<body-html>` | `bodyHtml` | no | text | — | Optional HTML version of the message. Use `{{ … }}` to include inputs, earlier results or variables. |

### `<microsql>` · MicroSQL

Runs a query against your reporting data and returns the rows. Use it to fetch figures for a later step, such as totals for a notification.

Node type `microsql`. The element's own text or CDATA sets `query`; do not also set it another way.

| Attribute | Config name | Required | Type / values | Default | Meaning |
|---|---|---|---|---|---|
| `maxRows` | — | no | integer | `1000` | Most rows to return; at most 10,000. |
| `query` | — | yes | string | — | The query. Mark parameters as `:name` and give their values in `<bindings>`; `{{ … }}` expressions are also allowed. |
| `<bindings>` | — | no | named `<value>` children | — | Parameter values: each name matches a `:name` in the query, and each value is a literal or a `{{ … }}` expression. |

### `<sql-query>` · SQL Query

Runs a SQL query on a connected device's database and returns the rows. Use it to read data held on equipment.

Node type `sql_query`. The element's own text or CDATA sets `query`; do not also set it another way.

| Attribute | Config name | Required | Type / values | Default | Meaning |
|---|---|---|---|---|---|
| `deviceId` | — | yes | string | — | The device whose database to query, or a `{{ … }}` expression. |
| `query` | — | no | string | — | The SQL query; `{{ … }}` expressions are allowed. Prefer `<bindings>` for values. |
| `<bindings>` | — | no | `<value>` list | — | Values for the query's parameters: literals or `{{ … }}` expressions. |
| `<post-process-script>` | `postProcessScript` | no | text | — | Optional script run on the device to reshape the results; `{{ … }}` expressions are allowed. |

### `<script>` · Script

Runs a Lua script, either saved in your script library or written inline. Use it for logic the other nodes do not cover.

Node type `script`. The element's own text or CDATA sets `inline`; do not also set it another way. `type="lua"` is optional.

| Attribute | Config name | Required | Type / values | Default | Meaning |
|---|---|---|---|---|---|
| `scriptId` | — | no | string | — | Script to run from your library, by ID (a TypeID). |
| `scriptName` | — | no | string | — | Script to run from your library, by name. |
| `scriptTimeoutMs` | `timeout` | no | integer | — | Most time the script may take, in milliseconds. Defaults to your installation's script time limit. |
| `type` | — | no | `lua` | — | Language supported by the engine's script node. |
| `<code>` | `inline` | no | text | — | Lua source to run, instead of a library script. |

### `<task>` · Task

Creates a task for a person or team and waits until it is resolved. Use it when a step needs a human decision or action.

Node type `task`.

| Attribute | Config name | Required | Type / values | Default | Meaning |
|---|---|---|---|---|---|
| `assignedTeamId` | — | no | string | — | Team to assign the task to. |
| `priority` | — | no | string | — | Task priority. |
| `taskDefinitionId` | — | yes | string | — | The task definition to create the task from. |
| `title` | — | no | string | — | Task title, instead of the definition's name. Use `{{ … }}` to include inputs, earlier results or variables. |
| `<description>` | — | no | text | — | Task description, instead of the definition's. Use `{{ … }}` to include inputs, earlier results or variables. |

## AI

### `<agent>` · Agent

Sends a prompt to an AI agent and returns its reply. Use it for free-form work such as summarising, classifying or drafting text from earlier steps.

Node type `agent`. The element's own text or CDATA sets `prompt`; do not also set it another way.

| Attribute | Config name | Required | Type / values | Default | Meaning |
|---|---|---|---|---|---|
| `agentId` | — | yes | string | — | The AI agent to use. |
| `prompt` | — | yes | string | — | What to ask the agent. Use `{{ … }}` to include inputs, earlier results or variables. |
| `responseVariable` | — | no | string | — | Optional workflow variable that also receives the agent's reply. |
| `<context>` | `contextPaths` | no | `<value>` list | — | Extra context for the agent: each `{{ … }}` expression, such as `{{ nodes.load.output }}`, is resolved and added to the prompt. |

### `<agent-task>` · Agent Task

Lets an AI agent resolve a task by choosing one of the task's outcomes. Use it to automate a decision that would otherwise go to a person, optionally falling back to one.

Node type `agent_task`. The element's own text or CDATA sets `prompt`; do not also set it another way.

| Attribute | Config name | Required | Type / values | Default | Meaning |
|---|---|---|---|---|---|
| `agentId` | — | yes | string | — | The AI agent that decides the outcome. |
| `fallbackToHuman` | — | no | boolean | — | If the agent cannot resolve the task, create a task for a person instead and wait for them. |
| `prompt` | — | no | string | — | Extra instructions for the agent. Use `{{ … }}` to include inputs, earlier results or variables. |
| `taskDefinitionId` | — | yes | string | — | The task definition whose outcomes the agent chooses from. |
| `<context>` | `contextPaths` | no | `<value>` list | — | Extra context for the agent: each `{{ … }}` expression is resolved and added to the prompt. |

## Production

### `<producibility-audit>` · Producibility Audit

Checks whether a job can be produced as planned, flagging time overruns, waste and low yield. Use it to catch problems before or during production.

Node type `producibility_audit`.

| Attribute | Config name | Required | Type / values | Default | Meaning |
|---|---|---|---|---|---|
| `durationCriticalFactor` | — | no | number | `1.5` | Run-time overrun that counts as critical: 1.5 means 50% over plan. |
| `durationWarningFactor` | — | no | number | `1.2` | Run-time overrun that counts as a warning: 1.2 means 20% over plan. |
| `jobId` | — | yes | string | — | The job to check, as a TypeID or a `{{ … }}` expression such as `{{ input.jobId }}`. |
| `wasteCriticalRatio` | — | no | number | `0.1` | Waste share that counts as critical: 0.10 means 10%. |
| `wasteWarningRatio` | — | no | number | `0.05` | Waste share that counts as a warning: 0.05 means 5%. |
| `yieldCriticalRatio` | — | no | number | `0.8` | Yield below which the job counts as critical: 0.80 means 80%. |
| `yieldMinProgressPercent` | — | no | number | `50` | How far along, in percent, the job must be before yield is checked. |
| `yieldWarningRatio` | — | no | number | `0.9` | Yield below which the job counts as a warning: 0.90 means 90%. |

## Print

### `<v:impose-pdf>` · Impose PDF

Places source PDF pages onto press sheets according to an imposition plan, and stores the print-ready PDF on the component. Use it after `impose-plan`, or with saved imposition specs.

Node type `impose_pdf`. Declare `xmlns:v="urn:cococo:workflow:print:1"` on the workflow; any prefix works, but the URI must match.

| Attribute | Config name | Required | Type / values | Default | Meaning |
|---|---|---|---|---|---|
| `componentId` | — | yes | string | — | The component (a TypeID starting `cmp_`) the imposition belongs to. It supplies the default artwork and receives the finished PDF. |
| `fileName` | — | no | string | — | Name for the stored PDF. Defaults to `imposition-<component short id>.pdf`. |
| `outputFolderId` | — | no | string | — | Folder for the imposed PDF (a TypeID starting `fld_`). Leave it out to use your default folder. |
| `renderMode` | — | no | `production`, `debug_summary` | `production` | `production` places the real source pages, with crop and registration marks; `debug_summary` writes a text summary of the placements instead, for testing. |
| `<plan>` | — | no | one typed value | — | One imposition plan, as produced by `impose-plan`. Give either this or `<imposition-spec-ids>`. |
| `<imposition-spec-ids>` | `impositionSpecIds` | no | `<value>` list | — | Saved imposition specs for the component (TypeIDs starting `imp_`), imposed in order. Give either this or `<plan>`. |
| `<page-binding>` | `pageBindings` | no | repeated element | — | Which source PDF supplies which placed pages. Optional when the component has exactly one artwork file. |

Each `<page-binding>` accepts:

| Attribute | Config name | Required | Type / values | Default | Meaning |
|---|---|---|---|---|---|
| `pageRangeEnd` | — | yes | integer | — | Last placed page this source covers (inclusive). |
| `pageRangeStart` | — | yes | integer | — | First placed page this source covers (inclusive, counting from 1). |
| `sourceDocumentId` | — | yes | string | — | The source PDF: an artwork file (`caf_…`) or a managed file (`fil_…`). |
| `sourcePageOffset` | — | no | integer | `0` | Added to the page number when mapping a placed page to a source page. |

### `<v:impose-plan>` · Impose Plan

Works out how to impose a job's pages on press sheets and returns the recommended plan. Use it to compare options, or feed the plan to `impose-pdf`.

Node type `impose_plan`. Declare `xmlns:v="urn:cococo:workflow:print:1"` on the workflow; any prefix works, but the URI must match.

| Attribute | Config name | Required | Type / values | Default | Meaning |
|---|---|---|---|---|---|
| `bindingType` | — | no | `SADDLE_STITCH`, `PERFECT_BOUND`, `CASE_BOUND`, `WIRE_BOUND`, `FLATWORK`, `FOLDED`, `OTHER` | — | Binding method; it decides how pages are ordered on the sheet. |
| `bleedMm` | — | no | number | `3` | Bleed on every edge, in millimetres. With `componentId`, it replaces the component's bleed. |
| `componentId` | — | no | string | — | Component (a TypeID starting `cmp_`) to take page size, quantity and substrates from, or a `{{ … }}` expression. Use this or the size attributes, not both. |
| `finishedHeightMm` | — | no | number | — | Trimmed page height in millimetres, when you give the size directly. |
| `finishedWidthMm` | — | no | number | — | Trimmed page width in millimetres, when you give the size directly. |
| `fullResult` | — | no | boolean | `false` | Also return every ranked plan as `plans`, not only the best one. |
| `maxPagesUp` | — | no | integer | — | Most pages to place per section; larger fold patterns are left out. |
| `mode` | — | no | `signature`, `ganging` | `signature` | `signature` plans folded sections for bound or folded work; `ganging` plans flat step-and-repeat layouts, several copies to a sheet. |
| `quantity` | — | no | integer | — | Copies to produce, used to estimate total sheets. With `componentId`, it replaces the component's quantity. |
| `totalPages` | — | no | integer | — | Total trimmed pages, when you give the size directly (with the width and height). |
| `<substrate>` | `substrates` | no | repeated element | — | Sheets to plan against, written out in full. Only with a size given directly, and not together with `<substrate-ids>`. |
| `<substrate-ids>` | `substrateIds` | no | `<value>` list | — | Substrates to plan against (TypeIDs starting `sub_`). With `componentId`, it narrows the component's substrates. |
| `<permitted-folds>` | `permittedFolds` | no | `<value>` list | — | Only consider these fold patterns, for example `f8` and `f16`. Unknown patterns are rejected. |

Each `<substrate>` accepts:

| Attribute | Config name | Required | Type / values | Default | Meaning |
|---|---|---|---|---|---|
| `heightMm` | — | yes | number | — | Sheet height in millimetres. |
| `name` | — | yes | string | — | Sheet name, for example `SRA3`. |
| `widthMm` | — | yes | number | — | Sheet width in millimetres. |

### `<v:pdf-preflight>` · PDF Preflight

Checks a component's artwork PDF against print requirements and reports any problems. Use it before production so faulty files are caught early.

Node type `pdf_preflight`. Declare `xmlns:v="urn:cococo:workflow:print:1"` on the workflow; any prefix works, but the URI must match.

| Attribute | Config name | Required | Type / values | Default | Meaning |
|---|---|---|---|---|---|
| `artworkFileId` | — | yes | string | — | The artwork file to check (a TypeID starting `caf_`), or a `{{ … }}` expression. |
| `persist` | — | no | boolean | `true` | Save the full report on the component. |
| `profile` | — | no | `COMMERCIAL_OFFSET`, `PDF_X_1A`, `PDF_X_3`, `PDF_X_4`, `PDF_X_CLAIMED` | `COMMERCIAL_OFFSET` | The standard to check against. |

### `<v:pdf-render>` · PDF Render

Renders one page of a PDF as an image. Use it to make proofs or thumbnails.

Node type `pdf_render`. Declare `xmlns:v="urn:cococo:workflow:print:1"` on the workflow; any prefix works, but the URI must match.

| Attribute | Config name | Required | Type / values | Default | Meaning |
|---|---|---|---|---|---|
| `artworkFileId` | — | no | string | — | Artwork file whose PDF to render (a TypeID starting `caf_`). Give either this or `fileId`. |
| `delivery` | — | no | `file`, `inline` | `file` | `file` stores the image as a file; `inline` returns it in the node's output. |
| `dpi` | — | no | integer | `200` | Resolution in dots per inch; 72 is the PDF's own size. |
| `fileId` | — | no | string | — | Managed file of the PDF to render (a TypeID starting `fil_`). Give either this or `artworkFileId`. |
| `fileName` | — | no | string | — | Name for the stored image, when delivered as a file. Defaults to `render-p<page>.<extension>`. |
| `format` | — | no | `jpeg`, `png`, `cmyk_tiff` | `jpeg` | Image format. |
| `maxEdgePixels` | — | no | integer | — | Optional limit on the image's longest side, in pixels; larger renders are scaled down. |
| `outputFolderId` | — | no | string | — | Folder for the stored image (a TypeID starting `fld_`), when delivered as a file. Leave it out to use your default folder. |
| `page` | — | no | integer | `1` | Page to render, counting from 1. |
| `quality` | — | no | integer | `85` | JPEG quality from 1 to 100. Ignored for PNG and TIFF. |

### `<v:pdf-separations>` · PDF Separations

Renders each ink of a PDF page as its own greyscale image, stored as files. Use it to check what each printing plate will carry.

Node type `pdf_separations`. Declare `xmlns:v="urn:cococo:workflow:print:1"` on the workflow; any prefix works, but the URI must match.

| Attribute | Config name | Required | Type / values | Default | Meaning |
|---|---|---|---|---|---|
| `artworkFileId` | — | no | string | — | Artwork file whose PDF to separate (a TypeID starting `caf_`). Give either this or `fileId`. |
| `dpi` | — | no | integer | `300` | Resolution in dots per inch; 72 is the PDF's own size. |
| `fileId` | — | no | string | — | Managed file of the PDF to separate (a TypeID starting `fil_`). Give either this or `artworkFileId`. |
| `fileName` | — | no | string | `separation` | Start of each stored file's name; files are named `<prefix>-p<page>-<ink>.png`. |
| `outputFolderId` | — | no | string | — | Folder for the plate images (a TypeID starting `fld_`). Leave it out to use your default folder. |
| `page` | — | no | integer | `1` | Page to separate, counting from 1. |
| `polarity` | — | no | `POSITIVE`, `NEGATIVE` | `POSITIVE` | Whether more ink shows as darker (`POSITIVE`) or lighter (`NEGATIVE`). |
| `<colorant>` | `colorants` | no | `<item>` list | — | Inks to render, for example `Cyan` or `PANTONE 286 C`. Leave it out to render CMYK plus every spot colour in the document. |

## Diagnostics

### `<log>` · Log

Writes a message to the run's log and passes its input on unchanged. Use it to record what happened, or to help understand a run later.

Node type `log`. The element's own text or CDATA sets `message`; do not also set it another way.

| Attribute | Config name | Required | Type / values | Default | Meaning |
|---|---|---|---|---|---|
| `level` | — | no | `debug`, `info`, `warning`, `error` | `info` | How important the message is. |
| `message` | — | yes | string | — | The message. Use `{{ … }}` to include inputs, earlier results or variables. |