# Workflow

A **Workflow** defines how the experience responds to a matched user intent. It contains the triggers (intents, keywords, expressions) and the ordered sequence of actions to execute.

## Workflow Properties

| Property      | Type                                                                       | Required | Default | Constraints               | Description                                                                                  |
| ------------- | -------------------------------------------------------------------------- | -------- | ------- | ------------------------- | -------------------------------------------------------------------------------------------- |
| `name`        | string                                                                     | No       | —       | Must not start with `nm:` | Unique identifier for this workflow. Used by `execute`, `goto`, and `welcomeMessageExecute`. |
| `intents`     | array of string \| [IntentObject](#intentobject)                           | **Yes**  | —       | —                         | Intent triggers for this workflow.                                                           |
| `keywords`    | array of [Keyword](#keyword)                                               | No       | —       | —                         | Exact-match keyword triggers.                                                                |
| `expressions` | array of string \| [Expression](#expression)                               | No       | —       | —                         | NLU training phrases for intent matching.                                                    |
| `actions`     | array of [Action](broken://pages/5b89afd4cd5115b5bcefb6933f09e2528ee35422) | **Yes**  | —       | —                         | Ordered sequence of actions to execute.                                                      |
| `validation`  | [Validation](#validation)                                                  | No       | —       | —                         | Attribute validation applied before action execution.                                        |

{% hint style="danger" %}
Both `intents` and `actions` are required on every workflow. A workflow missing either property is invalid.
{% endhint %}

{% hint style="danger" %}
Workflow `name` values MUST NOT begin with the prefix `nm:`. This prefix is reserved for internal nativeMsg system identifiers.
{% endhint %}

## Sub-Definitions

### IntentObject

An **IntentObject** is the structured form of an intent declaration. It is used when an intent requires additional configuration beyond a bare string name.

| Property         | Type                               | Required | Default | Constraints | Description                                              |
| ---------------- | ---------------------------------- | -------- | ------- | ----------- | -------------------------------------------------------- |
| `name`           | string                             | **Yes**  | —       | —           | Intent identifier.                                       |
| `expressions`    | array of [Expression](#expression) | No       | —       | —           | NLU training phrases scoped to this intent.              |
| `excludeContext` | string                             | No       | —       | —           | Suppresses this intent when the named context is active. |

```json
{
  "intents": [
    {
      "name": "cancel_order",
      "excludeContext": "payment_in_progress",
      "expressions": [
        { "text": "I want to cancel my order" },
        { "text": "cancel order" }
      ]
    }
  ]
}
```

### Keyword

A **Keyword** defines an exact-match trigger. The platform matches keyword values before evaluating NLU intents.

| Property | Type                  | Required | Default | Constraints | Description               |
| -------- | --------------------- | -------- | ------- | ----------- | ------------------------- |
| `name`   | string                | **Yes**  | —       | —           | Keyword identifier.       |
| `values` | array of KeywordValue | No       | —       | —           | List of matchable values. |

KeywordValue sub-object:

| Property      | Type            | Required | Default | Constraints | Description                               |
| ------------- | --------------- | -------- | ------- | ----------- | ----------------------------------------- |
| `value`       | string          | **Yes**  | —       | —           | Exact string to match against user input. |
| `expressions` | array of string | No       | —       | —           | Alternate phrasings for this value.       |

```json
{
  "keywords": [
    {
      "name": "stop_keyword",
      "values": [
        { "value": "STOP" },
        { "value": "UNSUBSCRIBE", "expressions": ["opt out", "remove me"] }
      ]
    }
  ]
}
```

### Expression

An **Expression** is a natural language training phrase. It MAY be a bare string or a structured object.

| Property   | Type                   | Required | Default | Constraints | Description                                                       |
| ---------- | ---------------------- | -------- | ------- | ----------- | ----------------------------------------------------------------- |
| `text`     | string                 | **Yes**  | —       | —           | The training phrase text.                                         |
| `generate` | boolean                | No       | `true`  | —           | When `true`, the platform generates additional phrase variations. |
| `slots`    | array of [Slot](#slot) | No       | —       | —           | Entity annotations within the expression text.                    |

Bare string form:

```json
{
  "expressions": ["track my order", "where is my package"]
}
```

Structured object form:

```json
{
  "expressions": [
    {
      "text": "I want to track order number ACM-12345",
      "generate": true,
      "slots": [
        {
          "type": "order_number",
          "value": "ACM-12345",
          "name": "orderNumber"
        }
      ]
    }
  ]
}
```

### Slot

A **Slot** annotates an entity within an expression text.

| Property | Type   | Required | Default | Constraints | Description                                                             |
| -------- | ------ | -------- | ------- | ----------- | ----------------------------------------------------------------------- |
| `type`   | string | **Yes**  | —       | —           | Entity type recognized by the NLU engine.                               |
| `value`  | string | **Yes**  | —       | —           | The literal substring in the expression text that represents this slot. |
| `name`   | string | **Yes**  | —       | —           | Name under which the extracted value is stored.                         |

{% hint style="info" %}
The `value` in a Slot definition is the training example value — the literal text as it appears in the expression. At runtime, the NLU engine recognizes any matching entity of the given `type`, not just the training value.
{% endhint %}

### Validation

A **Validation** tests an attribute value before executing the workflow's actions.

| Property         | Type                      | Required | Default | Constraints           | Description                                                  |
| ---------------- | ------------------------- | -------- | ------- | --------------------- | ------------------------------------------------------------ |
| `content`        | string                    | **Yes**  | —       | —                     | Name of the attribute to validate.                           |
| `pattern`        | string                    | **Yes**  | —       | Must be a valid regex | Regular expression the attribute value must match.           |
| `executeOnError` | string \| array of string | No       | —       | —                     | Workflow or action name(s) to execute when validation fails. |

```json
{
  "validation": {
    "content": "orderNumber",
    "pattern": "^ACM-\\d{5}$",
    "executeOnError": "invalid-order-number"
  }
}
```

{% hint style="danger" %}
Both `content` and `pattern` are required in a Validation object. Omitting either property produces a schema validation error.
{% endhint %}

## Complete Example

The following example shows a realistic workflow with multiple intent forms, keyword triggers, NLU expressions, attribute validation, and several action types.

```json
{
  "name": "order-tracking",
  "intents": [
    "check_order_status",
    {
      "name": "track_package",
      "excludeContext": "order_dispute_open",
      "expressions": [
        { "text": "track my package" },
        { "text": "where is my shipment", "generate": true }
      ]
    }
  ],
  "keywords": [
    {
      "name": "track_keyword",
      "values": [
        { "value": "TRACK" },
        { "value": "TRACKORDER" }
      ]
    }
  ],
  "expressions": [
    "where is my order",
    "has my order shipped",
    {
      "text": "track order ACM-12345",
      "generate": false,
      "slots": [
        {
          "type": "order_id",
          "value": "ACM-12345",
          "name": "orderNumber"
        }
      ]
    }
  ],
  "validation": {
    "content": "sessionActive",
    "pattern": "^true$",
    "executeOnError": "session-expired"
  },
  "actions": [
    {
      "name": "ask-order-id",
      "send": {
        "message": {
          "text": "Please enter your order number (format: ACM-XXXXX)."
        }
      }
    },
    {
      "name": "capture-order-id",
      "waitFor": {
        "data": "text",
        "content": "orderNumber",
        "timeout": "2m",
        "executeOnTimeout": "order-id-timeout"
      }
    },
    {
      "name": "validate-order-id",
      "validation": {
        "content": "orderNumber",
        "pattern": "^ACM-\\d{5}$",
        "executeOnError": "invalid-order-id"
      }
    },
    {
      "name": "fetch-order-status",
      "send": {
        "request": {
          "url": "https://api.acme.com/orders/{orderNumber}/status",
          "method": "GET",
          "headers": {
            "Authorization": "Bearer {apiToken}",
            "Accept": "application/json"
          },
          "dataFormat": "json",
          "response": {
            "status": "orderStatus",
            "estimatedDelivery": "deliveryDate",
            "carrier": "carrierName"
          },
          "retries": 2,
          "fallback": "order-lookup-failed"
        }
      }
    },
    {
      "name": "send-order-status",
      "send": {
        "message": {
          "text": "Your order {orderNumber} is currently {orderStatus}. Estimated delivery: {deliveryDate} via {carrierName}.",
          "quickReplies": [
            {
              "type": "text",
              "title": "Track shipment",
              "payload": "track_shipment"
            },
            {
              "type": "text",
              "title": "Contact support",
              "payload": "contact_support"
            }
          ]
        }
      }
    }
  ]
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://playbook.nativemsg.com/rcs-experience-schema/reference/workflow.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
