From 4235d97710b1810f2786ca67c46de5bea415a1f8 Mon Sep 17 00:00:00 2001 From: Naresh Jain Date: Wed, 3 Dec 2025 11:23:58 +0530 Subject: [PATCH 01/21] Added support for AsyncAPI v3 Also cleaned up the spec to make it very clear that step-object can be oneOf openapi-step-object or asyncapi-step-object or workflow-step-object For AsyncAPI we really need support for timeout and dependOn. However, these are also useful for OpenAPI/Workflow steps so added it at the base step object. For OpenAPI we need at least one successCriteria but for AsyncAPI it can be optional. --- src/schemas/validation/schema.yaml | 137 ++++++++++++++++++++++++----- 1 file changed, 116 insertions(+), 21 deletions(-) diff --git a/src/schemas/validation/schema.yaml b/src/schemas/validation/schema.yaml index 8c08ee2..61d054a 100644 --- a/src/schemas/validation/schema.yaml +++ b/src/schemas/validation/schema.yaml @@ -77,6 +77,7 @@ $defs: enum: - arazzo - openapi + - asyncapi required: - name - url @@ -156,7 +157,12 @@ $defs: $comment: https://spec.openapis.org/arazzo/v1.1#step-object' description: |- Describes a single workflow step which MAY be a call to an - API operation (OpenAPI Operation Object or another Workflow Object) + API operation (OpenAPI Operation Object or AsyncAPI Operation Object or another Workflow Object) + oneOf: + - $ref: '#/$defs/openapi-step-object' + - $ref: '#/$defs/asyncapi-step-object' + - $ref: '#/$defs/workflow-step-object' + step-object-base: type: object properties: stepId: @@ -169,6 +175,16 @@ $defs: operationId: description: The name of an existing, resolvable operation, as defined with a unique operationId and existing within one of the sourceDescriptions type: string + timeout: + description: The duration in milliseconds to wait before timing out the step + type: integer + dependsOn: + description: Specifies a list of step identifiers that must complete (or be waited for) before the current step can begin execution + type: array + uniqueItems: true + minItems: 1 + items: + $ref: '#stepId' operationPath: description: A reference to a Source combined with a JSON Pointer to reference an operation type: string @@ -217,14 +233,21 @@ $defs: - $ref: '#/$defs/selector-object' required: - stepId - oneOf: - - required: - - operationId - - required: - - operationPath - - required: - - workflowId + openapi-step-object: allOf: + - $ref: '#/$defs/step-object-base' + - type: object + properties: + operationPath: + description: A reference to a Source combined with a JSON Pointer to reference an operation + type: string + successCriteria: + description: A list of assertions to determine the success of the step + type: array + uniqueItems: true + minItems: 1 + items: + $ref: '#/$defs/criterion-object' - if: oneOf: - required: @@ -236,25 +259,96 @@ $defs: parameters: items: oneOf: - - $ref: '#/$defs/reusable-object' - $ref: '#/$defs/parameter-object' required: - in + - $ref: '#/$defs/reusable-object' + - oneOf: + - required: + - operationId + - required: + - operationPath + $ref: '#/$defs/specification-extensions' + unevaluatedProperties: false + asyncapi-step-object: + allOf: + - $ref: '#/$defs/step-object-base' + - type: object + properties: + channelPath: + description: A reference to a Source combined with a JSON Pointer to reference an async channel + type: string + correlationId: + description: ID to correlate async responses with their requests, only specified for async receive steps + type: + - string + - number + - boolean + - object + - array + action: + description: Specifies the intended operation on the async channel, indicating whether the action is sending data to the channel or receiving data from the channel + enum: + - send + - receive + successCriteria: + description: A list of assertions to determine the success of the step + type: array + uniqueItems: true + minItems: 0 + items: + $ref: '#/$defs/criterion-object' + required: + - action - if: - required: - - workflowId + oneOf: + - required: + - operationId + - required: + - channelPath then: properties: parameters: items: oneOf: - - $ref: '#/$defs/parameter-object' - $ref: '#/$defs/reusable-object' + - $ref: '#/$defs/parameter-object' + required: + - in + - if: + required: + - correlationId + then: + properties: + action: + const: receive + required: + - action + - oneOf: + - required: + - operationId + - required: + - channelPath $ref: '#/$defs/specification-extensions' unevaluatedProperties: false + workflow-step-object: + allOf: + - $ref: '#/$defs/step-object-base' + - type: object + properties: + workflowId: + description: The workflowId referencing an existing workflow within the Arazzo description + $ref: '#workflowId' + parameters: + items: + oneOf: + - $ref: '#/$defs/parameter-object' + - $ref: '#/$defs/reusable-object' + required: + - workflowId request-body-object: $comment: https://spec.openapis.org/arazzo/v1.1#request-body-object - description: The request body to pass to an operation as referenced by operationId or operationPath + description: The request body to pass to an operation as referenced by operationId or operationPath or channelPath type: object properties: contentType: @@ -287,7 +381,7 @@ $defs: description: The type of condition to be applied or a reference to an expression type object oneOf: - type: string - enum: + enum: - simple - regex - jsonpath @@ -330,10 +424,10 @@ $defs: then: properties: version: - enum: + enum: - rfc9535 - draft-goessner-dispatch-jsonpath-00 - + - if: required: - type @@ -356,7 +450,7 @@ $defs: then: properties: version: - const: rfc6901 + const: rfc6901 $ref: '#/$defs/specification-extensions' success-action-object: $comment: https://spec.openapis.org/arazzo/v1.1#success-action-object @@ -435,7 +529,7 @@ $defs: description: A list of parameters that MUST be passed to a workflow as referenced by workflowId type: array uniqueItems: true - items: true + items: true retryAfter: description: A non-negative decimal indicating the seconds to delay after the step failure before another attempt SHALL be made type: number @@ -475,7 +569,7 @@ $defs: - parameters then: required: - - workflowId + - workflowId required: - name - type @@ -516,6 +610,7 @@ $defs: - query - header - cookie + - channel value: description: The value to pass in the parameter oneOf: @@ -525,7 +620,7 @@ $defs: - array - number - 'null' - - $ref: '#/$defs/selector-object' + - $ref: '#/$defs/selector-object' required: - name - value @@ -544,7 +639,7 @@ $defs: The selector expression type to use (e.g., `jsonpath`, `xpath`, or `jsonpointer`). Should an alternate version be required, the Expression Type Object may be used instead. If omitted, defaults to JSON Pointer for `application/json` or XPath for XML-based media types. - $ref: '#/$defs/selector-type' + $ref: '#/$defs/selector-type' value: description: > The value to set at the location defined by the target. May be a literal, From 37a515126b1814154d14369ed1f2b01dad102187 Mon Sep 17 00:00:00 2001 From: Naresh Jain Date: Sun, 7 Dec 2025 22:06:59 +0530 Subject: [PATCH 02/21] Update arazzo.md file with AsyncAPI related changes along with a sample AsyncAPI specification for Pet Purchase API --- src/arazzo.md | 363 ++++++++++++++++----------- src/specifications/pet-asyncapi.yaml | 81 ++++++ 2 files changed, 294 insertions(+), 150 deletions(-) create mode 100644 src/specifications/pet-asyncapi.yaml diff --git a/src/arazzo.md b/src/arazzo.md index 248b017..c2bc2cd 100644 --- a/src/arazzo.md +++ b/src/arazzo.md @@ -84,13 +84,13 @@ As defined by the [JSON Schema Validation vocabulary](https://tools.ietf.org/htm The formats defined are: -| `format` | JSON Data Type | Comments | -| ---- | ---- | ---- | -| `int32` | number | signed 32 bits | -| `int64` | number | signed 64 bits (a.k.a long) | -| `float` | number | | -| `double` | number | | -| `password` | string | A hint to obscure the value. | +| `format` | JSON Data Type | Comments | +| ---------- | -------------- | ---------------------------- | +| `int32` | number | signed 32 bits | +| `int64` | number | signed 64 bits (a.k.a long) | +| `float` | number | | +| `double` | number | | +| `password` | string | A hint to obscure the value. | ### Relative References in URLs @@ -107,20 +107,20 @@ This is the root object of the [Arazzo Description](#arazzo-description). ##### Fixed Fields -| Field Name | Type | Description | -| ---- | :----: | ---- | -| arazzo | `string` | **REQUIRED**. This string MUST be the [version number](#versions) of the Arazzo Specification that the Arazzo Description uses. The `arazzo` field MUST be used by tooling to interpret the Arazzo Description. | -| info | [Info Object](#info-object) | **REQUIRED**. Provides metadata about the workflows contain within the Arazzo Description. The metadata MAY be used by tooling as required. | -| sourceDescriptions | [[Source Description Object](#source-description-object)] | **REQUIRED**. A list of source descriptions (such as an OpenAPI description) this Arazzo Description SHALL apply to. The list MUST have at least one entry. | -| workflows | [[Workflow Object](#workflow-object)] | **REQUIRED**. A list of workflows. The list MUST have at least one entry. | -| components | [Components Object](#components-object) | An element to hold various schemas for the Arazzo Description. | +| Field Name | Type | Description | +| ---------------------------------------------- | :-------------------------------------------------------: | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| arazzo | `string` | **REQUIRED**. This string MUST be the [version number](#versions) of the Arazzo Specification that the Arazzo Description uses. The `arazzo` field MUST be used by tooling to interpret the Arazzo Description. | +| info | [Info Object](#info-object) | **REQUIRED**. Provides metadata about the workflows contain within the Arazzo Description. The metadata MAY be used by tooling as required. | +| sourceDescriptions | [[Source Description Object](#source-description-object)] | **REQUIRED**. A list of source descriptions (such as an OpenAPI description) this Arazzo Description SHALL apply to. The list MUST have at least one entry. | +| workflows | [[Workflow Object](#workflow-object)] | **REQUIRED**. A list of workflows. The list MUST have at least one entry. | +| components | [Components Object](#components-object) | An element to hold various schemas for the Arazzo Description. | This object MAY be extended with [Specification Extensions](#specification-extensions). ##### Arazzo Specification Object Example ```yaml -arazzo: 1.0.1 +arazzo: 1.1.0 info: title: A pet purchasing workflow summary: This Arazzo Description showcases the workflow for how to purchase a pet through a sequence of API calls @@ -131,6 +131,9 @@ sourceDescriptions: - name: petStoreDescription url: https://github.com/swagger-api/swagger-petstore/blob/master/src/main/resources/openapi.yaml type: openapi +- name: asyncOrderApiDescription + url: https://github.com/OAI/Arazzo-Specification/blob/dev/src/specification/order-asyncapi.yaml + type: asyncapi workflows: - workflowId: loginUserAndRetrievePet @@ -143,6 +146,8 @@ workflows: type: string password: type: string + orderCorrelationId: + type: string steps: - stepId: loginStep description: This step demonstrates the user login step @@ -175,11 +180,35 @@ workflows: value: $steps.loginUser.outputs.sessionToken successCriteria: - condition: $statusCode == 200 + onSuccess: + - name: 'noPetsAvailable' + type: "end" + criteria: + - condition: $response.body#/0 == null outputs: - # outputs from this step - availablePets: $response.body + petId: $response.body#/0/id + - stepId: purchasePetStep + description: purchase a pet by posting an message on place-order channel + operationPath: $sourceDescriptions.asyncOrderApiDescription.placeOrder + action: send + parameters: + - name: orderCorrelationId + in: header + value: $inputs.orderCorrelationId + requestBody: + contentType: application/json + payload: + petId: $steps.getPetStep.outputs.petId + - stepId: confirmPetPurchaseStep + description: confirm the purchase of a pet + operationPath: $sourceDescriptions.asyncOrderApiDescription.confirmOrder + correlationId: $inputs.orderCorrelationId + timeout: 6000 + action: receive + outputs: + orderId: $message.payload.orderId outputs: - available: $steps.getPetStep.outputs.availablePets + orderId: $steps.confirmPetPurchaseStep.outputs.orderId ``` #### Info Object @@ -189,12 +218,12 @@ The metadata MAY be used by the clients if needed. ##### Fixed Fields -| Field Name | Type | Description | -| --- | :---: | --- | -| title | `string` | **REQUIRED**. A human readable title of the Arazzo Description. | -| summary | `string` | A short summary of the Arazzo Description. | +| Field Name | Type | Description | +| ----------------------------------------- | :------: | -------------------------------------------------------------------------------------------------------------------------------------------------- | +| title | `string` | **REQUIRED**. A human readable title of the Arazzo Description. | +| summary | `string` | A short summary of the Arazzo Description. | | description | `string` | A description of the purpose of the workflows defined. [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation. | -| version | `string` | **REQUIRED**. The version identifier of the Arazzo document (which is distinct from the [Arazzo Specification version](#versions)). | +| version | `string` | **REQUIRED**. The version identifier of the Arazzo document (which is distinct from the [Arazzo Specification version](#versions)). | This object MAY be extended with [Specification Extensions](#specification-extensions). @@ -217,11 +246,11 @@ An object storing a map between named description keys and location URLs to the ##### Fixed Fields -| Field Name | Type | Description | -| --- | :---: | --- | +| Field Name | Type | Description | +| ----------------------------- | :------: | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | name | `string` | **REQUIRED**. A unique name for the source description. Tools and libraries MAY use the `name` to uniquely identify a source description, therefore, it is RECOMMENDED to follow common programming naming conventions. SHOULD conform to the regular expression `[A-Za-z0-9_\-]+`. | -| url | `string` | **REQUIRED**. A URL to a source description to be used by a workflow. If a relative reference is used, it MUST be in the form of a URI-reference as defined by [RFC3986](https://tools.ietf.org/html/rfc3986#section-4.2). | -| type | `string` | The type of source description. Possible values are `"openapi"` or `"arazzo"`. | +| url | `string` | **REQUIRED**. A URL to a source description to be used by a workflow. If a relative reference is used, it MUST be in the form of a URI-reference as defined by [RFC3986](https://tools.ietf.org/html/rfc3986#section-4.2). | +| type | `string` | The type of source description. Possible values are `"openapi"` or `"asyncapi"` or `"arazzo"`. | This object MAY be extended with [Specification Extensions](#specification-extensions). @@ -240,18 +269,18 @@ Describes the steps to be taken across one or more APIs to achieve an objective. ##### Fixed Fields -| Field Name | Type | Description | -| --- | :---: | --- | -| workflowId | `string` | **REQUIRED**. Unique string to represent the workflow. The id MUST be unique amongst all workflows described in the Arazzo Description. The `workflowId` value is **case-sensitive**. Tools and libraries MAY use the `workflowId` to uniquely identify a workflow, therefore, it is RECOMMENDED to follow common programming naming conventions. SHOULD conform to the regular expression `[A-Za-z0-9_\-]+`. | -| summary | `string` | A summary of the purpose or objective of the workflow. | -| description | `string` | A description of the workflow. [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation. | -| inputs | `JSON Schema` | A JSON Schema 2020-12 object representing the input parameters used by this workflow. | -| dependsOn | [`string`] | A list of workflows that MUST be completed before this workflow can be processed. Each value provided MUST be a `workflowId`. If the workflow depended on is defined within the current Workflow Document, then specify the `workflowId` of the relevant local workflow. If the workflow is defined in a separate Arazzo Document then the workflow MUST be defined in the `sourceDescriptions` and the `workflowId` MUST be specified using a [Runtime Expression](#runtime-expressions) (e.g., `$sourceDescriptions..`) to avoid ambiguity or potential clashes. | -| steps | [[Step Object](#step-object)] | **REQUIRED**. An ordered list of steps where each step represents a call to an API operation or to another workflow. | -| successActions | [[Success Action Object](#success-action-object) \| [Reusable Object](#reusable-object)] | A list of success actions that are applicable for all steps described under this workflow. These success actions can be overridden at the step level but cannot be removed there. If a Reusable Object is provided, it MUST link to success actions defined in the [components/successActions](#components-object) of the current Arazzo document. The list MUST NOT include duplicate success actions. | -| failureActions | [[Failure Action Object](#failure-action-object) \| [Reusable Object](#reusable-object)] | A list of failure actions that are applicable for all steps described under this workflow. These failure actions can be overridden at the step level but cannot be removed there. If a Reusable Object is provided, it MUST link to failure actions defined in the [components/failureActions](#components-object) of the current Arazzo document. The list MUST NOT include duplicate failure actions. | -| outputs | Map[`string`, {expression} \| [Selector Object](#selector-object) ] | A map between a friendly name and a dynamic output value defined using a [Runtime Expression](#runtime-expressions) or [Selector Object](#selector-object). The name MUST use keys that match the regular expression: `^[a-zA-Z0-9\.\-_]+$`. | -| parameters | [[Parameter Object](#parameter-object) \| [Reusable Object](#reusable-object)] | A list of parameters that are applicable for all steps described under this workflow. These parameters can be overridden at the step level but cannot be removed there. Each parameter MUST be passed to an operation or workflow as referenced by `operationId`, `operationPath`, or `workflowId` as specified within each step. If a Reusable Object is provided, it MUST link to a parameter defined in the [components/parameters](#components-object) of the current Arazzo document. The list MUST NOT include duplicate parameters. | +| Field Name | Type | Description | +| --------------------------------------------------- | :--------------------------------------------------------------------------------------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| workflowId | `string` | **REQUIRED**. Unique string to represent the workflow. The id MUST be unique amongst all workflows described in the Arazzo Description. The `workflowId` value is **case-sensitive**. Tools and libraries MAY use the `workflowId` to uniquely identify a workflow, therefore, it is RECOMMENDED to follow common programming naming conventions. SHOULD conform to the regular expression `[A-Za-z0-9_\-]+`. | +| summary | `string` | A summary of the purpose or objective of the workflow. | +| description | `string` | A description of the workflow. [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation. | +| inputs | `JSON Schema` | A JSON Schema 2020-12 object representing the input parameters used by this workflow. | +| dependsOn | [`string`] | A list of workflows that MUST be completed before this workflow can be processed. Each value provided MUST be a `workflowId`. If the workflow depended on is defined within the current Workflow Document, then specify the `workflowId` of the relevant local workflow. If the workflow is defined in a separate Arazzo Document then the workflow MUST be defined in the `sourceDescriptions` and the `workflowId` MUST be specified using a [Runtime Expression](#runtime-expressions) (e.g., `$sourceDescriptions..`) to avoid ambiguity or potential clashes. | +| steps | [[Step Object](#step-object)] | **REQUIRED**. An ordered list of steps where each step represents a call to an API operation or to another workflow. | +| successActions | [[Success Action Object](#success-action-object) \| [Reusable Object](#reusable-object)] | A list of success actions that are applicable for all steps described under this workflow. These success actions can be overridden at the step level but cannot be removed there. If a Reusable Object is provided, it MUST link to success actions defined in the [components/successActions](#components-object) of the current Arazzo document. The list MUST NOT include duplicate success actions. | +| failureActions | [[Failure Action Object](#failure-action-object) \| [Reusable Object](#reusable-object)] | A list of failure actions that are applicable for all steps described under this workflow. These failure actions can be overridden at the step level but cannot be removed there. If a Reusable Object is provided, it MUST link to failure actions defined in the [components/failureActions](#components-object) of the current Arazzo document. The list MUST NOT include duplicate failure actions. | +| outputs | Map[`string`, {expression} \| [Selector Object](#selector-object) ] | A map between a friendly name and a dynamic output value defined using a [Runtime Expression](#runtime-expressions) or [Selector Object](#selector-object). The name MUST use keys that match the regular expression: `^[a-zA-Z0-9\.\-_]+$`. | +| parameters | [[Parameter Object](#parameter-object) \| [Reusable Object](#reusable-object)] | A list of parameters that are applicable for all steps described under this workflow. These parameters can be overridden at the step level but cannot be removed there. Each parameter MUST be passed to an operation or workflow as referenced by `operationId`, `operationPath`, or `workflowId` as specified within each step. If a Reusable Object is provided, it MUST link to a parameter defined in the [components/parameters](#components-object) of the current Arazzo document. The list MUST NOT include duplicate parameters. | This object MAY be extended with [Specification Extensions](#specification-extensions). @@ -298,19 +327,24 @@ Describes a single workflow step which MAY be a call to an API operation ([OpenA ##### Fixed Fields -| Field Name | Type | Description | -| --- | :---: | --- | -| description | `string` | A description of the step. [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation. | -| stepId | `string` | **REQUIRED**. Unique string to represent the step. The `stepId` MUST be unique amongst all steps described in the workflow. The `stepId` value is **case-sensitive**. Tools and libraries MAY use the `stepId` to uniquely identify a workflow step, therefore, it is RECOMMENDED to follow common programming naming conventions. SHOULD conform to the regular expression `[A-Za-z0-9_\-]+`. | -| operationId | `string` | The name of an existing, resolvable operation, as defined with a unique `operationId` and existing within one of the `sourceDescriptions`. The referenced operation will be invoked by this workflow step. If multiple (non `arazzo` type) `sourceDescriptions` are defined, then the `operationId` MUST be specified using a [Runtime Expression](#runtime-expressions) (e.g., `$sourceDescriptions..`) to avoid ambiguity or potential clashes. This field is mutually exclusive of the `operationPath` and `workflowId` fields respectively. | -| operationPath | `string` | A reference to a [Source Description Object](#source-description-object) combined with a [JSON Pointer](https://tools.ietf.org/html/rfc6901) to reference an operation. This field is mutually exclusive of the `operationId` and `workflowId` fields respectively. The operation being referenced MUST be described within one of the `sourceDescriptions` descriptions. A [Runtime Expression](#runtime-expressions) syntax MUST be used to identify the source description document. If the referenced operation has an `operationId` defined then the `operationId` SHOULD be preferred over the `operationPath`. | -| workflowId | `string` | The [workflowId](#fixed-fields-2) referencing an existing workflow within the Arazzo Description. If the referenced workflow is contained within an `arazzo` type `sourceDescription`, then the `workflowId` MUST be specified using a [Runtime Expression](#runtime-expressions) (e.g., `$sourceDescriptions..`) to avoid ambiguity or potential clashes. The field is mutually exclusive of the `operationId` and `operationPath` fields respectively. | -| parameters | [[Parameter Object](#parameter-object) \| [Reusable Object](#reusable-object)] | A list of parameters that MUST be passed to an operation or workflow as referenced by `operationId`, `operationPath`, or `workflowId`. If a parameter is already defined at the [Workflow](#workflow-object), the new definition will override it but can never remove it. If a Reusable Object is provided, it MUST link to a parameter defined in the [components/parameters](#components-object) of the current Arazzo document. The list MUST NOT include duplicate parameters. | -| requestBody | [Request Body Object](#request-body-object) | The request body to pass to an operation as referenced by `operationId` or `operationPath`. The `requestBody` is fully supported in HTTP methods where the HTTP 1.1 specification [RFC9110](https://tools.ietf.org/html/rfc9110#section-9.3) explicitly defines semantics for "content" like request bodies, such as within POST, PUT, and PATCH methods. For methods where the HTTP specification provides less clarity—such as GET, HEAD, and DELETE—the use of `requestBody` is permitted but does not have well-defined semantics. In these cases, its use SHOULD be avoided if possible. | -| successCriteria | [[Criterion Object](#criterion-object)] | A list of assertions to determine the success of the step. Each assertion is described using a [Criterion Object](#criterion-object). All assertions `MUST` be satisfied for the step to be deemed successful. | -| onSuccess | [[Success Action Object](#success-action-object) \| [Reusable Object](#reusable-object)] | An array of success action objects that specify what to do upon step success. If omitted, the next sequential step shall be executed as the default behavior. If multiple success actions have similar `criteria`, the first sequential action matching the criteria SHALL be the action executed. If a success action is already defined at the [Workflow](#workflow-object), the new definition will override it but can never remove it. If a Reusable Object is provided, it MUST link to a success action defined in the [components](#components-object) of the current Arazzo document. The list MUST NOT include duplicate success actions. | -| onFailure | [[Failure Action Object](#failure-action-object) \| [Reusable Object](#reusable-object)] | An array of failure action objects that specify what to do upon step failure. If omitted, the default behavior is to break and return. If multiple failure actions have similar `criteria`, the first sequential action matching the criteria SHALL be the action executed. If a failure action is already defined at the [Workflow](#workflow-object), the new definition will override it but can never remove it. If a Reusable Object is provided, it MUST link to a failure action defined in the [components](#components-object) of the current Arazzo document. The list MUST NOT include duplicate failure actions. | -| outputs | Map[`string`, {expression} \| [Selector Object](#selector-object)] | A map between a friendly name and a dynamic output value defined using a [Runtime Expression](#runtime-expressions) or [Selector Object](#selector-object). The name MUST use keys that match the regular expression: `^[a-zA-Z0-9\.\-_]+$`. | +| Field Name | Type | Description | +| ------------------------------------------------- | :--------------------------------------------------------------------------------------: | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| description | `string` | A description of the step. [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation. | +| stepId | `string` | **REQUIRED**. Unique string to represent the step. The `stepId` MUST be unique amongst all steps described in the workflow. The `stepId` value is **case-sensitive**. Tools and libraries MAY use the `stepId` to uniquely identify a workflow step, therefore, it is RECOMMENDED to follow common programming naming conventions. SHOULD conform to the regular expression `[A-Za-z0-9_\-]+`. | +| operationId | `string` | The name of an existing, resolvable operation, as defined with a unique `operationId` and existing within one of the `sourceDescriptions`. The referenced operation will be invoked by this workflow step. If multiple (non `arazzo` type) `sourceDescriptions` are defined, then the `operationId` MUST be specified using a [Runtime Expression](#runtime-expressions) (e.g., `$sourceDescriptions..`) to avoid ambiguity or potential clashes. This field is mutually exclusive of the `operationPath` and `workflowId` fields respectively. | +| operationPath | `string` | A reference to a [Source Description Object](#source-description-object) combined with a [JSON Pointer](https://tools.ietf.org/html/rfc6901) to reference an operation. This field is mutually exclusive of the `operationId` and `workflowId` fields respectively. The operation being referenced MUST be described within one of the `sourceDescriptions` descriptions. A [Runtime Expression](#runtime-expressions) syntax MUST be used to identify the source description document. If the referenced operation has an `operationId` defined then the `operationId` SHOULD be preferred over the `operationPath`. | +| channelPath | `string` | A reference to a [Source Description Object](#source-description-object) combined with a [JSON Pointer](https://tools.ietf.org/html/rfc6901) to reference an event channel. This field is mutually exclusive of the `operationId` and `workflowId` fields respectively. The operation being referenced MUST be described within one of the `sourceDescriptions` descriptions. A [Runtime Expression](#runtime-expressions) syntax MUST be used to identify the source description document. If the referenced operation has an `operationId` defined then the `operationId` SHOULD be preferred over the `channelPath`. | +| workflowId | `string` | The [workflowId](#fixed-fields-2) referencing an existing workflow within the Arazzo Description. If the referenced workflow is contained within an `arazzo` type `sourceDescription`, then the `workflowId` MUST be specified using a [Runtime Expression](#runtime-expressions) (e.g., `$sourceDescriptions..`) to avoid ambiguity or potential clashes. The field is mutually exclusive of the `operationId` and `operationPath` fields respectively. | +| parameters | [[Parameter Object](#parameter-object) \| [Reusable Object](#reusable-object)] | A list of parameters that MUST be passed to an operation or workflow as referenced by `operationId`, `operationPath`, or `workflowId`. If a parameter is already defined at the [Workflow](#workflow-object), the new definition will override it but can never remove it. If a Reusable Object is provided, it MUST link to a parameter defined in the [components/parameters](#components-object) of the current Arazzo document. The list MUST NOT include duplicate parameters. | +| requestBody | [Request Body Object](#request-body-object) | The request body to pass to an operation as referenced by `operationId` or `operationPath`. The `requestBody` is fully supported in HTTP methods where the HTTP 1.1 specification [RFC9110](https://tools.ietf.org/html/rfc9110#section-9.3) explicitly defines semantics for "content" like request bodies, such as within POST, PUT, and PATCH methods. For methods where the HTTP specification provides less clarity—such as GET, HEAD, and DELETE—the use of `requestBody` is permitted but does not have well-defined semantics. In these cases, its use SHOULD be avoided if possible. | +| successCriteria | [[Criterion Object](#criterion-object)] | A list of assertions to determine the success of the step. Each assertion is described using a [Criterion Object](#criterion-object). All assertions `MUST` be satisfied for the step to be deemed successful. | +| onSuccess | [[Success Action Object](#success-action-object) \| [Reusable Object](#reusable-object)] | An array of success action objects that specify what to do upon step success. If omitted, the next sequential step shall be executed as the default behavior. If multiple success actions have similar `criteria`, the first sequential action matching the criteria SHALL be the action executed. If a success action is already defined at the [Workflow](#workflow-object), the new definition will override it but can never remove it. If a Reusable Object is provided, it MUST link to a success action defined in the [components](#components-object) of the current Arazzo document. The list MUST NOT include duplicate success actions. | +| onFailure | [[Failure Action Object](#failure-action-object) \| [Reusable Object](#reusable-object)] | An array of failure action objects that specify what to do upon step failure. If omitted, the default behavior is to break and return. If multiple failure actions have similar `criteria`, the first sequential action matching the criteria SHALL be the action executed. If a failure action is already defined at the [Workflow](#workflow-object), the new definition will override it but can never remove it. If a Reusable Object is provided, it MUST link to a failure action defined in the [components](#components-object) of the current Arazzo document. The list MUST NOT include duplicate failure actions. | +| outputs | Map[`string`, {expression} \| [Selector Object](#selector-object)] | A map between a friendly name and a dynamic output value defined using a [Runtime Expression](#runtime-expressions) or [Selector Object](#selector-object). The name MUST use keys that match the regular expression: `^[a-zA-Z0-9\.\-_]+$`. | +| timeout | `integer` | The maximum number of milli-seconds to wait for the step to complete before aborting and failing the step. Consequently this will fail the workflow unless failureActions are defined. | +| correlationId | `string` | A correlationId in AsyncAPI links a request with its response (or more broadly, to trace a single logical transaction across multiple asynchronous messages). Only applicable to `asyncapi` steps with action `receive` and has to be in-sync with correlationId defined in the AsyncAPI document. | +| action | `send or receive` | Describes the intent of the message flow. Indicates whether the step will send (publish) or receive (subscribe) to a message on a channel described in an AsyncAPI document, Only applicable for `asyncapi` steps. | +| dependsOn | List[`string`] | A list of steps that MUST be completed before this step can be executed. Each value provided MUST be a `stepdId`. The keys must follow the regular expression: `^\$steps.$`. | This object MAY be extended with [Specification Extensions](#specification-extensions). @@ -379,6 +413,32 @@ steps: availablePets: $response.body ``` +An async step example: + +```yaml +- stepId: placeOrder + description: This step demonstrates the action of sending a message payload to place an order + operationId: $sourceDescriptions.asyncOrderApi.placeOrder + action: send + parameters: + - name: requestId + in: header + value: $inputs.correlationId + requestBody: + payload: + productId: $inputs.productDetails.productId + quantity: $inputs.productDetails.quantity +- stepId: confirmOrder + description: This step demonstrates the action of receiving a message payload to confirm an order + operationId: $sourceDescriptions.asyncOrderApi.confirmOrder + correlationId: $steps.placeOrder.outputs.requestId + action: receive + dependsOn: $steps.placeOrder + timeout: 6000 + outputs: + orderId: $message.payload.orderId +``` + #### Parameter Object Describes a single step parameter. A unique parameter is defined by the combination of a `name` and `in` fields. There are four possible locations specified by the `in` field: @@ -390,11 +450,11 @@ Describes a single step parameter. A unique parameter is defined by the combinat ##### Fixed Fields -| Field Name | Type | Description | -| --- | :---: | --- | -| name | `string` | **REQUIRED**. The name of the parameter. Parameter names are _case sensitive_. | -| in | `string` | The location of the parameter. Possible values are `"path"`, `"query"`, `"header"`, or `"cookie"`. When the step, success action, or failure action in context specifies a `workflowId`, then all parameters map to workflow inputs. In all other scenarios (e.g., a step specifies an `operationId`), the `in` field MUST be specified. | -| value | Any \| {expression} \| [Selector Object](#selector-object) | **REQUIRED**. The value to pass in the parameter. The value can be a constant, a [Runtime Expression](#runtime-expressions), or a [Selector Object](#selector-object) to be evaluated and passed to the referenced operation or workflow. | +| Field Name | Type | Description | +| ----------------------------------- | :--------------------------------------------------------: | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| name | `string` | **REQUIRED**. The name of the parameter. Parameter names are _case sensitive_. | +| in | `string` | The location of the parameter. Possible values are `"path"`, `"query"`, `"header"`, or `"cookie"`. When the step, success action, or failure action in context specifies a `workflowId`, then all parameters map to workflow inputs. In all other scenarios (e.g., a step specifies an `operationId`), the `in` field MUST be specified. | +| value | Any \| {expression} \| [Selector Object](#selector-object) | **REQUIRED**. The value to pass in the parameter. The value can be a constant, a [Runtime Expression](#runtime-expressions), or a [Selector Object](#selector-object) to be evaluated and passed to the referenced operation or workflow. | This object MAY be extended with [Specification Extensions](#specification-extensions). @@ -430,14 +490,14 @@ A single success action which describes an action to take upon success of a work ##### Fixed Fields -| Field Name | Type | Description | -| --- | :---: | --- | -| name | `string` | **REQUIRED**. The name of the success action. Names are _case sensitive_. | -| type | `string` | **REQUIRED**. The type of action to take. Possible values are `"end"` or `"goto"`. | -| workflowId | `string` | The [workflowId](#fixed-fields-2) referencing an existing workflow within the Arazzo Description to transfer to upon success of the step. This field is only relevant when the `type` field value is `"goto"`. If the referenced workflow is contained within an `arazzo` type `sourceDescription`, then the `workflowId` MUST be specified using a [Runtime Expression](#runtime-expressions) (e.g., `$sourceDescriptions..`) to avoid ambiguity or potential clashes. This field is mutually exclusive to `stepId`. | -| stepId | `string` | The `stepId` to transfer to upon success of the step. This field is only relevant when the `type` field value is `"goto"`. The referenced `stepId` MUST be within the current workflow. This field is mutually exclusive to `workflowId`. | -| parameters | [[Parameter Object](#parameter-object) \| [Reusable Object](#reusable-object)] | A list of parameters that MUST be passed to a workflow as referenced by `workflowId`. If a Reusable Object is provided, it MUST link to a parameter defined in the [components/parameters](#components-object) of the current Arazzo document. The list MUST NOT include duplicate parameters. The `in` field MUST NOT be used. | -| criteria | [[Criterion Object](#criterion-object)] | A list of assertions to determine if this action SHALL be executed. Each assertion is described using a [Criterion Object](#criterion-object). All criteria assertions `MUST` be satisfied for the action to be executed. | +| Field Name | Type | Description | +| ------------------------------------------- | :----------------------------------------------------------------------------: | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| name | `string` | **REQUIRED**. The name of the success action. Names are _case sensitive_. | +| type | `string` | **REQUIRED**. The type of action to take. Possible values are `"end"` or `"goto"`. | +| workflowId | `string` | The [workflowId](#fixed-fields-2) referencing an existing workflow within the Arazzo Description to transfer to upon success of the step. This field is only relevant when the `type` field value is `"goto"`. If the referenced workflow is contained within an `arazzo` type `sourceDescription`, then the `workflowId` MUST be specified using a [Runtime Expression](#runtime-expressions) (e.g., `$sourceDescriptions..`) to avoid ambiguity or potential clashes. This field is mutually exclusive to `stepId`. | +| stepId | `string` | The `stepId` to transfer to upon success of the step. This field is only relevant when the `type` field value is `"goto"`. The referenced `stepId` MUST be within the current workflow. This field is mutually exclusive to `workflowId`. | +| parameters | [[Parameter Object](#parameter-object) \| [Reusable Object](#reusable-object)] | A list of parameters that MUST be passed to a workflow as referenced by `workflowId`. If a Reusable Object is provided, it MUST link to a parameter defined in the [components/parameters](#components-object) of the current Arazzo document. The list MUST NOT include duplicate parameters. The `in` field MUST NOT be used. | +| criteria | [[Criterion Object](#criterion-object)] | A list of assertions to determine if this action SHALL be executed. Each assertion is described using a [Criterion Object](#criterion-object). All criteria assertions `MUST` be satisfied for the action to be executed. | This object MAY be extended with [Specification Extensions](#specification-extensions). @@ -464,17 +524,16 @@ A single failure action which describes an action to take upon failure of a work ##### Fixed Fields -| Field Name | Type | Description | -| --- | :---: | --- | -| name | `string` | **REQUIRED**. The name of the failure action. Names are _case sensitive_. | -| type | `string` | **REQUIRED**. The type of action to take. Possible values are `"end"`, `"retry"`, or `"goto"`. | -| workflowId | `string` | The [workflowId](#fixed-fields-2) referencing an existing workflow within the Arazzo Description to transfer to upon failure of the step. This field is only relevant when the `type` field value is `"goto"` or `"retry"`. If the referenced workflow is contained within an `arazzo` type `sourceDescription`, then the `workflowId` MUST be specified using a [Runtime Expression](#runtime-expressions) (e.g., `$sourceDescriptions..`) to avoid ambiguity or potential clashes. This field is mutually exclusive to `stepId`. When used with `"retry"`, context transfers back upon completion of the specified workflow. | -| stepId | `string` | The `stepId` to transfer to upon failure of the step. This field is only relevant when the `type` field value is `"goto"` or `"retry"`. The referenced `stepId` MUST be within the current workflow. This field is mutually exclusive to `workflowId`. When used with `"retry"`, context transfers back upon completion of the specified step. | -| parameters | [[Parameter Object](#parameter-object) \| [Reusable Object](#reusable-object)] | A list of parameters that MUST be passed to a workflow as referenced by `workflowId`. If a Reusable Object is provided, it MUST link to a parameter defined in the [components/parameters](#components-object) of the current Arazzo document. The list MUST NOT include duplicate parameters. The `in` field MUST NOT be used. | -| retryAfter | `number` | A non-negative decimal indicating the seconds to delay after the step failure before another attempt SHALL be made. **Note:** if an HTTP [Retry-After](https://tools.ietf.org/html/rfc9110.html#name-retry-after) response header was returned to a step from a targeted operation, then it SHOULD overrule this particular field value. This field only applies when the `type` field value is `"retry"`. | -| retryLimit | `integer` | A non-negative integer indicating how many attempts to retry the step MAY be attempted before failing the overall step. If not specified then a single retry SHALL be attempted. This field only applies when the `type` field value is `"retry"`. The `retryLimit` MUST be exhausted prior to executing subsequent failure actions. | -| criteria | [[Criterion Object](#criterion-object)] | A list of assertions to determine if this action SHALL be executed. Each assertion is described using a [Criterion Object](#criterion-object). | - +| Field Name | Type | Description | +| ------------------------------------------- | :----------------------------------------------------------------------------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| name | `string` | **REQUIRED**. The name of the failure action. Names are _case sensitive_. | +| type | `string` | **REQUIRED**. The type of action to take. Possible values are `"end"`, `"retry"`, or `"goto"`. | +| workflowId | `string` | The [workflowId](#fixed-fields-2) referencing an existing workflow within the Arazzo Description to transfer to upon failure of the step. This field is only relevant when the `type` field value is `"goto"` or `"retry"`. If the referenced workflow is contained within an `arazzo` type `sourceDescription`, then the `workflowId` MUST be specified using a [Runtime Expression](#runtime-expressions) (e.g., `$sourceDescriptions..`) to avoid ambiguity or potential clashes. This field is mutually exclusive to `stepId`. When used with `"retry"`, context transfers back upon completion of the specified workflow. | +| stepId | `string` | The `stepId` to transfer to upon failure of the step. This field is only relevant when the `type` field value is `"goto"` or `"retry"`. The referenced `stepId` MUST be within the current workflow. This field is mutually exclusive to `workflowId`. When used with `"retry"`, context transfers back upon completion of the specified step. | +| parameters | [[Parameter Object](#parameter-object) \| [Reusable Object](#reusable-object)] | A list of parameters that MUST be passed to a workflow as referenced by `workflowId`. If a Reusable Object is provided, it MUST link to a parameter defined in the [components/parameters](#components-object) of the current Arazzo document. The list MUST NOT include duplicate parameters. The `in` field MUST NOT be used. | +| retryAfter | `number` | A non-negative decimal indicating the seconds to delay after the step failure before another attempt SHALL be made. **Note:** if an HTTP [Retry-After](https://tools.ietf.org/html/rfc9110.html#name-retry-after) response header was returned to a step from a targeted operation, then it SHOULD overrule this particular field value. This field only applies when the `type` field value is `"retry"`. | +| retryLimit | `integer` | A non-negative integer indicating how many attempts to retry the step MAY be attempted before failing the overall step. If not specified then a single retry SHALL be attempted. This field only applies when the `type` field value is `"retry"`. The `retryLimit` MUST be exhausted prior to executing subsequent failure actions. | +| criteria | [[Criterion Object](#criterion-object)] | A list of assertions to determine if this action SHALL be executed. Each assertion is described using a [Criterion Object](#criterion-object). | This object MAY be extended with [Specification Extensions](#specification-extensions). @@ -498,12 +557,12 @@ Components are scoped to the Arazzo document they are defined in. For example, i ##### Fixed Fields -| Field Name | Type | Description | -| --- | :--- | --- | -| inputs | Map[`string`, `JSON Schema`] | An object to hold reusable JSON Schema objects to be referenced from workflow inputs. | -| parameters | Map[`string`, [Parameter Object](#parameter-object)] | An object to hold reusable Parameter Objects | -| successActions | Map[`string`, [Success Action Object](#success-action-object)] | An object to hold reusable Success Actions Objects. | -| failureActions | Map[`string`, [Failure Action Object](#failure-action-object)] | An object to hold reusable Failure Actions Objects. | +| Field Name | Type | Description | +| ---------------------------------------------------- | :------------------------------------------------------------- | ------------------------------------------------------------------------------------- | +| inputs | Map[`string`, `JSON Schema`] | An object to hold reusable JSON Schema objects to be referenced from workflow inputs. | +| parameters | Map[`string`, [Parameter Object](#parameter-object)] | An object to hold reusable Parameter Objects | +| successActions | Map[`string`, [Success Action Object](#success-action-object)] | An object to hold reusable Success Actions Objects. | +| failureActions | Map[`string`, [Failure Action Object](#failure-action-object)] | An object to hold reusable Failure Actions Objects. | This object MAY be extended with [Specification Extensions](#specification-extensions). @@ -599,10 +658,10 @@ A simple object to allow referencing of objects contained within the [Components ##### Fixed Fields -| Field Name | Type | Description | -| --- | :---: | --- | -| reference | `{expression}` | **REQUIRED**. A [Runtime Expression](#runtime-expressions) used to reference the desired object. | -| value | `string` | Sets a value of the referenced parameter. This is only applicable for parameter object references. | +| Field Name | Type | Description | +| ----------------------------------------------- | :------------: | -------------------------------------------------------------------------------------------------- | +| reference | `{expression}` | **REQUIRED**. A [Runtime Expression](#runtime-expressions) used to reference the desired object. | +| value | `string` | Sets a value of the referenced parameter. This is only applicable for parameter object references. | This object cannot be extended with additional properties and any properties added MUST be ignored. @@ -645,39 +704,39 @@ There are four flavors of conditions supported: As part of a condition expression, you can use `boolean`, `null`, `number`, or `string` data types. -| Type | Literal value | -| --- | --- | -| `boolean` | `true` or `false` | -| `null` | `null` | -| `number` | Any number format supported in [Data Types](#data-types). | -| `string` | Strings MUST use single quotes (') around the string. To use a literal single quote, escape the literal single quote using an additional single quote (''). | +| Type | Literal value | +| --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `boolean` | `true` or `false` | +| `null` | `null` | +| `number` | Any number format supported in [Data Types](#data-types). | +| `string` | Strings MUST use single quotes (') around the string. To use a literal single quote, escape the literal single quote using an additional single quote (''). | ##### Operators -| Operator | Description | -| --- | --- | -| `<` | Less than | -| `<=` | Less than or equal | -| `>` | Greater than | -| `>=` | Greater than or equal | -| `==` | Equal | -| `!=` | Not equal | -| `!` | Not | -| `&&` | And | -| \|\| | Or | -| `()` | Logical Grouping | -| `[]` | Index (0-based) | -| `.` | Property de-reference | +| Operator | Description | +| ----------------- | --------------------- | +| `<` | Less than | +| `<=` | Less than or equal | +| `>` | Greater than | +| `>=` | Greater than or equal | +| `==` | Equal | +| `!=` | Not equal | +| `!` | Not | +| `&&` | And | +| \|\| | Or | +| `()` | Logical Grouping | +| `[]` | Index (0-based) | +| `.` | Property de-reference | String comparisons `MUST` be case insensitive. ##### Fixed Fields -| Field Name | Type | Description | -| --- | :---: | --- | -| context | `{expression}` | A [Runtime Expression](#runtime-expressions) used to set the context for the condition to be applied on. If `type` is specified, then the `context` MUST be provided (e.g. `$response.body` would set the context that a JSONPath query expression could be applied to). | -| condition | `string` | **REQUIRED**. The condition to apply. Conditions can be simple (e.g. `$statusCode == 200` which applies an operator on a value obtained from a runtime expression), or a regex, or a JSONPath expression. For regex or JSONPath, the `type` and `context` MUST be specified. | -| type | `string` \| [Expression Type Object](#expression-type-object) | The type of condition to be applied. If specified, the options allowed are `simple`, `regex`, `jsonpath` or `xpath`. If omitted, then the condition is assumed to be `simple`, which at most combines literals, operators and [Runtime Expressions](#runtime-expressions). If `jsonpath`, then the expression MUST conform to [JSONPath](https://tools.ietf.org/html/rfc9535). If `xpath` the expression MUST conform to [XML Path Language 3.1](https://www.w3.org/TR/xpath-31/#d2e24229). Should other variants of JSONPath or XPath be required, then a [Expression Type Object](#expression-type-object) MUST be specified. | +| Field Name | Type | Description | +| ------------------------------------------ | :-----------------------------------------------------------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| context | `{expression}` | A [Runtime Expression](#runtime-expressions) used to set the context for the condition to be applied on. If `type` is specified, then the `context` MUST be provided (e.g. `$response.body` would set the context that a JSONPath query expression could be applied to). | +| condition | `string` | **REQUIRED**. The condition to apply. Conditions can be simple (e.g. `$statusCode == 200` which applies an operator on a value obtained from a runtime expression), or a regex, or a JSONPath expression. For regex or JSONPath, the `type` and `context` MUST be specified. | +| type | `string` \| [Expression Type Object](#expression-type-object) | The type of condition to be applied. If specified, the options allowed are `simple`, `regex`, `jsonpath` or `xpath`. If omitted, then the condition is assumed to be `simple`, which at most combines literals, operators and [Runtime Expressions](#runtime-expressions). If `jsonpath`, then the expression MUST conform to [JSONPath](https://tools.ietf.org/html/rfc9535). If `xpath` the expression MUST conform to [XML Path Language 3.1](https://www.w3.org/TR/xpath-31/#d2e24229). Should other variants of JSONPath or XPath be required, then a [Expression Type Object](#expression-type-object) MUST be specified. | This object MAY be extended with [Specification Extensions](#specification-extensions). @@ -713,18 +772,18 @@ Defining this object gives the ability to utilize tooling compatible with older ##### Fixed Fields -| Field Name | Type | Description | -| --- | :---: | --- | -| type | `string` | **REQUIRED**. The selector type. The options allowed are `jsonpath`, `xpath`, or `jsonpointer`. | +| Field Name | Type | Description | +| --------------------------------------- | :------: | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| type | `string` | **REQUIRED**. The selector type. The options allowed are `jsonpath`, `xpath`, or `jsonpointer`. | | version | `string` | **REQUIRED**. A short hand string representing the version of the expression type being used. The allowed values for JSONPath are `rfc9535` or `draft-goessner-dispatch-jsonpath-00`. The allowed values for XPath are `xpath-30`, `xpath-20`, or `xpath-10`. The allowed value for JSON Pointer is `rfc6901`. | The supported expression selector types and versions are as follows: -| Type | Allowed Versions | Default | -| ---- | --- | --- | -| `jsonpath` | `rfc9535`, `draft-goessner-dispatch-jsonpath-00` | `rfc9535` | -| `xpath` | `xpath-31`, `xpath-30`, `xpath-20`, `xpath-10` | `xpath-31` | -| `jsonpointer` | `rfc6901` (added for completeness) | `rfc6901` | +| Type | Allowed Versions | Default | +| ------------- | ------------------------------------------------ | ---------- | +| `jsonpath` | `rfc9535`, `draft-goessner-dispatch-jsonpath-00` | `rfc9535` | +| `xpath` | `xpath-31`, `xpath-30`, `xpath-20`, `xpath-10` | `xpath-31` | +| `jsonpointer` | `rfc6901` (added for completeness) | `rfc6901` | If this object is not defined, the default version for the selector type MUST be used. @@ -791,11 +850,11 @@ A single request body describing the `Content-Type` and request body content to ##### Fixed Fields -| Field Name | Type | Description | -| --- | :---: | --- | -| contentType | `string` | The Content-Type for the request content. If omitted then refer to Content-Type specified at the targeted operation to understand serialization requirements. | -| payload | Any | A value representing the request body payload. The value can be a literal value or can contain [Runtime Expressions](#runtime-expressions) or [Selector Objects](#selector-object) which MUST be evaluated prior to calling the referenced operation. To represent examples of media types that cannot be naturally represented in JSON or YAML, use a string value to contain the example, escaping where necessary. | -| replacements | [[Payload Replacement Object](#payload-replacement-object)] | A list of locations and values to set within a payload. | +| Field Name | Type | Description | +| -------------------------------------------------- | :---------------------------------------------------------: | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| contentType | `string` | The Content-Type for the request content. If omitted then refer to Content-Type specified at the targeted operation to understand serialization requirements. | +| payload | Any | A value representing the request body payload. The value can be a literal value or can contain [Runtime Expressions](#runtime-expressions) or [Selector Objects](#selector-object) which MUST be evaluated prior to calling the referenced operation. To represent examples of media types that cannot be naturally represented in JSON or YAML, use a string value to contain the example, escaping where necessary. | +| replacements | [[Payload Replacement Object](#payload-replacement-object)] | A list of locations and values to set within a payload. | This object MAY be extended with [Specification Extensions](#specification-extensions). @@ -877,11 +936,11 @@ Describes a location within a payload (e.g., a request body) and a value to set ##### Fixed Fields -| Field Name | Type | Description | -| --- | :---: | --- | -| target | `string` | **REQUIRED**. A [JSON Pointer](https://tools.ietf.org/html/rfc6901), or [XPath Expression](https://www.w3.org/TR/xpath-31/#id-expressions), or [JSONPath](https://tools.ietf.org/html/rfc9535) which MUST be resolved against the request body. Used to identify the location to inject the `value`. | +| Field Name | Type | Description | +| --------------------------------------------------------------------- | :-----------------------------------------------------------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| target | `string` | **REQUIRED**. A [JSON Pointer](https://tools.ietf.org/html/rfc6901), or [XPath Expression](https://www.w3.org/TR/xpath-31/#id-expressions), or [JSONPath](https://tools.ietf.org/html/rfc9535) which MUST be resolved against the request body. Used to identify the location to inject the `value`. | | targetSelectorType | `string` \| [Expression Type Object](#expression-type-object) | The selector expression type to use (e.g., `jsonpath`, `xpath`, or `jsonpointer`). If `jsonpath`, then the `target` expression MUST conform to [JSONPath](https://tools.ietf.org/html/rfc9535). If `xpath` the expression MUST conform to [XML Path Language 3.1](https://www.w3.org/TR/xpath-31/#d2e24229). Should other variants of JSONPath or XPath be required, then a [Expression Type Object](#expression-type-object) MUST be specified. | -| value | Any \| {expression} \| [Selector Object](#selector-object) | **REQUIRED**. The value set within the target location. The value can be a constant, a [Runtime Expression](#runtime-expressions), or [Selector Objects](#selector-object) to be evaluated and passed to the referenced operation or workflow. | +| value | Any \| {expression} \| [Selector Object](#selector-object) | **REQUIRED**. The value set within the target location. The value can be a constant, a [Runtime Expression](#runtime-expressions), or [Selector Objects](#selector-object) to be evaluated and passed to the referenced operation or workflow. | If `targetSelectorType` is omitted, then: @@ -939,13 +998,14 @@ A runtime expression allows values to be defined based on information that will The runtime expression is defined by the following [ABNF](https://tools.ietf.org/html/rfc5234) syntax: ```abnf - expression = ( "$url" / "$method" / "$statusCode" / "$request." source / "$response." source / "$inputs." name / "$outputs." name / "$steps." name / "$workflows." name / "$sourceDescriptions." name / "$components." name / "$components.parameters." parameter-name) + expression = ( "$url" / "$method" / "$statusCode" / "$request." source / "$response." source / "$message." source / "$inputs." name / "$outputs." name / "$steps." name / "$workflows." name / "$sourceDescriptions." name / "$components." name / "$components.parameters." parameter-name) parameter-name = name ; Reuses 'name' rule for parameter names - source = ( header-reference / query-reference / path-reference / body-reference ) + source = ( header-reference / query-reference / path-reference / body-reference / payload-reference ) header-reference = "header." token query-reference = "query." name path-reference = "path." name body-reference = "body" ["#" json-pointer ] + payload-reference = "payload" ["#" json-pointer ] json-pointer = *( "/" reference-token ) reference-token = *( unescaped / escaped ) unescaped = %x00-2E / %x30-7D / %x7F-10FFFF @@ -960,19 +1020,21 @@ The runtime expression is defined by the following [ABNF](https://tools.ietf.org #### Examples -| Source Location | example expression | notes | -| --- | :--- | :--- | -| HTTP Method | `$method` | The allowable values for the `$method` will be those for the HTTP operation. | -| Requested media type | `$request.header.accept` | | -| Request parameter | `$request.path.id` | Request parameters MUST be declared in the `parameters` section of the parent operation or they cannot be evaluated. This includes request headers. | -| Request body property | `$request.body#/user/uuid` | In operations which accept payloads, references may be made to portions of the `requestBody` or the entire body. | -| Request URL | `$url` | | -| Response value | `$response.body#/status` | In operations which return payloads, references may be made to portions of the response body or the entire body. | -| Response header | `$response.header.Server` | Single header values only are available. | -| workflow input | `$inputs.username` or `$workflows.foo.inputs.username` | Single input values only are available. | -| Step output value | `$steps.someStepId.outputs.pets` | In situations where the output named property return payloads, references may be made to portions of the response body (e.g., `$steps.someStepId.outputs.pets#/0/id`) or the entire body. | -| Workflow output value | `$outputs.bar` or `$workflows.foo.outputs.bar` | In situations where the output named property return payloads, references may be made to portions of the response body (e.g., `$workflows.foo.outputs.mappedResponse#/name`) or the entire body. | -| Components parameter | `$components.parameters.foo` | Accesses a foo parameter defined within the Components Object. | +| Source Location | example expression | notes | +| --------------------- | :----------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| HTTP Method | `$method` | The allowable values for the `$method` will be those for the HTTP operation. | +| Requested media type | `$request.header.accept` | | +| Request parameter | `$request.path.id` | Request parameters MUST be declared in the `parameters` section of the parent operation or they cannot be evaluated. This includes request headers. | +| Request body property | `$request.body#/user/uuid` | In operations which accept payloads, references may be made to portions of the `requestBody` or the entire body. | +| Request URL | `$url` | | +| Response value | `$response.body#/status` | In operations which return payloads, references may be made to portions of the response body or the entire body. | +| Response header | `$response.header.Server` | Single header values only are available. | +| Message header | `$message.header.Server` | Single header values only are available. | +| Payload value | `$message.payload#/status` | In operations which return payloads, references may be made to portions of the payload or the entire payload. | +| workflow input | `$inputs.username` or `$workflows.foo.inputs.username` | Single input values only are available. | +| Step output value | `$steps.someStepId.outputs.pets` | In situations where the output named property return payloads, references may be made to portions of the response body (e.g., `$steps.someStepId.outputs.pets#/0/id`) or the entire body. | +| Workflow output value | `$outputs.bar` or `$workflows.foo.outputs.bar` | In situations where the output named property return payloads, references may be made to portions of the response body (e.g., `$workflows.foo.outputs.mappedResponse#/name`) or the entire body. | +| Components parameter | `$components.parameters.foo` | Accesses a foo parameter defined within the Components Object. | Runtime expressions preserve the type of the referenced value. Expressions can be embedded into string values by surrounding the expression with `{}` curly braces. @@ -984,9 +1046,9 @@ While the Arazzo Specification tries to accommodate most use cases, additional d The extension properties are implemented as patterned fields that are always prefixed by `"x-"`. -| Field Pattern | Type | Description | -| --- | :---: | --- | -| ^x- | Any | Allows extensions to the Arazzo Specification. The field name MUST begin with `x-`, for example, `x-internal-id`. Field names beginning `x-oai-`, `x-oas-`, and `x-arazzo` are reserved for uses defined by the [OpenAPI Initiative](https://www.openapis.org/). The value MAY be `null`, a primitive, an array or an object. | +| Field Pattern | Type | Description | +| ---------------------------------- | :--: | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| ^x- | Any | Allows extensions to the Arazzo Specification. The field name MUST begin with `x-`, for example, `x-internal-id`. Field names beginning `x-oai-`, `x-oas-`, and `x-arazzo` are reserved for uses defined by the [OpenAPI Initiative](https://www.openapis.org/). The value MAY be `null`, a primitive, an array or an object. | The extensions may or may not be supported by the available tooling, but those may be extended as well to add requested support (if tools are internal or open-sourced). @@ -1060,7 +1122,8 @@ The proposed MIME media type for Arazzo documents (e.g. workflows) that require ## Appendix A: Revision History -| Version | Date | Notes | -| --- | --- | --- | -| 1.0.1 | 2025-01-16 | Patch release of the Arazzo Specification 1.0.1 | -| 1.0.0 | 2024-05-29 | First release of the Arazzo Specification | +| Version | Date | Notes | +|---------|------------|-------------------------------------------------| +| 1.1.0 | 2025-12-08 | Minor release of the Arazzo Specification 1.1.0 | +| 1.0.1 | 2025-01-16 | Patch release of the Arazzo Specification 1.0.1 | +| 1.0.0 | 2024-05-29 | First release of the Arazzo Specification | diff --git a/src/specifications/pet-asyncapi.yaml b/src/specifications/pet-asyncapi.yaml new file mode 100644 index 0000000..695139d --- /dev/null +++ b/src/specifications/pet-asyncapi.yaml @@ -0,0 +1,81 @@ +asyncapi: 3.0.0 + +info: + title: Simple Pet Purchase API + version: "1.0.0" + +servers: + localKafka: + host: localhost:9092 + protocol: kafka + +channels: + place-order: + address: place-order + messages: + placeOrder.message: + $ref: "#/components/messages/OrderRequest" + + confirm-order: + address: confirm-order + messages: + confirmOrder.message: + $ref: "#/components/messages/OrderResponse" + +operations: + placeOrder: + description: Place an order + action: receive + channel: + $ref: "#/channels/place-order" + messages: + - $ref: "#/channels/place-order/messages/placeOrder.message" + reply: + channel: + $ref: "#/channels/confirm-order" + messages: + - $ref: "#/channels/confirm-order/messages/confirmOrder.message" + +components: + messages: + OrderRequest: + contentType: application/json + correlationId: + description: Identifier that correlates this request with a response + location: "$message.header#/orderRequestId" + headers: + type: object + required: + - orderRequestId + properties: + orderRequestId: + type: string + description: Unique ID for tracking the order flow + payload: + type: object + required: + - petId + properties: + petId: + type: integer + + OrderResponse: + contentType: application/json + correlationId: + description: Identifier that correlates this response with a request + location: "$message.header#/orderRequestId" + headers: + type: object + required: + - orderRequestId + properties: + orderRequestId: + type: string + description: Unique ID for tracking the order flow + payload: + type: object + required: + - orderId + properties: + orderId: + type: integer \ No newline at end of file From 37d911f7fb6ae57cd23ec8df25ac5096369fe426 Mon Sep 17 00:00:00 2001 From: Naresh Jain Date: Tue, 16 Dec 2025 13:07:50 +0530 Subject: [PATCH 03/21] fix: update operationId and correlationId references in arazzo.md AND add pattern for dependsOn in schema.yaml to clarify that it can ref to a step from another workflow --- src/arazzo.md | 8 ++++---- src/schemas/validation/schema.yaml | 11 +++-------- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/src/arazzo.md b/src/arazzo.md index c2bc2cd..3555d51 100644 --- a/src/arazzo.md +++ b/src/arazzo.md @@ -151,7 +151,7 @@ workflows: steps: - stepId: loginStep description: This step demonstrates the user login step - operationId: loginUser + operationId: $sourceDescriptions.petstoreDescription.loginUser parameters: # parameters to inject into the loginUser operation (parameter name must be resolvable at the referenced operation and the value is determined using {expression} syntax) - name: username @@ -328,7 +328,7 @@ Describes a single workflow step which MAY be a call to an API operation ([OpenA ##### Fixed Fields | Field Name | Type | Description | -| ------------------------------------------------- | :--------------------------------------------------------------------------------------: | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| ------------------------------------------------- | :--------------------------------------------------------------------------------------: |-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | description | `string` | A description of the step. [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation. | | stepId | `string` | **REQUIRED**. Unique string to represent the step. The `stepId` MUST be unique amongst all steps described in the workflow. The `stepId` value is **case-sensitive**. Tools and libraries MAY use the `stepId` to uniquely identify a workflow step, therefore, it is RECOMMENDED to follow common programming naming conventions. SHOULD conform to the regular expression `[A-Za-z0-9_\-]+`. | | operationId | `string` | The name of an existing, resolvable operation, as defined with a unique `operationId` and existing within one of the `sourceDescriptions`. The referenced operation will be invoked by this workflow step. If multiple (non `arazzo` type) `sourceDescriptions` are defined, then the `operationId` MUST be specified using a [Runtime Expression](#runtime-expressions) (e.g., `$sourceDescriptions..`) to avoid ambiguity or potential clashes. This field is mutually exclusive of the `operationPath` and `workflowId` fields respectively. | @@ -344,7 +344,7 @@ Describes a single workflow step which MAY be a call to an API operation ([OpenA | timeout | `integer` | The maximum number of milli-seconds to wait for the step to complete before aborting and failing the step. Consequently this will fail the workflow unless failureActions are defined. | | correlationId | `string` | A correlationId in AsyncAPI links a request with its response (or more broadly, to trace a single logical transaction across multiple asynchronous messages). Only applicable to `asyncapi` steps with action `receive` and has to be in-sync with correlationId defined in the AsyncAPI document. | | action | `send or receive` | Describes the intent of the message flow. Indicates whether the step will send (publish) or receive (subscribe) to a message on a channel described in an AsyncAPI document, Only applicable for `asyncapi` steps. | -| dependsOn | List[`string`] | A list of steps that MUST be completed before this step can be executed. Each value provided MUST be a `stepdId`. The keys must follow the regular expression: `^\$steps.$`. | +| dependsOn | List[`string`] | A list of steps that MUST be completed before this step can be executed. Each value provided MUST be a `stepdId`. If you depend on a step from another workflow, you MUST use the full reference format with the workflow id. The keys MUST follow the regular expression: `^\$(?:workflows\.[^.]+\.)?steps\.[^.]+$`. | This object MAY be extended with [Specification Extensions](#specification-extensions). @@ -431,7 +431,7 @@ An async step example: - stepId: confirmOrder description: This step demonstrates the action of receiving a message payload to confirm an order operationId: $sourceDescriptions.asyncOrderApi.confirmOrder - correlationId: $steps.placeOrder.outputs.requestId + correlationId: $inputs.correlationId action: receive dependsOn: $steps.placeOrder timeout: 6000 diff --git a/src/schemas/validation/schema.yaml b/src/schemas/validation/schema.yaml index 61d054a..a595d41 100644 --- a/src/schemas/validation/schema.yaml +++ b/src/schemas/validation/schema.yaml @@ -179,18 +179,13 @@ $defs: description: The duration in milliseconds to wait before timing out the step type: integer dependsOn: - description: Specifies a list of step identifiers that must complete (or be waited for) before the current step can begin execution + description: Specifies a list of step identifiers that must complete (or be waited for) before the current step can begin execution. If you depend on a step from another workflow, you MUST use the full reference format with the workflow id. type: array uniqueItems: true minItems: 1 items: - $ref: '#stepId' - operationPath: - description: A reference to a Source combined with a JSON Pointer to reference an operation - type: string - workflowId: - description: The workflowId referencing an existing workflow within the Arazzo description - $ref: '#workflowId' + type: string + pattern: ^\\$(?:workflows\\.[^.]+\\.)?steps\\.[^.]+$ parameters: description: A list of parameters that MUST be passed to an operation or workflow as referenced by operationId, operationPath, or workflowId type: array From 75d1cb051c76ee7d15142a2db8ca2d81056c5775 Mon Sep 17 00:00:00 2001 From: Naresh Jain Date: Wed, 4 Feb 2026 19:52:57 +0530 Subject: [PATCH 04/21] fix: enhance dependsOn description in schema.yaml and arazzo.md, and add new AsyncAPI examples for test --- src/arazzo.md | 2 +- src/schemas/validation/schema.yaml | 8 +- ...el-path-is-invalid-for-openapi.arazzo.yaml | 13 ++ ...relation-id-non-receive-action.arazzo.yaml | 15 ++ tests/schema/fail/invalid-async.arazzo.yaml | 14 ++ ...relation-id-for-receive-action.arazzo.yaml | 15 ++ .../schema/pass/async-depends-on.arazzo.yaml | 39 ++++++ .../pass/async-with-channel-path.arazzo.yaml | 15 ++ tests/schema/pass/minimal-async.arazzo.yaml | 14 ++ .../pass/openapi-and-asyncapi.arazzo.yaml | 129 ++++++++++++++++++ 10 files changed, 260 insertions(+), 4 deletions(-) create mode 100644 tests/schema/fail/channel-path-is-invalid-for-openapi.arazzo.yaml create mode 100644 tests/schema/fail/invalid-async-correlation-id-non-receive-action.arazzo.yaml create mode 100644 tests/schema/fail/invalid-async.arazzo.yaml create mode 100644 tests/schema/pass/async-correlation-id-for-receive-action.arazzo.yaml create mode 100644 tests/schema/pass/async-depends-on.arazzo.yaml create mode 100644 tests/schema/pass/async-with-channel-path.arazzo.yaml create mode 100644 tests/schema/pass/minimal-async.arazzo.yaml create mode 100644 tests/schema/pass/openapi-and-asyncapi.arazzo.yaml diff --git a/src/arazzo.md b/src/arazzo.md index 3555d51..988e29c 100644 --- a/src/arazzo.md +++ b/src/arazzo.md @@ -344,7 +344,7 @@ Describes a single workflow step which MAY be a call to an API operation ([OpenA | timeout | `integer` | The maximum number of milli-seconds to wait for the step to complete before aborting and failing the step. Consequently this will fail the workflow unless failureActions are defined. | | correlationId | `string` | A correlationId in AsyncAPI links a request with its response (or more broadly, to trace a single logical transaction across multiple asynchronous messages). Only applicable to `asyncapi` steps with action `receive` and has to be in-sync with correlationId defined in the AsyncAPI document. | | action | `send or receive` | Describes the intent of the message flow. Indicates whether the step will send (publish) or receive (subscribe) to a message on a channel described in an AsyncAPI document, Only applicable for `asyncapi` steps. | -| dependsOn | List[`string`] | A list of steps that MUST be completed before this step can be executed. Each value provided MUST be a `stepdId`. If you depend on a step from another workflow, you MUST use the full reference format with the workflow id. The keys MUST follow the regular expression: `^\$(?:workflows\.[^.]+\.)?steps\.[^.]+$`. | +| dependsOn | List[`string`] | A list of steps that MUST be completed before this step can be executed. Each value provided MUST be a `stepdId`. If you depend on a step from another workflow, you MUST use the full reference format with the workflow id. The keys MUST follow the regular expression: `^\$(?:workflows\.[^.]+\.)?steps\.[^.]+$`. If your step depends on the output of a non-blocking/async step, then you SHOULD use dependsOn in your current step and reffer to the async step | This object MAY be extended with [Specification Extensions](#specification-extensions). diff --git a/src/schemas/validation/schema.yaml b/src/schemas/validation/schema.yaml index a595d41..07737c8 100644 --- a/src/schemas/validation/schema.yaml +++ b/src/schemas/validation/schema.yaml @@ -179,13 +179,13 @@ $defs: description: The duration in milliseconds to wait before timing out the step type: integer dependsOn: - description: Specifies a list of step identifiers that must complete (or be waited for) before the current step can begin execution. If you depend on a step from another workflow, you MUST use the full reference format with the workflow id. + description: Specifies a list of step identifiers that must complete (or be waited for) before the current step can begin execution. Steps referred by dependsOn SHOULD be non-blocking/async steps. If you depend on a step from another workflow, you MUST use the full reference format with the workflow id. type: array uniqueItems: true minItems: 1 items: type: string - pattern: ^\\$(?:workflows\\.[^.]+\\.)?steps\\.[^.]+$ + pattern: ^\$(?:workflows\.[^.]+\.)?steps\.[^.]+$ parameters: description: A list of parameters that MUST be passed to an operation or workflow as referenced by operationId, operationPath, or workflowId type: array @@ -254,10 +254,10 @@ $defs: parameters: items: oneOf: + - $ref: '#/$defs/reusable-object' - $ref: '#/$defs/parameter-object' required: - in - - $ref: '#/$defs/reusable-object' - oneOf: - required: - operationId @@ -341,6 +341,8 @@ $defs: - $ref: '#/$defs/reusable-object' required: - workflowId + $ref: '#/$defs/specification-extensions' + unevaluatedProperties: false request-body-object: $comment: https://spec.openapis.org/arazzo/v1.1#request-body-object description: The request body to pass to an operation as referenced by operationId or operationPath or channelPath diff --git a/tests/schema/fail/channel-path-is-invalid-for-openapi.arazzo.yaml b/tests/schema/fail/channel-path-is-invalid-for-openapi.arazzo.yaml new file mode 100644 index 0000000..25bd0e5 --- /dev/null +++ b/tests/schema/fail/channel-path-is-invalid-for-openapi.arazzo.yaml @@ -0,0 +1,13 @@ +arazzo: 1.1.0 +info: + title: Minimal Arazzo Example for AsyncAPI + version: 1.0.0 +sourceDescriptions: + - name: exampleAPI + url: https://example.com/openapi.yaml + type: openapi +workflows: + - workflowId: basicWorkflow + steps: + - stepId: step1 + channelPath: createUser \ No newline at end of file diff --git a/tests/schema/fail/invalid-async-correlation-id-non-receive-action.arazzo.yaml b/tests/schema/fail/invalid-async-correlation-id-non-receive-action.arazzo.yaml new file mode 100644 index 0000000..cfdd9a6 --- /dev/null +++ b/tests/schema/fail/invalid-async-correlation-id-non-receive-action.arazzo.yaml @@ -0,0 +1,15 @@ +arazzo: 1.1.0 +info: + title: Minimal Arazzo Example for AsyncAPI + version: 1.0.0 +sourceDescriptions: + - name: exampleAPI + url: https://example.com/asyncapi.yaml + type: asyncapi +workflows: + - workflowId: basicWorkflow + steps: + - stepId: step1 + operationId: createUser + action: send + correlationId: invalid \ No newline at end of file diff --git a/tests/schema/fail/invalid-async.arazzo.yaml b/tests/schema/fail/invalid-async.arazzo.yaml new file mode 100644 index 0000000..af42925 --- /dev/null +++ b/tests/schema/fail/invalid-async.arazzo.yaml @@ -0,0 +1,14 @@ +arazzo: 1.1.0 +info: + title: Minimal Arazzo Example for AsyncAPI + version: 1.0.0 +sourceDescriptions: + - name: exampleAPI + url: https://example.com/asyncapi.yaml + type: asyncapi +workflows: + - workflowId: basicWorkflow + steps: + - stepId: step1 + operationId: createUser + action: invalid diff --git a/tests/schema/pass/async-correlation-id-for-receive-action.arazzo.yaml b/tests/schema/pass/async-correlation-id-for-receive-action.arazzo.yaml new file mode 100644 index 0000000..a00b6df --- /dev/null +++ b/tests/schema/pass/async-correlation-id-for-receive-action.arazzo.yaml @@ -0,0 +1,15 @@ +arazzo: 1.1.0 +info: + title: Minimal Arazzo Example for AsyncAPI with Correlation ID for Receive Action + version: 1.0.0 +sourceDescriptions: + - name: exampleAPI + url: https://example.com/asyncapi.yaml + type: asyncapi +workflows: + - workflowId: basicWorkflow + steps: + - stepId: step1 + operationId: createUser + action: receive + correlationId: id123 \ No newline at end of file diff --git a/tests/schema/pass/async-depends-on.arazzo.yaml b/tests/schema/pass/async-depends-on.arazzo.yaml new file mode 100644 index 0000000..3128ff6 --- /dev/null +++ b/tests/schema/pass/async-depends-on.arazzo.yaml @@ -0,0 +1,39 @@ +arazzo: 1.1.0 +info: + title: Minimal Arazzo Example for AsyncAPI with Depends On + version: 1.0.0 +sourceDescriptions: + - name: exampleAPI + url: https://example.com/asyncapi.yaml + type: asyncapi +workflows: + - workflowId: dependsOnWorkflow + steps: + - stepId: step1 + operationId: createUser + action: send + - stepId: step2 + operationId: fetchUserId + action: receive + correlationId: id123 + timeout: 6000 + outputs: + userId: "$message.payload.userId" + - stepId: step3 + operationId: updateUser + action: send + dependsOn: + - "$steps.step2" + parameters: + - name: userId + in: header + value: "$steps.fetchUserId.outputs.userId" + - stepId: step4 + operationId: deleteUser + action: send + dependsOn: + - "$workflows.dependsOnWorkflow.steps.step2" + parameters: + - name: userId + in: header + value: "$steps.fetchUserId.outputs.userId" \ No newline at end of file diff --git a/tests/schema/pass/async-with-channel-path.arazzo.yaml b/tests/schema/pass/async-with-channel-path.arazzo.yaml new file mode 100644 index 0000000..161ae85 --- /dev/null +++ b/tests/schema/pass/async-with-channel-path.arazzo.yaml @@ -0,0 +1,15 @@ +arazzo: 1.1.0 +info: + title: Minimal Arazzo Example for AsyncAPI + version: 1.0.0 +sourceDescriptions: + - name: exampleAPI + url: https://example.com/asyncapi.yaml + type: asyncapi +workflows: + - workflowId: basicWorkflow + steps: + - stepId: step1 + channelPath: createUser + action: receive + correlationId: id123 \ No newline at end of file diff --git a/tests/schema/pass/minimal-async.arazzo.yaml b/tests/schema/pass/minimal-async.arazzo.yaml new file mode 100644 index 0000000..a9da527 --- /dev/null +++ b/tests/schema/pass/minimal-async.arazzo.yaml @@ -0,0 +1,14 @@ +arazzo: 1.1.0 +info: + title: Minimal Arazzo Example for AsyncAPI + version: 1.0.0 +sourceDescriptions: + - name: exampleAPI + url: https://example.com/asyncapi.yaml + type: asyncapi +workflows: + - workflowId: basicWorkflow + steps: + - stepId: step1 + operationId: createUser + action: send diff --git a/tests/schema/pass/openapi-and-asyncapi.arazzo.yaml b/tests/schema/pass/openapi-and-asyncapi.arazzo.yaml new file mode 100644 index 0000000..34609a5 --- /dev/null +++ b/tests/schema/pass/openapi-and-asyncapi.arazzo.yaml @@ -0,0 +1,129 @@ +arazzo: "1.1.0" +info: + title: "Arazzo Workflow" + version: "1.1.0" +sourceDescriptions: +- name: "LocationApi" + url: "./workflow/openapi/location.yaml" + type: "openapi" +- name: "ProductApi" + url: "./workflow/openapi/product.yaml" + type: "openapi" +- name: "AsyncOrderApi" + url: "./workflow/asyncapi/order.yaml" + type: "asyncapi" +- name: "WarehouseApi" + url: "./workflow/openapi/warehouse.yaml" + type: "openapi" +- name: "OrderApi" + url: "./workflow/openapi/order.yaml" + type: "openapi" +workflows: +- workflowId: "OrderId" + inputs: + required: + - "createOrderSend" + - "getUserLocation" + type: "object" + properties: + createOrderSend: + required: + - "requestId" + type: "object" + properties: + requestId: + type: "string" + getUserLocation: + required: + - "userEmail" + type: "object" + properties: + userEmail: + type: "string" + format: "email" + steps: + - stepId: "getUserLocation" + operationId: "$sourceDescriptions.LocationApi.getUserLocation" + parameters: + - name: "userEmail" + in: "query" + value: "$inputs.getUserLocation.userEmail" + successCriteria: + - condition: "$statusCode == 200" + outputs: + userId: "$response.body#/userId" + locationCode: "$response.body#/locationCode" + - stepId: "getProducts" + operationId: "$sourceDescriptions.ProductApi.getProducts" + parameters: + - name: "locationCode" + in: "query" + value: "$steps.getUserLocation.outputs.locationCode" + successCriteria: + - condition: "$statusCode == 200" + onSuccess: + - name: "IsArrayEmpty" + type: "end" + criteria: + - condition: "$response.body#/0 == null" + outputs: + productId: "$response.body#/0/productId" + inventory: "$response.body#/0/inventory" + - stepId: "createOrderSend" + operationId: "$sourceDescriptions.AsyncOrderApi.createOrder" + action: "send" + parameters: + - name: "requestId" + in: "header" + value: "$inputs.createOrderSend.requestId" + requestBody: + payload: + userId: "$steps.getUserLocation.outputs.userId" + productId: "$steps.getProducts.outputs.productId" + inventory: "$steps.getProducts.outputs.inventory" + outputs: + requestId: "$message.header.requestId" + - stepId: "createOrderReceive" + operationId: "$sourceDescriptions.AsyncOrderApi.createOrder" + action: "receive" + correlationId: "$steps.createOrderSend.outputs.requestId" + timeout: 6000 + outputs: + orderId: "$message.payload.orderId" + - stepId: "reserveInventory" + operationId: "$sourceDescriptions.WarehouseApi.reserveInventory" + dependsOn: + - "$steps.createOrderReceive" + parameters: + - name: "orderId" + in: "query" + value: "$steps.createOrderReceive.outputs.orderId" + successCriteria: + - condition: "$statusCode == 200" + - stepId: "orderAccepted" + operationId: "$sourceDescriptions.AsyncOrderApi.orderAccepted" + action: "receive" + correlationId: "$steps.createOrderSend.outputs.requestId" + timeout: 6000 + - stepId: "outForDelivery" + operationId: "$sourceDescriptions.AsyncOrderApi.outForDelivery" + action: "send" + dependsOn: + - "$steps.createOrderReceive" + parameters: + - name: "requestId" + in: "header" + value: "$steps.createOrderSend.outputs.requestId" + requestBody: + payload: + orderId: "$steps.createOrderReceive.outputs.orderId" + - stepId: "getOrderDetails" + operationId: "$sourceDescriptions.OrderApi.getOrderDetails" + dependsOn: + - "$steps.createOrderReceive" + parameters: + - name: "orderId" + in: "path" + value: "$steps.createOrderReceive.outputs.orderId" + successCriteria: + - condition: "$statusCode == 200" \ No newline at end of file From ff0122759b3aaf40afe9f5029ae0686d789f2445 Mon Sep 17 00:00:00 2001 From: Naresh Jain Date: Wed, 4 Feb 2026 23:05:18 +0530 Subject: [PATCH 05/21] fix: update stepId in examples --- tests/schema/pass/async-depends-on.arazzo.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/schema/pass/async-depends-on.arazzo.yaml b/tests/schema/pass/async-depends-on.arazzo.yaml index 3128ff6..97e4983 100644 --- a/tests/schema/pass/async-depends-on.arazzo.yaml +++ b/tests/schema/pass/async-depends-on.arazzo.yaml @@ -27,7 +27,7 @@ workflows: parameters: - name: userId in: header - value: "$steps.fetchUserId.outputs.userId" + value: "$steps.step2.outputs.userId" - stepId: step4 operationId: deleteUser action: send @@ -36,4 +36,4 @@ workflows: parameters: - name: userId in: header - value: "$steps.fetchUserId.outputs.userId" \ No newline at end of file + value: "$steps.step2.outputs.userId" \ No newline at end of file From fd1bc7dd61fcfabf77ce96bec9433b9ffac80177 Mon Sep 17 00:00:00 2001 From: Naresh Jain Date: Sun, 15 Mar 2026 20:28:45 +0530 Subject: [PATCH 06/21] Apply suggestion from @frankkilcommins Co-authored-by: Frank Kilcommins --- src/arazzo.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arazzo.md b/src/arazzo.md index 988e29c..8fa67b9 100644 --- a/src/arazzo.md +++ b/src/arazzo.md @@ -344,7 +344,7 @@ Describes a single workflow step which MAY be a call to an API operation ([OpenA | timeout | `integer` | The maximum number of milli-seconds to wait for the step to complete before aborting and failing the step. Consequently this will fail the workflow unless failureActions are defined. | | correlationId | `string` | A correlationId in AsyncAPI links a request with its response (or more broadly, to trace a single logical transaction across multiple asynchronous messages). Only applicable to `asyncapi` steps with action `receive` and has to be in-sync with correlationId defined in the AsyncAPI document. | | action | `send or receive` | Describes the intent of the message flow. Indicates whether the step will send (publish) or receive (subscribe) to a message on a channel described in an AsyncAPI document, Only applicable for `asyncapi` steps. | -| dependsOn | List[`string`] | A list of steps that MUST be completed before this step can be executed. Each value provided MUST be a `stepdId`. If you depend on a step from another workflow, you MUST use the full reference format with the workflow id. The keys MUST follow the regular expression: `^\$(?:workflows\.[^.]+\.)?steps\.[^.]+$`. If your step depends on the output of a non-blocking/async step, then you SHOULD use dependsOn in your current step and reffer to the async step | +| dependsOn | List[`string`] | A list of steps that MUST be completed before this step can be executed. Each value provided MUST be a `stepId`. The `stepId` value is case-sensitive. If the step depended on is defined within the **current workflow**, specify the `stepId` directly (e.g., `authStep`). If the step is defined in a **different workflow within the current Arazzo Document**, reference it using `$workflows..steps.`. If the step is defined in a **separate Arazzo Document**, the workflow MUST be defined in `sourceDescriptions` and referenced using `$sourceDescriptions...steps.` to avoid ambiguity. If your step depends on the output of a non-blocking/asynchronous step, then you SHOULD use `dependsOn` and refer to the async step using one of these patterns. | This object MAY be extended with [Specification Extensions](#specification-extensions). From f53a80b3b04d346de2f5a80705e1bf115cb0f188 Mon Sep 17 00:00:00 2001 From: Naresh Jain Date: Sun, 15 Mar 2026 21:00:40 +0530 Subject: [PATCH 07/21] refactor: update dependsOn references to remove $steps prefix and clarify usage in schema --- src/arazzo.md | 38 +++++++++---------- src/schemas/validation/schema.yaml | 11 ++++-- ...ync-depends-on-across-document.arazzo.yaml | 29 ++++++++++++++ ...sync-depends-on-cross-workflow.arazzo.yaml | 32 ++++++++++++++++ .../schema/pass/async-depends-on.arazzo.yaml | 2 +- .../pass/openapi-and-asyncapi.arazzo.yaml | 6 +-- 6 files changed, 92 insertions(+), 26 deletions(-) create mode 100644 tests/schema/pass/async-depends-on-across-document.arazzo.yaml create mode 100644 tests/schema/pass/async-depends-on-cross-workflow.arazzo.yaml diff --git a/src/arazzo.md b/src/arazzo.md index 8fa67b9..6554f78 100644 --- a/src/arazzo.md +++ b/src/arazzo.md @@ -327,24 +327,24 @@ Describes a single workflow step which MAY be a call to an API operation ([OpenA ##### Fixed Fields -| Field Name | Type | Description | -| ------------------------------------------------- | :--------------------------------------------------------------------------------------: |-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| description | `string` | A description of the step. [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation. | -| stepId | `string` | **REQUIRED**. Unique string to represent the step. The `stepId` MUST be unique amongst all steps described in the workflow. The `stepId` value is **case-sensitive**. Tools and libraries MAY use the `stepId` to uniquely identify a workflow step, therefore, it is RECOMMENDED to follow common programming naming conventions. SHOULD conform to the regular expression `[A-Za-z0-9_\-]+`. | -| operationId | `string` | The name of an existing, resolvable operation, as defined with a unique `operationId` and existing within one of the `sourceDescriptions`. The referenced operation will be invoked by this workflow step. If multiple (non `arazzo` type) `sourceDescriptions` are defined, then the `operationId` MUST be specified using a [Runtime Expression](#runtime-expressions) (e.g., `$sourceDescriptions..`) to avoid ambiguity or potential clashes. This field is mutually exclusive of the `operationPath` and `workflowId` fields respectively. | -| operationPath | `string` | A reference to a [Source Description Object](#source-description-object) combined with a [JSON Pointer](https://tools.ietf.org/html/rfc6901) to reference an operation. This field is mutually exclusive of the `operationId` and `workflowId` fields respectively. The operation being referenced MUST be described within one of the `sourceDescriptions` descriptions. A [Runtime Expression](#runtime-expressions) syntax MUST be used to identify the source description document. If the referenced operation has an `operationId` defined then the `operationId` SHOULD be preferred over the `operationPath`. | -| channelPath | `string` | A reference to a [Source Description Object](#source-description-object) combined with a [JSON Pointer](https://tools.ietf.org/html/rfc6901) to reference an event channel. This field is mutually exclusive of the `operationId` and `workflowId` fields respectively. The operation being referenced MUST be described within one of the `sourceDescriptions` descriptions. A [Runtime Expression](#runtime-expressions) syntax MUST be used to identify the source description document. If the referenced operation has an `operationId` defined then the `operationId` SHOULD be preferred over the `channelPath`. | -| workflowId | `string` | The [workflowId](#fixed-fields-2) referencing an existing workflow within the Arazzo Description. If the referenced workflow is contained within an `arazzo` type `sourceDescription`, then the `workflowId` MUST be specified using a [Runtime Expression](#runtime-expressions) (e.g., `$sourceDescriptions..`) to avoid ambiguity or potential clashes. The field is mutually exclusive of the `operationId` and `operationPath` fields respectively. | -| parameters | [[Parameter Object](#parameter-object) \| [Reusable Object](#reusable-object)] | A list of parameters that MUST be passed to an operation or workflow as referenced by `operationId`, `operationPath`, or `workflowId`. If a parameter is already defined at the [Workflow](#workflow-object), the new definition will override it but can never remove it. If a Reusable Object is provided, it MUST link to a parameter defined in the [components/parameters](#components-object) of the current Arazzo document. The list MUST NOT include duplicate parameters. | -| requestBody | [Request Body Object](#request-body-object) | The request body to pass to an operation as referenced by `operationId` or `operationPath`. The `requestBody` is fully supported in HTTP methods where the HTTP 1.1 specification [RFC9110](https://tools.ietf.org/html/rfc9110#section-9.3) explicitly defines semantics for "content" like request bodies, such as within POST, PUT, and PATCH methods. For methods where the HTTP specification provides less clarity—such as GET, HEAD, and DELETE—the use of `requestBody` is permitted but does not have well-defined semantics. In these cases, its use SHOULD be avoided if possible. | -| successCriteria | [[Criterion Object](#criterion-object)] | A list of assertions to determine the success of the step. Each assertion is described using a [Criterion Object](#criterion-object). All assertions `MUST` be satisfied for the step to be deemed successful. | -| onSuccess | [[Success Action Object](#success-action-object) \| [Reusable Object](#reusable-object)] | An array of success action objects that specify what to do upon step success. If omitted, the next sequential step shall be executed as the default behavior. If multiple success actions have similar `criteria`, the first sequential action matching the criteria SHALL be the action executed. If a success action is already defined at the [Workflow](#workflow-object), the new definition will override it but can never remove it. If a Reusable Object is provided, it MUST link to a success action defined in the [components](#components-object) of the current Arazzo document. The list MUST NOT include duplicate success actions. | -| onFailure | [[Failure Action Object](#failure-action-object) \| [Reusable Object](#reusable-object)] | An array of failure action objects that specify what to do upon step failure. If omitted, the default behavior is to break and return. If multiple failure actions have similar `criteria`, the first sequential action matching the criteria SHALL be the action executed. If a failure action is already defined at the [Workflow](#workflow-object), the new definition will override it but can never remove it. If a Reusable Object is provided, it MUST link to a failure action defined in the [components](#components-object) of the current Arazzo document. The list MUST NOT include duplicate failure actions. | -| outputs | Map[`string`, {expression} \| [Selector Object](#selector-object)] | A map between a friendly name and a dynamic output value defined using a [Runtime Expression](#runtime-expressions) or [Selector Object](#selector-object). The name MUST use keys that match the regular expression: `^[a-zA-Z0-9\.\-_]+$`. | -| timeout | `integer` | The maximum number of milli-seconds to wait for the step to complete before aborting and failing the step. Consequently this will fail the workflow unless failureActions are defined. | -| correlationId | `string` | A correlationId in AsyncAPI links a request with its response (or more broadly, to trace a single logical transaction across multiple asynchronous messages). Only applicable to `asyncapi` steps with action `receive` and has to be in-sync with correlationId defined in the AsyncAPI document. | -| action | `send or receive` | Describes the intent of the message flow. Indicates whether the step will send (publish) or receive (subscribe) to a message on a channel described in an AsyncAPI document, Only applicable for `asyncapi` steps. | -| dependsOn | List[`string`] | A list of steps that MUST be completed before this step can be executed. Each value provided MUST be a `stepId`. The `stepId` value is case-sensitive. If the step depended on is defined within the **current workflow**, specify the `stepId` directly (e.g., `authStep`). If the step is defined in a **different workflow within the current Arazzo Document**, reference it using `$workflows..steps.`. If the step is defined in a **separate Arazzo Document**, the workflow MUST be defined in `sourceDescriptions` and referenced using `$sourceDescriptions...steps.` to avoid ambiguity. If your step depends on the output of a non-blocking/asynchronous step, then you SHOULD use `dependsOn` and refer to the async step using one of these patterns. | +| Field Name | Type | Description | +|---------------------------------------------------|:----------------------------------------------------------------------------------------:|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| description | `string` | A description of the step. [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation. | +| stepId | `string` | **REQUIRED**. Unique string to represent the step. The `stepId` MUST be unique amongst all steps described in the workflow. The `stepId` value is **case-sensitive**. Tools and libraries MAY use the `stepId` to uniquely identify a workflow step, therefore, it is RECOMMENDED to follow common programming naming conventions. SHOULD conform to the regular expression `[A-Za-z0-9_\-]+`. | +| operationId | `string` | The name of an existing, resolvable operation, as defined with a unique `operationId` and existing within one of the `sourceDescriptions`. The referenced operation will be invoked by this workflow step. If multiple (non `arazzo` type) `sourceDescriptions` are defined, then the `operationId` MUST be specified using a [Runtime Expression](#runtime-expressions) (e.g., `$sourceDescriptions..`) to avoid ambiguity or potential clashes. This field is mutually exclusive of the `operationPath` and `workflowId` fields respectively. | +| operationPath | `string` | A reference to a [Source Description Object](#source-description-object) combined with a [JSON Pointer](https://tools.ietf.org/html/rfc6901) to reference an operation. This field is mutually exclusive of the `operationId` and `workflowId` fields respectively. The operation being referenced MUST be described within one of the `sourceDescriptions` descriptions. A [Runtime Expression](#runtime-expressions) syntax MUST be used to identify the source description document. If the referenced operation has an `operationId` defined then the `operationId` SHOULD be preferred over the `operationPath`. | +| channelPath | `string` | A reference to a [Source Description Object](#source-description-object) combined with a [JSON Pointer](https://tools.ietf.org/html/rfc6901) to reference an event channel. This field is mutually exclusive of the `operationId` and `workflowId` fields respectively. The operation being referenced MUST be described within one of the `sourceDescriptions` descriptions. A [Runtime Expression](#runtime-expressions) syntax MUST be used to identify the source description document. If the referenced operation has an `operationId` defined then the `operationId` SHOULD be preferred over the `channelPath`. | +| workflowId | `string` | The [workflowId](#fixed-fields-2) referencing an existing workflow within the Arazzo Description. If the referenced workflow is contained within an `arazzo` type `sourceDescription`, then the `workflowId` MUST be specified using a [Runtime Expression](#runtime-expressions) (e.g., `$sourceDescriptions..`) to avoid ambiguity or potential clashes. The field is mutually exclusive of the `operationId` and `operationPath` fields respectively. | +| parameters | [[Parameter Object](#parameter-object) \| [Reusable Object](#reusable-object)] | A list of parameters that MUST be passed to an operation or workflow as referenced by `operationId`, `operationPath`, or `workflowId`. If a parameter is already defined at the [Workflow](#workflow-object), the new definition will override it but can never remove it. If a Reusable Object is provided, it MUST link to a parameter defined in the [components/parameters](#components-object) of the current Arazzo document. The list MUST NOT include duplicate parameters. | +| requestBody | [Request Body Object](#request-body-object) | The request body to pass to an operation as referenced by `operationId` or `operationPath`. The `requestBody` is fully supported in HTTP methods where the HTTP 1.1 specification [RFC9110](https://tools.ietf.org/html/rfc9110#section-9.3) explicitly defines semantics for "content" like request bodies, such as within POST, PUT, and PATCH methods. For methods where the HTTP specification provides less clarity—such as GET, HEAD, and DELETE—the use of `requestBody` is permitted but does not have well-defined semantics. In these cases, its use SHOULD be avoided if possible. | +| successCriteria | [[Criterion Object](#criterion-object)] | A list of assertions to determine the success of the step. Each assertion is described using a [Criterion Object](#criterion-object). All assertions `MUST` be satisfied for the step to be deemed successful. | +| onSuccess | [[Success Action Object](#success-action-object) \| [Reusable Object](#reusable-object)] | An array of success action objects that specify what to do upon step success. If omitted, the next sequential step shall be executed as the default behavior. If multiple success actions have similar `criteria`, the first sequential action matching the criteria SHALL be the action executed. If a success action is already defined at the [Workflow](#workflow-object), the new definition will override it but can never remove it. If a Reusable Object is provided, it MUST link to a success action defined in the [components](#components-object) of the current Arazzo document. The list MUST NOT include duplicate success actions. | +| onFailure | [[Failure Action Object](#failure-action-object) \| [Reusable Object](#reusable-object)] | An array of failure action objects that specify what to do upon step failure. If omitted, the default behavior is to break and return. If multiple failure actions have similar `criteria`, the first sequential action matching the criteria SHALL be the action executed. If a failure action is already defined at the [Workflow](#workflow-object), the new definition will override it but can never remove it. If a Reusable Object is provided, it MUST link to a failure action defined in the [components](#components-object) of the current Arazzo document. The list MUST NOT include duplicate failure actions. | +| outputs | Map[`string`, {expression} \| [Selector Object](#selector-object)] | A map between a friendly name and a dynamic output value defined using a [Runtime Expression](#runtime-expressions) or [Selector Object](#selector-object). The name MUST use keys that match the regular expression: `^[a-zA-Z0-9\.\-_]+$`. | +| timeout | `integer` | The maximum number of milli-seconds to wait for the step to complete before aborting and failing the step. Consequently this will fail the workflow unless failureActions are defined. | +| correlationId | `string` | A correlationId in AsyncAPI links a request with its response (or more broadly, to trace a single logical transaction across multiple asynchronous messages). Only applicable to `asyncapi` steps with action `receive` and has to be in-sync with correlationId defined in the AsyncAPI document. | +| action | `send or receive` | Describes the intent of the message flow. Indicates whether the step will send (publish) or receive (subscribe) to a message on a channel described in an AsyncAPI document, Only applicable for `asyncapi` steps. | +| dependsOn | List[`string`] | A list of steps that MUST be completed before this step can be executed. Each value provided MUST be a `stepId`. The `stepId` value is case-sensitive. If the step depended on is defined within the **current workflow**, specify the `stepId` directly (e.g., `authStep`). If the step is defined in a **different workflow within the current Arazzo Document**, reference it using `$workflows..steps.`. If the step is defined in a **separate Arazzo Document**, the workflow MUST be defined in `sourceDescriptions` and referenced using `$sourceDescriptions...steps.` to avoid ambiguity. If your step depends on the output of a non-blocking/asynchronous step, then you SHOULD use `dependsOn` and refer to the async step using one of these patterns. | This object MAY be extended with [Specification Extensions](#specification-extensions). @@ -433,7 +433,7 @@ An async step example: operationId: $sourceDescriptions.asyncOrderApi.confirmOrder correlationId: $inputs.correlationId action: receive - dependsOn: $steps.placeOrder + dependsOn: placeOrder timeout: 6000 outputs: orderId: $message.payload.orderId diff --git a/src/schemas/validation/schema.yaml b/src/schemas/validation/schema.yaml index 07737c8..432864a 100644 --- a/src/schemas/validation/schema.yaml +++ b/src/schemas/validation/schema.yaml @@ -179,13 +179,18 @@ $defs: description: The duration in milliseconds to wait before timing out the step type: integer dependsOn: - description: Specifies a list of step identifiers that must complete (or be waited for) before the current step can begin execution. Steps referred by dependsOn SHOULD be non-blocking/async steps. If you depend on a step from another workflow, you MUST use the full reference format with the workflow id. + description: Specifies a list of step identifiers that must complete (or be waited for) before the current step can begin execution. Steps referred by dependsOn SHOULD be non-blocking/async steps. Steps in the current workflow MUST be referenced directly by stepId. Steps in another workflow in the same Arazzo document MUST use $workflows..steps.. Steps in another Arazzo document MUST use $sourceDescriptions...steps.. type: array uniqueItems: true minItems: 1 items: - type: string - pattern: ^\$(?:workflows\.[^.]+\.)?steps\.[^.]+$ + oneOf: + - type: string + pattern: ^(?!\$).+$ + - type: string + pattern: ^\$workflows\.[^.]+\.steps\.[^.]+$ + - type: string + pattern: ^\$sourceDescriptions\.[^.]+\.[^.]+\.steps\.[^.]+$ parameters: description: A list of parameters that MUST be passed to an operation or workflow as referenced by operationId, operationPath, or workflowId type: array diff --git a/tests/schema/pass/async-depends-on-across-document.arazzo.yaml b/tests/schema/pass/async-depends-on-across-document.arazzo.yaml new file mode 100644 index 0000000..95a5006 --- /dev/null +++ b/tests/schema/pass/async-depends-on-across-document.arazzo.yaml @@ -0,0 +1,29 @@ +arazzo: 1.1.0 +info: + title: Async dependsOn across documents + version: 1.0.0 +sourceDescriptions: + - name: localAsyncApi + url: https://example.com/local-asyncapi.yaml + type: asyncapi + - name: otherWorkflowDoc + url: https://example.com/other.arazzo.yaml + type: arazzo +workflows: + - workflowId: localWorkflow + steps: + - stepId: waitForLocalEvent + operationId: localReceive + action: receive + correlationId: id123 + timeout: 6000 + - stepId: useLocalDirectStepId + operationId: localSend + action: send + dependsOn: + - waitForLocalEvent + - stepId: useExternalWorkflowStep + operationId: localSend + action: send + dependsOn: + - "$sourceDescriptions.otherWorkflowDoc.remoteWorkflow.steps.remoteReceive" diff --git a/tests/schema/pass/async-depends-on-cross-workflow.arazzo.yaml b/tests/schema/pass/async-depends-on-cross-workflow.arazzo.yaml new file mode 100644 index 0000000..2b9cc90 --- /dev/null +++ b/tests/schema/pass/async-depends-on-cross-workflow.arazzo.yaml @@ -0,0 +1,32 @@ +arazzo: 1.1.0 +info: + title: Async dependsOn across workflows in one document + version: 1.0.0 +sourceDescriptions: + - name: exampleAPI + url: https://example.com/asyncapi.yaml + type: asyncapi +workflows: + - workflowId: producerWorkflow + steps: + - stepId: produceEvent + operationId: createUser + action: send + - stepId: waitForEvent + operationId: fetchUserId + action: receive + correlationId: id123 + timeout: 6000 + outputs: + userId: "$message.payload.userId" + - workflowId: consumerWorkflow + steps: + - stepId: processEvent + operationId: updateUser + action: send + dependsOn: + - "$workflows.producerWorkflow.steps.waitForEvent" + parameters: + - name: userId + in: header + value: "$workflows.producerWorkflow.steps.waitForEvent.outputs.userId" diff --git a/tests/schema/pass/async-depends-on.arazzo.yaml b/tests/schema/pass/async-depends-on.arazzo.yaml index 97e4983..4a3a034 100644 --- a/tests/schema/pass/async-depends-on.arazzo.yaml +++ b/tests/schema/pass/async-depends-on.arazzo.yaml @@ -23,7 +23,7 @@ workflows: operationId: updateUser action: send dependsOn: - - "$steps.step2" + - "step2" parameters: - name: userId in: header diff --git a/tests/schema/pass/openapi-and-asyncapi.arazzo.yaml b/tests/schema/pass/openapi-and-asyncapi.arazzo.yaml index 34609a5..6a3fb4a 100644 --- a/tests/schema/pass/openapi-and-asyncapi.arazzo.yaml +++ b/tests/schema/pass/openapi-and-asyncapi.arazzo.yaml @@ -93,7 +93,7 @@ workflows: - stepId: "reserveInventory" operationId: "$sourceDescriptions.WarehouseApi.reserveInventory" dependsOn: - - "$steps.createOrderReceive" + - "createOrderReceive" parameters: - name: "orderId" in: "query" @@ -109,7 +109,7 @@ workflows: operationId: "$sourceDescriptions.AsyncOrderApi.outForDelivery" action: "send" dependsOn: - - "$steps.createOrderReceive" + - "createOrderReceive" parameters: - name: "requestId" in: "header" @@ -120,7 +120,7 @@ workflows: - stepId: "getOrderDetails" operationId: "$sourceDescriptions.OrderApi.getOrderDetails" dependsOn: - - "$steps.createOrderReceive" + - "createOrderReceive" parameters: - name: "orderId" in: "path" From 37a412719006a468fa54fe7914e5a39de1b6013c Mon Sep 17 00:00:00 2001 From: Naresh Jain Date: Mon, 16 Mar 2026 22:11:32 +0530 Subject: [PATCH 08/21] fix: remove quotes from YAML runtime expressions and dependsOn references --- src/specifications/pet-asyncapi.yaml | 4 +- ...ync-depends-on-across-document.arazzo.yaml | 2 +- ...sync-depends-on-cross-workflow.arazzo.yaml | 6 +- .../schema/pass/async-depends-on.arazzo.yaml | 10 +-- .../pass/openapi-and-asyncapi.arazzo.yaml | 68 +++++++++---------- 5 files changed, 45 insertions(+), 45 deletions(-) diff --git a/src/specifications/pet-asyncapi.yaml b/src/specifications/pet-asyncapi.yaml index 695139d..3c7d1ef 100644 --- a/src/specifications/pet-asyncapi.yaml +++ b/src/specifications/pet-asyncapi.yaml @@ -42,7 +42,7 @@ components: contentType: application/json correlationId: description: Identifier that correlates this request with a response - location: "$message.header#/orderRequestId" + location: $message.header#/orderRequestId headers: type: object required: @@ -63,7 +63,7 @@ components: contentType: application/json correlationId: description: Identifier that correlates this response with a request - location: "$message.header#/orderRequestId" + location: $message.header#/orderRequestId headers: type: object required: diff --git a/tests/schema/pass/async-depends-on-across-document.arazzo.yaml b/tests/schema/pass/async-depends-on-across-document.arazzo.yaml index 95a5006..950355c 100644 --- a/tests/schema/pass/async-depends-on-across-document.arazzo.yaml +++ b/tests/schema/pass/async-depends-on-across-document.arazzo.yaml @@ -26,4 +26,4 @@ workflows: operationId: localSend action: send dependsOn: - - "$sourceDescriptions.otherWorkflowDoc.remoteWorkflow.steps.remoteReceive" + - $sourceDescriptions.otherWorkflowDoc.remoteWorkflow.steps.remoteReceive \ No newline at end of file diff --git a/tests/schema/pass/async-depends-on-cross-workflow.arazzo.yaml b/tests/schema/pass/async-depends-on-cross-workflow.arazzo.yaml index 2b9cc90..29ac945 100644 --- a/tests/schema/pass/async-depends-on-cross-workflow.arazzo.yaml +++ b/tests/schema/pass/async-depends-on-cross-workflow.arazzo.yaml @@ -18,15 +18,15 @@ workflows: correlationId: id123 timeout: 6000 outputs: - userId: "$message.payload.userId" + userId: $message.payload.userId - workflowId: consumerWorkflow steps: - stepId: processEvent operationId: updateUser action: send dependsOn: - - "$workflows.producerWorkflow.steps.waitForEvent" + - $workflows.producerWorkflow.steps.waitForEvent parameters: - name: userId in: header - value: "$workflows.producerWorkflow.steps.waitForEvent.outputs.userId" + value: $workflows.producerWorkflow.steps.waitForEvent.outputs.userId \ No newline at end of file diff --git a/tests/schema/pass/async-depends-on.arazzo.yaml b/tests/schema/pass/async-depends-on.arazzo.yaml index 4a3a034..f034287 100644 --- a/tests/schema/pass/async-depends-on.arazzo.yaml +++ b/tests/schema/pass/async-depends-on.arazzo.yaml @@ -18,22 +18,22 @@ workflows: correlationId: id123 timeout: 6000 outputs: - userId: "$message.payload.userId" + userId: $message.payload.userId - stepId: step3 operationId: updateUser action: send dependsOn: - - "step2" + - step2 parameters: - name: userId in: header - value: "$steps.step2.outputs.userId" + value: $steps.step2.outputs.userId - stepId: step4 operationId: deleteUser action: send dependsOn: - - "$workflows.dependsOnWorkflow.steps.step2" + - $workflows.dependsOnWorkflow.steps.step2 parameters: - name: userId in: header - value: "$steps.step2.outputs.userId" \ No newline at end of file + value: $steps.step2.outputs.userId \ No newline at end of file diff --git a/tests/schema/pass/openapi-and-asyncapi.arazzo.yaml b/tests/schema/pass/openapi-and-asyncapi.arazzo.yaml index 6a3fb4a..ee24bff 100644 --- a/tests/schema/pass/openapi-and-asyncapi.arazzo.yaml +++ b/tests/schema/pass/openapi-and-asyncapi.arazzo.yaml @@ -43,87 +43,87 @@ workflows: format: "email" steps: - stepId: "getUserLocation" - operationId: "$sourceDescriptions.LocationApi.getUserLocation" + operationId: $sourceDescriptions.LocationApi.getUserLocation parameters: - name: "userEmail" in: "query" - value: "$inputs.getUserLocation.userEmail" + value: $inputs.getUserLocation.userEmail successCriteria: - - condition: "$statusCode == 200" + - condition: $statusCode == 200 outputs: - userId: "$response.body#/userId" - locationCode: "$response.body#/locationCode" + userId: $response.body#/userId + locationCode: $response.body#/locationCode - stepId: "getProducts" - operationId: "$sourceDescriptions.ProductApi.getProducts" + operationId: $sourceDescriptions.ProductApi.getProducts parameters: - name: "locationCode" in: "query" - value: "$steps.getUserLocation.outputs.locationCode" + value: $steps.getUserLocation.outputs.locationCode successCriteria: - - condition: "$statusCode == 200" + - condition: $statusCode == 200 onSuccess: - name: "IsArrayEmpty" type: "end" criteria: - - condition: "$response.body#/0 == null" + - condition: $response.body#/0 == null outputs: - productId: "$response.body#/0/productId" - inventory: "$response.body#/0/inventory" + productId: $response.body#/0/productId + inventory: $response.body#/0/inventory - stepId: "createOrderSend" - operationId: "$sourceDescriptions.AsyncOrderApi.createOrder" + operationId: $sourceDescriptions.AsyncOrderApi.createOrder action: "send" parameters: - name: "requestId" in: "header" - value: "$inputs.createOrderSend.requestId" + value: $inputs.createOrderSend.requestId requestBody: payload: - userId: "$steps.getUserLocation.outputs.userId" - productId: "$steps.getProducts.outputs.productId" - inventory: "$steps.getProducts.outputs.inventory" + userId: $steps.getUserLocation.outputs.userId + productId: $steps.getProducts.outputs.productId + inventory: $steps.getProducts.outputs.inventory outputs: - requestId: "$message.header.requestId" + requestId: $message.header.requestId - stepId: "createOrderReceive" - operationId: "$sourceDescriptions.AsyncOrderApi.createOrder" + operationId: $sourceDescriptions.AsyncOrderApi.createOrder action: "receive" - correlationId: "$steps.createOrderSend.outputs.requestId" + correlationId: $steps.createOrderSend.outputs.requestId timeout: 6000 outputs: - orderId: "$message.payload.orderId" + orderId: $message.payload.orderId - stepId: "reserveInventory" - operationId: "$sourceDescriptions.WarehouseApi.reserveInventory" + operationId: $sourceDescriptions.WarehouseApi.reserveInventory dependsOn: - - "createOrderReceive" + - createOrderReceive parameters: - name: "orderId" in: "query" - value: "$steps.createOrderReceive.outputs.orderId" + value: $steps.createOrderReceive.outputs.orderId successCriteria: - - condition: "$statusCode == 200" + - condition: $statusCode == 200 - stepId: "orderAccepted" - operationId: "$sourceDescriptions.AsyncOrderApi.orderAccepted" + operationId: $sourceDescriptions.AsyncOrderApi.orderAccepted action: "receive" - correlationId: "$steps.createOrderSend.outputs.requestId" + correlationId: $steps.createOrderSend.outputs.requestId timeout: 6000 - stepId: "outForDelivery" - operationId: "$sourceDescriptions.AsyncOrderApi.outForDelivery" + operationId: $sourceDescriptions.AsyncOrderApi.outForDelivery action: "send" dependsOn: - - "createOrderReceive" + - createOrderReceive parameters: - name: "requestId" in: "header" - value: "$steps.createOrderSend.outputs.requestId" + value: $steps.createOrderSend.outputs.requestId requestBody: payload: - orderId: "$steps.createOrderReceive.outputs.orderId" + orderId: $steps.createOrderReceive.outputs.orderId - stepId: "getOrderDetails" - operationId: "$sourceDescriptions.OrderApi.getOrderDetails" + operationId: $sourceDescriptions.OrderApi.getOrderDetails dependsOn: - - "createOrderReceive" + - createOrderReceive parameters: - name: "orderId" in: "path" - value: "$steps.createOrderReceive.outputs.orderId" + value: $steps.createOrderReceive.outputs.orderId successCriteria: - - condition: "$statusCode == 200" \ No newline at end of file + - condition: $statusCode == 200 \ No newline at end of file From 65b796be29d4e25af5e1a806768ddc4cfb6a09f1 Mon Sep 17 00:00:00 2001 From: Naresh Jain Date: Wed, 1 Apr 2026 22:59:06 +0530 Subject: [PATCH 09/21] fix: update dependsOn format to use a list in arazzo.md --- src/arazzo.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/arazzo.md b/src/arazzo.md index 6554f78..f1599fe 100644 --- a/src/arazzo.md +++ b/src/arazzo.md @@ -433,7 +433,8 @@ An async step example: operationId: $sourceDescriptions.asyncOrderApi.confirmOrder correlationId: $inputs.correlationId action: receive - dependsOn: placeOrder + dependsOn: + - placeOrder timeout: 6000 outputs: orderId: $message.payload.orderId From d06e43a0644be083bc0fd2a09adda09966663a30 Mon Sep 17 00:00:00 2001 From: Naresh Jain Date: Wed, 1 Apr 2026 23:10:15 +0530 Subject: [PATCH 10/21] fix: remove quotes from YAML keys and update formatting in openapi-and-asyncapi.arazzo.yaml --- .../pass/openapi-and-asyncapi.arazzo.yaml | 110 +++++++++--------- 1 file changed, 55 insertions(+), 55 deletions(-) diff --git a/tests/schema/pass/openapi-and-asyncapi.arazzo.yaml b/tests/schema/pass/openapi-and-asyncapi.arazzo.yaml index ee24bff..32c8a04 100644 --- a/tests/schema/pass/openapi-and-asyncapi.arazzo.yaml +++ b/tests/schema/pass/openapi-and-asyncapi.arazzo.yaml @@ -1,80 +1,80 @@ -arazzo: "1.1.0" +arazzo: 1.1.0 info: - title: "Arazzo Workflow" - version: "1.1.0" + title: Arazzo Workflow + version: 1.1.0 sourceDescriptions: -- name: "LocationApi" - url: "./workflow/openapi/location.yaml" - type: "openapi" -- name: "ProductApi" - url: "./workflow/openapi/product.yaml" - type: "openapi" -- name: "AsyncOrderApi" - url: "./workflow/asyncapi/order.yaml" - type: "asyncapi" -- name: "WarehouseApi" - url: "./workflow/openapi/warehouse.yaml" - type: "openapi" -- name: "OrderApi" - url: "./workflow/openapi/order.yaml" - type: "openapi" +- name: LocationApi + url: ./workflow/openapi/location.yaml + type: openapi +- name: ProductApi + url: ./workflow/openapi/product.yaml + type: openapi +- name: AsyncOrderApi + url: ./workflow/asyncapi/order.yaml + type: asyncapi +- name: WarehouseApi + url: ./workflow/openapi/warehouse.yaml + type: openapi +- name: OrderApi + url: ./workflow/openapi/order.yaml + type: openapi workflows: -- workflowId: "OrderId" +- workflowId: OrderId inputs: required: - - "createOrderSend" - - "getUserLocation" - type: "object" + - createOrderSend + - getUserLocation + type: object properties: createOrderSend: required: - - "requestId" - type: "object" + - requestId + type: object properties: requestId: - type: "string" + type: string getUserLocation: required: - - "userEmail" - type: "object" + - userEmail + type: object properties: userEmail: - type: "string" - format: "email" + type: string + format: email steps: - - stepId: "getUserLocation" + - stepId: getUserLocation operationId: $sourceDescriptions.LocationApi.getUserLocation parameters: - - name: "userEmail" - in: "query" + - name: userEmail + in: query value: $inputs.getUserLocation.userEmail successCriteria: - condition: $statusCode == 200 outputs: userId: $response.body#/userId locationCode: $response.body#/locationCode - - stepId: "getProducts" + - stepId: getProducts operationId: $sourceDescriptions.ProductApi.getProducts parameters: - - name: "locationCode" - in: "query" + - name: locationCode + in: query value: $steps.getUserLocation.outputs.locationCode successCriteria: - condition: $statusCode == 200 onSuccess: - - name: "IsArrayEmpty" - type: "end" + - name: IsArrayEmpty + type: end criteria: - condition: $response.body#/0 == null outputs: productId: $response.body#/0/productId inventory: $response.body#/0/inventory - - stepId: "createOrderSend" + - stepId: createOrderSend operationId: $sourceDescriptions.AsyncOrderApi.createOrder - action: "send" + action: send parameters: - - name: "requestId" - in: "header" + - name: requestId + in: header value: $inputs.createOrderSend.requestId requestBody: payload: @@ -83,47 +83,47 @@ workflows: inventory: $steps.getProducts.outputs.inventory outputs: requestId: $message.header.requestId - - stepId: "createOrderReceive" + - stepId: createOrderReceive operationId: $sourceDescriptions.AsyncOrderApi.createOrder - action: "receive" + action: receive correlationId: $steps.createOrderSend.outputs.requestId timeout: 6000 outputs: orderId: $message.payload.orderId - - stepId: "reserveInventory" + - stepId: reserveInventory operationId: $sourceDescriptions.WarehouseApi.reserveInventory dependsOn: - createOrderReceive parameters: - - name: "orderId" - in: "query" + - name: orderId + in: query value: $steps.createOrderReceive.outputs.orderId successCriteria: - condition: $statusCode == 200 - - stepId: "orderAccepted" + - stepId: orderAccepted operationId: $sourceDescriptions.AsyncOrderApi.orderAccepted - action: "receive" + action: receive correlationId: $steps.createOrderSend.outputs.requestId timeout: 6000 - - stepId: "outForDelivery" + - stepId: outForDelivery operationId: $sourceDescriptions.AsyncOrderApi.outForDelivery - action: "send" + action: send dependsOn: - createOrderReceive parameters: - - name: "requestId" - in: "header" + - name: requestId + in: header value: $steps.createOrderSend.outputs.requestId requestBody: payload: orderId: $steps.createOrderReceive.outputs.orderId - - stepId: "getOrderDetails" + - stepId: getOrderDetails operationId: $sourceDescriptions.OrderApi.getOrderDetails dependsOn: - createOrderReceive parameters: - - name: "orderId" - in: "path" + - name: orderId + in: path value: $steps.createOrderReceive.outputs.orderId successCriteria: - condition: $statusCode == 200 \ No newline at end of file From 8ef01ecac3af458e1f65e1e685571eff6f3f0aff Mon Sep 17 00:00:00 2001 From: Naresh Jain Date: Fri, 3 Apr 2026 13:33:29 +0530 Subject: [PATCH 11/21] refactor: move default successCriteria to workflow-step from step-object-base to avoid confusion. Add success criteria examples for AsyncAPI, OpenAPI and workflow steps --- src/schemas/validation/schema.yaml | 14 +++++------ ...valid-openapi-success-criteria.arazzo.yaml | 14 +++++++++++ ...alid-workflow-success-criteria.arazzo.yaml | 16 ++++++++++++ .../asyncapi-success-criteria.arazzo.yaml | 19 ++++++++++++++ .../pass/openapi-success-criteria.arazzo.yaml | 15 +++++++++++ .../workflow-success-criteria.arazzo.yaml | 25 +++++++++++++++++++ 6 files changed, 96 insertions(+), 7 deletions(-) create mode 100644 tests/schema/fail/invalid-openapi-success-criteria.arazzo.yaml create mode 100644 tests/schema/fail/invalid-workflow-success-criteria.arazzo.yaml create mode 100644 tests/schema/pass/asyncapi-success-criteria.arazzo.yaml create mode 100644 tests/schema/pass/openapi-success-criteria.arazzo.yaml create mode 100644 tests/schema/pass/workflow-success-criteria.arazzo.yaml diff --git a/src/schemas/validation/schema.yaml b/src/schemas/validation/schema.yaml index 432864a..b2a546e 100644 --- a/src/schemas/validation/schema.yaml +++ b/src/schemas/validation/schema.yaml @@ -198,13 +198,6 @@ $defs: items: true requestBody: $ref: '#/$defs/request-body-object' - successCriteria: - description: A list of assertions to determine the success of the step - type: array - uniqueItems: true - minItems: 1 - items: - $ref: '#/$defs/criterion-object' onSuccess: description: An array of success action objects that specify what to do upon step success type: array @@ -339,6 +332,13 @@ $defs: workflowId: description: The workflowId referencing an existing workflow within the Arazzo description $ref: '#workflowId' + successCriteria: + description: A list of assertions to determine the success of the step + type: array + uniqueItems: true + minItems: 1 + items: + $ref: '#/$defs/criterion-object' parameters: items: oneOf: diff --git a/tests/schema/fail/invalid-openapi-success-criteria.arazzo.yaml b/tests/schema/fail/invalid-openapi-success-criteria.arazzo.yaml new file mode 100644 index 0000000..0c2afaa --- /dev/null +++ b/tests/schema/fail/invalid-openapi-success-criteria.arazzo.yaml @@ -0,0 +1,14 @@ +arazzo: 1.1.0 +info: + title: Invalid OpenAPI step success criteria + version: 1.0.0 +sourceDescriptions: + - name: exampleAPI + url: https://example.com/openapi.yaml + type: openapi +workflows: + - workflowId: openapiWorkflow + steps: + - stepId: getUsers + operationId: listUsers + successCriteria: [] diff --git a/tests/schema/fail/invalid-workflow-success-criteria.arazzo.yaml b/tests/schema/fail/invalid-workflow-success-criteria.arazzo.yaml new file mode 100644 index 0000000..3f6e5e5 --- /dev/null +++ b/tests/schema/fail/invalid-workflow-success-criteria.arazzo.yaml @@ -0,0 +1,16 @@ +arazzo: 1.1.0 +info: + title: Invalid workflow step success criteria + version: 1.0.0 +workflows: + - workflowId: parentWorkflow + steps: + - stepId: nestedWorkflow + workflowId: childWorkflow + successCriteria: [] + - workflowId: childWorkflow + steps: + - stepId: childStep + operationId: getUsers + successCriteria: + - condition: $statusCode == 200 diff --git a/tests/schema/pass/asyncapi-success-criteria.arazzo.yaml b/tests/schema/pass/asyncapi-success-criteria.arazzo.yaml new file mode 100644 index 0000000..297eedf --- /dev/null +++ b/tests/schema/pass/asyncapi-success-criteria.arazzo.yaml @@ -0,0 +1,19 @@ +arazzo: 1.1.0 +info: + title: AsyncAPI step with success criteria + version: 1.0.0 +sourceDescriptions: + - name: UserAPI + url: https://user.com/asyncapi.yaml + type: asyncapi +workflows: + - workflowId: asyncWorkflow + steps: + - stepId: receiveOrder + operationId: $sourceDescriptions.UserAPI.orderCreated + action: receive + correlationId: request-123 + successCriteria: + - context: $message.payload + condition: $.status == 'accepted' + type: jsonpath diff --git a/tests/schema/pass/openapi-success-criteria.arazzo.yaml b/tests/schema/pass/openapi-success-criteria.arazzo.yaml new file mode 100644 index 0000000..f388681 --- /dev/null +++ b/tests/schema/pass/openapi-success-criteria.arazzo.yaml @@ -0,0 +1,15 @@ +arazzo: 1.1.0 +info: + title: OpenAPI step with success criteria + version: 1.0.0 +sourceDescriptions: + - name: UserAPI + url: https://users.com/openapi.yaml + type: openapi +workflows: + - workflowId: openapiWorkflow + steps: + - stepId: getUsers + operationId: $sourceDescriptions.userAPI.listUsers + successCriteria: + - condition: $statusCode == 200 diff --git a/tests/schema/pass/workflow-success-criteria.arazzo.yaml b/tests/schema/pass/workflow-success-criteria.arazzo.yaml new file mode 100644 index 0000000..d496331 --- /dev/null +++ b/tests/schema/pass/workflow-success-criteria.arazzo.yaml @@ -0,0 +1,25 @@ +arazzo: 1.1.0 +info: + title: Valid workflow step success criteria + version: 1.0.0 +sourceDescriptions: + - name: UserAPI + url: https://users.com/openapi.yaml + type: openapi +workflows: + - workflowId: parentWorkflow + steps: + - stepId: nestedWorkflow + workflowId: childWorkflow + successCriteria: + - condition: $workflows.childWorkflow.outputs.userId > 0 + - workflowId: childWorkflow + steps: + - stepId: childStep + operationId: $sourceDescriptions.userAPI.listUsers + outputs: + userId: $response.body#/id + successCriteria: + - condition: $statusCode == 200 + outputs: + userId: $steps.childStep.outputs.userId From 7112d95f9027e58a7b0508bf890d113a2ab28ccf Mon Sep 17 00:00:00 2001 From: Naresh Jain Date: Fri, 3 Apr 2026 14:47:38 +0530 Subject: [PATCH 12/21] refactor: move successCriteria back to step-object-base. If successCriteria key is present, then at least one criterion-object should be present. --- src/arazzo.md | 4 ++-- src/schemas/validation/schema.yaml | 28 +++++++--------------------- 2 files changed, 9 insertions(+), 23 deletions(-) diff --git a/src/arazzo.md b/src/arazzo.md index f1599fe..a009444 100644 --- a/src/arazzo.md +++ b/src/arazzo.md @@ -323,7 +323,7 @@ outputs: #### Step Object -Describes a single workflow step which MAY be a call to an API operation ([OpenAPI Operation Object](https://spec.openapis.org/oas/latest.html#operation-object)) or another [Workflow Object](#workflow-object). +Describes a single workflow step which MAY be a call to an API operation ([OpenAPI Operation Object](https://spec.openapis.org/oas/latest.html#operation-object)), ([AysncAPI Operations Object](https://www.asyncapi.com/docs/reference/specification/latest#operationsObject)) or another [Workflow Object](#workflow-object). ##### Fixed Fields @@ -337,7 +337,7 @@ Describes a single workflow step which MAY be a call to an API operation ([OpenA | workflowId | `string` | The [workflowId](#fixed-fields-2) referencing an existing workflow within the Arazzo Description. If the referenced workflow is contained within an `arazzo` type `sourceDescription`, then the `workflowId` MUST be specified using a [Runtime Expression](#runtime-expressions) (e.g., `$sourceDescriptions..`) to avoid ambiguity or potential clashes. The field is mutually exclusive of the `operationId` and `operationPath` fields respectively. | | parameters | [[Parameter Object](#parameter-object) \| [Reusable Object](#reusable-object)] | A list of parameters that MUST be passed to an operation or workflow as referenced by `operationId`, `operationPath`, or `workflowId`. If a parameter is already defined at the [Workflow](#workflow-object), the new definition will override it but can never remove it. If a Reusable Object is provided, it MUST link to a parameter defined in the [components/parameters](#components-object) of the current Arazzo document. The list MUST NOT include duplicate parameters. | | requestBody | [Request Body Object](#request-body-object) | The request body to pass to an operation as referenced by `operationId` or `operationPath`. The `requestBody` is fully supported in HTTP methods where the HTTP 1.1 specification [RFC9110](https://tools.ietf.org/html/rfc9110#section-9.3) explicitly defines semantics for "content" like request bodies, such as within POST, PUT, and PATCH methods. For methods where the HTTP specification provides less clarity—such as GET, HEAD, and DELETE—the use of `requestBody` is permitted but does not have well-defined semantics. In these cases, its use SHOULD be avoided if possible. | -| successCriteria | [[Criterion Object](#criterion-object)] | A list of assertions to determine the success of the step. Each assertion is described using a [Criterion Object](#criterion-object). All assertions `MUST` be satisfied for the step to be deemed successful. | +| successCriteria | [[Criterion Object](#criterion-object)] | A list of assertions to determine the success of the step. Each assertion is described using a [Criterion Object](#criterion-object). All assertions `MUST` be satisfied for the step to be deemed successful. `MUST` contain at least one [Criterion Object](#criterion-object) | | onSuccess | [[Success Action Object](#success-action-object) \| [Reusable Object](#reusable-object)] | An array of success action objects that specify what to do upon step success. If omitted, the next sequential step shall be executed as the default behavior. If multiple success actions have similar `criteria`, the first sequential action matching the criteria SHALL be the action executed. If a success action is already defined at the [Workflow](#workflow-object), the new definition will override it but can never remove it. If a Reusable Object is provided, it MUST link to a success action defined in the [components](#components-object) of the current Arazzo document. The list MUST NOT include duplicate success actions. | | onFailure | [[Failure Action Object](#failure-action-object) \| [Reusable Object](#reusable-object)] | An array of failure action objects that specify what to do upon step failure. If omitted, the default behavior is to break and return. If multiple failure actions have similar `criteria`, the first sequential action matching the criteria SHALL be the action executed. If a failure action is already defined at the [Workflow](#workflow-object), the new definition will override it but can never remove it. If a Reusable Object is provided, it MUST link to a failure action defined in the [components](#components-object) of the current Arazzo document. The list MUST NOT include duplicate failure actions. | | outputs | Map[`string`, {expression} \| [Selector Object](#selector-object)] | A map between a friendly name and a dynamic output value defined using a [Runtime Expression](#runtime-expressions) or [Selector Object](#selector-object). The name MUST use keys that match the regular expression: `^[a-zA-Z0-9\.\-_]+$`. | diff --git a/src/schemas/validation/schema.yaml b/src/schemas/validation/schema.yaml index b2a546e..24b2a8f 100644 --- a/src/schemas/validation/schema.yaml +++ b/src/schemas/validation/schema.yaml @@ -198,6 +198,13 @@ $defs: items: true requestBody: $ref: '#/$defs/request-body-object' + successCriteria: + description: A list of assertions to determine the success of the step + type: array + uniqueItems: true + minItems: 1 + items: + $ref: '#/$defs/criterion-object' onSuccess: description: An array of success action objects that specify what to do upon step success type: array @@ -234,13 +241,6 @@ $defs: operationPath: description: A reference to a Source combined with a JSON Pointer to reference an operation type: string - successCriteria: - description: A list of assertions to determine the success of the step - type: array - uniqueItems: true - minItems: 1 - items: - $ref: '#/$defs/criterion-object' - if: oneOf: - required: @@ -284,13 +284,6 @@ $defs: enum: - send - receive - successCriteria: - description: A list of assertions to determine the success of the step - type: array - uniqueItems: true - minItems: 0 - items: - $ref: '#/$defs/criterion-object' required: - action - if: @@ -332,13 +325,6 @@ $defs: workflowId: description: The workflowId referencing an existing workflow within the Arazzo description $ref: '#workflowId' - successCriteria: - description: A list of assertions to determine the success of the step - type: array - uniqueItems: true - minItems: 1 - items: - $ref: '#/$defs/criterion-object' parameters: items: oneOf: From 5ed90c7b4f282a85e4a8593d10a6ac53ef63e38c Mon Sep 17 00:00:00 2001 From: Naresh Jain Date: Fri, 3 Apr 2026 16:44:32 +0530 Subject: [PATCH 13/21] test: add invalid workflow step example with operationId restriction --- ...-workflow-step-with-operationId.arazzo.yaml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 tests/schema/fail/invalid-workflow-step-with-operationId.arazzo.yaml diff --git a/tests/schema/fail/invalid-workflow-step-with-operationId.arazzo.yaml b/tests/schema/fail/invalid-workflow-step-with-operationId.arazzo.yaml new file mode 100644 index 0000000..194e0e0 --- /dev/null +++ b/tests/schema/fail/invalid-workflow-step-with-operationId.arazzo.yaml @@ -0,0 +1,18 @@ +arazzo: 1.1.0 +info: + title: Workflow step cannot have operationId + version: 1.0.0 +workflows: + - workflowId: parentWorkflow + steps: + - stepId: invalidStep + operationId: getUsers + workflowId: childWorkflow + successCriteria: + - condition: $statusCode == 200 + - workflowId: childWorkflow + steps: + - stepId: childStep + operationId: listUsers + successCriteria: + - condition: $statusCode == 200 From 471e32765e9891bb84f24b1ff2a1468e62edfafa Mon Sep 17 00:00:00 2001 From: Naresh Jain Date: Fri, 3 Apr 2026 17:13:08 +0530 Subject: [PATCH 14/21] fix: clarify description of dependsOn field in schema.yaml and update formatting in arazzo.md --- src/arazzo.md | 36 +++++++++++++++--------------- src/schemas/validation/schema.yaml | 2 +- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/arazzo.md b/src/arazzo.md index a009444..0245a3a 100644 --- a/src/arazzo.md +++ b/src/arazzo.md @@ -327,24 +327,24 @@ Describes a single workflow step which MAY be a call to an API operation ([OpenA ##### Fixed Fields -| Field Name | Type | Description | -|---------------------------------------------------|:----------------------------------------------------------------------------------------:|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| description | `string` | A description of the step. [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation. | -| stepId | `string` | **REQUIRED**. Unique string to represent the step. The `stepId` MUST be unique amongst all steps described in the workflow. The `stepId` value is **case-sensitive**. Tools and libraries MAY use the `stepId` to uniquely identify a workflow step, therefore, it is RECOMMENDED to follow common programming naming conventions. SHOULD conform to the regular expression `[A-Za-z0-9_\-]+`. | -| operationId | `string` | The name of an existing, resolvable operation, as defined with a unique `operationId` and existing within one of the `sourceDescriptions`. The referenced operation will be invoked by this workflow step. If multiple (non `arazzo` type) `sourceDescriptions` are defined, then the `operationId` MUST be specified using a [Runtime Expression](#runtime-expressions) (e.g., `$sourceDescriptions..`) to avoid ambiguity or potential clashes. This field is mutually exclusive of the `operationPath` and `workflowId` fields respectively. | -| operationPath | `string` | A reference to a [Source Description Object](#source-description-object) combined with a [JSON Pointer](https://tools.ietf.org/html/rfc6901) to reference an operation. This field is mutually exclusive of the `operationId` and `workflowId` fields respectively. The operation being referenced MUST be described within one of the `sourceDescriptions` descriptions. A [Runtime Expression](#runtime-expressions) syntax MUST be used to identify the source description document. If the referenced operation has an `operationId` defined then the `operationId` SHOULD be preferred over the `operationPath`. | -| channelPath | `string` | A reference to a [Source Description Object](#source-description-object) combined with a [JSON Pointer](https://tools.ietf.org/html/rfc6901) to reference an event channel. This field is mutually exclusive of the `operationId` and `workflowId` fields respectively. The operation being referenced MUST be described within one of the `sourceDescriptions` descriptions. A [Runtime Expression](#runtime-expressions) syntax MUST be used to identify the source description document. If the referenced operation has an `operationId` defined then the `operationId` SHOULD be preferred over the `channelPath`. | -| workflowId | `string` | The [workflowId](#fixed-fields-2) referencing an existing workflow within the Arazzo Description. If the referenced workflow is contained within an `arazzo` type `sourceDescription`, then the `workflowId` MUST be specified using a [Runtime Expression](#runtime-expressions) (e.g., `$sourceDescriptions..`) to avoid ambiguity or potential clashes. The field is mutually exclusive of the `operationId` and `operationPath` fields respectively. | -| parameters | [[Parameter Object](#parameter-object) \| [Reusable Object](#reusable-object)] | A list of parameters that MUST be passed to an operation or workflow as referenced by `operationId`, `operationPath`, or `workflowId`. If a parameter is already defined at the [Workflow](#workflow-object), the new definition will override it but can never remove it. If a Reusable Object is provided, it MUST link to a parameter defined in the [components/parameters](#components-object) of the current Arazzo document. The list MUST NOT include duplicate parameters. | -| requestBody | [Request Body Object](#request-body-object) | The request body to pass to an operation as referenced by `operationId` or `operationPath`. The `requestBody` is fully supported in HTTP methods where the HTTP 1.1 specification [RFC9110](https://tools.ietf.org/html/rfc9110#section-9.3) explicitly defines semantics for "content" like request bodies, such as within POST, PUT, and PATCH methods. For methods where the HTTP specification provides less clarity—such as GET, HEAD, and DELETE—the use of `requestBody` is permitted but does not have well-defined semantics. In these cases, its use SHOULD be avoided if possible. | -| successCriteria | [[Criterion Object](#criterion-object)] | A list of assertions to determine the success of the step. Each assertion is described using a [Criterion Object](#criterion-object). All assertions `MUST` be satisfied for the step to be deemed successful. `MUST` contain at least one [Criterion Object](#criterion-object) | -| onSuccess | [[Success Action Object](#success-action-object) \| [Reusable Object](#reusable-object)] | An array of success action objects that specify what to do upon step success. If omitted, the next sequential step shall be executed as the default behavior. If multiple success actions have similar `criteria`, the first sequential action matching the criteria SHALL be the action executed. If a success action is already defined at the [Workflow](#workflow-object), the new definition will override it but can never remove it. If a Reusable Object is provided, it MUST link to a success action defined in the [components](#components-object) of the current Arazzo document. The list MUST NOT include duplicate success actions. | -| onFailure | [[Failure Action Object](#failure-action-object) \| [Reusable Object](#reusable-object)] | An array of failure action objects that specify what to do upon step failure. If omitted, the default behavior is to break and return. If multiple failure actions have similar `criteria`, the first sequential action matching the criteria SHALL be the action executed. If a failure action is already defined at the [Workflow](#workflow-object), the new definition will override it but can never remove it. If a Reusable Object is provided, it MUST link to a failure action defined in the [components](#components-object) of the current Arazzo document. The list MUST NOT include duplicate failure actions. | -| outputs | Map[`string`, {expression} \| [Selector Object](#selector-object)] | A map between a friendly name and a dynamic output value defined using a [Runtime Expression](#runtime-expressions) or [Selector Object](#selector-object). The name MUST use keys that match the regular expression: `^[a-zA-Z0-9\.\-_]+$`. | -| timeout | `integer` | The maximum number of milli-seconds to wait for the step to complete before aborting and failing the step. Consequently this will fail the workflow unless failureActions are defined. | -| correlationId | `string` | A correlationId in AsyncAPI links a request with its response (or more broadly, to trace a single logical transaction across multiple asynchronous messages). Only applicable to `asyncapi` steps with action `receive` and has to be in-sync with correlationId defined in the AsyncAPI document. | -| action | `send or receive` | Describes the intent of the message flow. Indicates whether the step will send (publish) or receive (subscribe) to a message on a channel described in an AsyncAPI document, Only applicable for `asyncapi` steps. | -| dependsOn | List[`string`] | A list of steps that MUST be completed before this step can be executed. Each value provided MUST be a `stepId`. The `stepId` value is case-sensitive. If the step depended on is defined within the **current workflow**, specify the `stepId` directly (e.g., `authStep`). If the step is defined in a **different workflow within the current Arazzo Document**, reference it using `$workflows..steps.`. If the step is defined in a **separate Arazzo Document**, the workflow MUST be defined in `sourceDescriptions` and referenced using `$sourceDescriptions...steps.` to avoid ambiguity. If your step depends on the output of a non-blocking/asynchronous step, then you SHOULD use `dependsOn` and refer to the async step using one of these patterns. | +| Field Name | Type | Description | +|---------------------------------------------------|:----------------------------------------------------------------------------------------:|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| description | `string` | A description of the step. [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation. | +| stepId | `string` | **REQUIRED**. Unique string to represent the step. The `stepId` MUST be unique amongst all steps described in the workflow. The `stepId` value is **case-sensitive**. Tools and libraries MAY use the `stepId` to uniquely identify a workflow step, therefore, it is RECOMMENDED to follow common programming naming conventions. SHOULD conform to the regular expression `[A-Za-z0-9_\-]+`. | +| operationId | `string` | The name of an existing, resolvable operation, as defined with a unique `operationId` and existing within one of the `sourceDescriptions`. The referenced operation will be invoked by this workflow step. If multiple (non `arazzo` type) `sourceDescriptions` are defined, then the `operationId` MUST be specified using a [Runtime Expression](#runtime-expressions) (e.g., `$sourceDescriptions..`) to avoid ambiguity or potential clashes. This field is mutually exclusive of the `operationPath` and `workflowId` fields respectively. | +| operationPath | `string` | A reference to a [Source Description Object](#source-description-object) combined with a [JSON Pointer](https://tools.ietf.org/html/rfc6901) to reference an operation. This field is mutually exclusive of the `operationId` and `workflowId` fields respectively. The operation being referenced MUST be described within one of the `sourceDescriptions` descriptions. A [Runtime Expression](#runtime-expressions) syntax MUST be used to identify the source description document. If the referenced operation has an `operationId` defined then the `operationId` SHOULD be preferred over the `operationPath`. | +| channelPath | `string` | A reference to a [Source Description Object](#source-description-object) combined with a [JSON Pointer](https://tools.ietf.org/html/rfc6901) to reference an event channel. This field is mutually exclusive of the `operationId` and `workflowId` fields respectively. The operation being referenced MUST be described within one of the `sourceDescriptions` descriptions. A [Runtime Expression](#runtime-expressions) syntax MUST be used to identify the source description document. If the referenced operation has an `operationId` defined then the `operationId` SHOULD be preferred over the `channelPath`. | +| workflowId | `string` | The [workflowId](#fixed-fields-2) referencing an existing workflow within the Arazzo Description. If the referenced workflow is contained within an `arazzo` type `sourceDescription`, then the `workflowId` MUST be specified using a [Runtime Expression](#runtime-expressions) (e.g., `$sourceDescriptions..`) to avoid ambiguity or potential clashes. The field is mutually exclusive of the `operationId` and `operationPath` fields respectively. | +| parameters | [[Parameter Object](#parameter-object) \| [Reusable Object](#reusable-object)] | A list of parameters that MUST be passed to an operation or workflow as referenced by `operationId`, `operationPath`, or `workflowId`. If a parameter is already defined at the [Workflow](#workflow-object), the new definition will override it but can never remove it. If a Reusable Object is provided, it MUST link to a parameter defined in the [components/parameters](#components-object) of the current Arazzo document. The list MUST NOT include duplicate parameters. | +| requestBody | [Request Body Object](#request-body-object) | The request body to pass to an operation as referenced by `operationId` or `operationPath`. The `requestBody` is fully supported in HTTP methods where the HTTP 1.1 specification [RFC9110](https://tools.ietf.org/html/rfc9110#section-9.3) explicitly defines semantics for "content" like request bodies, such as within POST, PUT, and PATCH methods. For methods where the HTTP specification provides less clarity—such as GET, HEAD, and DELETE—the use of `requestBody` is permitted but does not have well-defined semantics. In these cases, its use SHOULD be avoided if possible. | +| successCriteria | [[Criterion Object](#criterion-object)] | A list of assertions to determine the success of the step. Each assertion is described using a [Criterion Object](#criterion-object). All assertions `MUST` be satisfied for the step to be deemed successful. `MUST` contain at least one [Criterion Object](#criterion-object) | +| onSuccess | [[Success Action Object](#success-action-object) \| [Reusable Object](#reusable-object)] | An array of success action objects that specify what to do upon step success. If omitted, the next sequential step shall be executed as the default behavior. If multiple success actions have similar `criteria`, the first sequential action matching the criteria SHALL be the action executed. If a success action is already defined at the [Workflow](#workflow-object), the new definition will override it but can never remove it. If a Reusable Object is provided, it MUST link to a success action defined in the [components](#components-object) of the current Arazzo document. The list MUST NOT include duplicate success actions. | +| onFailure | [[Failure Action Object](#failure-action-object) \| [Reusable Object](#reusable-object)] | An array of failure action objects that specify what to do upon step failure. If omitted, the default behavior is to break and return. If multiple failure actions have similar `criteria`, the first sequential action matching the criteria SHALL be the action executed. If a failure action is already defined at the [Workflow](#workflow-object), the new definition will override it but can never remove it. If a Reusable Object is provided, it MUST link to a failure action defined in the [components](#components-object) of the current Arazzo document. The list MUST NOT include duplicate failure actions. | +| outputs | Map[`string`, {expression} \| [Selector Object](#selector-object)] | A map between a friendly name and a dynamic output value defined using a [Runtime Expression](#runtime-expressions) or [Selector Object](#selector-object). The name MUST use keys that match the regular expression: `^[a-zA-Z0-9\.\-_]+$`. | +| timeout | `integer` | The maximum number of milli-seconds to wait for the step to complete before aborting and failing the step. Consequently this will fail the workflow unless failureActions are defined. | +| correlationId | `string` | A correlationId in AsyncAPI links a request with its response (or more broadly, to trace a single logical transaction across multiple asynchronous messages). Only applicable to `asyncapi` steps with action `receive` and has to be in-sync with correlationId defined in the AsyncAPI document. | +| action | `send or receive` | Describes the intent of the message flow. Indicates whether the step will send (publish) or receive (subscribe) to a message on a channel described in an AsyncAPI document, Only applicable for `asyncapi` steps. | +| dependsOn | List[`string`] | A list of steps that MUST be completed before this step can be executed. `dependsOn` only establishes a prerequisite relationship for the current step and does not trigger execution of the referenced steps. Each value provided MUST be a `stepId`. The `stepId` value is case-sensitive. If the step depended on is defined within the **current workflow**, specify the `stepId` directly (e.g., `authStep`). If the step is defined in a **different workflow within the current Arazzo Document**, reference it using `$workflows..steps.`. If the step is defined in a **separate Arazzo Document**, the workflow MUST be defined in `sourceDescriptions` and referenced using `$sourceDescriptions...steps.` to avoid ambiguity. If your step depends on the output of a non-blocking/asynchronous step, then you SHOULD use `dependsOn` and refer to the async step using one of these patterns. | This object MAY be extended with [Specification Extensions](#specification-extensions). diff --git a/src/schemas/validation/schema.yaml b/src/schemas/validation/schema.yaml index 24b2a8f..6589abc 100644 --- a/src/schemas/validation/schema.yaml +++ b/src/schemas/validation/schema.yaml @@ -179,7 +179,7 @@ $defs: description: The duration in milliseconds to wait before timing out the step type: integer dependsOn: - description: Specifies a list of step identifiers that must complete (or be waited for) before the current step can begin execution. Steps referred by dependsOn SHOULD be non-blocking/async steps. Steps in the current workflow MUST be referenced directly by stepId. Steps in another workflow in the same Arazzo document MUST use $workflows..steps.. Steps in another Arazzo document MUST use $sourceDescriptions...steps.. + description: Specifies a list of step identifiers that must complete (or be waited for) before the current step can begin execution. `dependsOn` only establishes a prerequisite relationship for the current step and does not trigger execution of the referenced steps. Steps referred by dependsOn SHOULD be non-blocking/async steps. Steps in the current workflow MUST be referenced directly by stepId. Steps in another workflow in the same Arazzo document MUST use $workflows..steps.. Steps in another Arazzo document MUST use $sourceDescriptions...steps.. type: array uniqueItems: true minItems: 1 From 0daa4d7b2af72c1d2b016dd054df1c7e3e3f3cea Mon Sep 17 00:00:00 2001 From: Naresh Jain Date: Thu, 9 Apr 2026 22:39:28 +0530 Subject: [PATCH 15/21] fix: remove fully qualified dependsOn field from async-depends-on.yaml --- tests/schema/pass/async-depends-on.arazzo.yaml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/tests/schema/pass/async-depends-on.arazzo.yaml b/tests/schema/pass/async-depends-on.arazzo.yaml index f034287..8747abe 100644 --- a/tests/schema/pass/async-depends-on.arazzo.yaml +++ b/tests/schema/pass/async-depends-on.arazzo.yaml @@ -24,15 +24,6 @@ workflows: action: send dependsOn: - step2 - parameters: - - name: userId - in: header - value: $steps.step2.outputs.userId - - stepId: step4 - operationId: deleteUser - action: send - dependsOn: - - $workflows.dependsOnWorkflow.steps.step2 parameters: - name: userId in: header From 39364e413db1de705bcd17b72ed85e69129e2b96 Mon Sep 17 00:00:00 2001 From: Naresh Jain Date: Wed, 15 Apr 2026 10:36:58 +0530 Subject: [PATCH 16/21] fix: refactor step schema to isolate operation-specific fields and deduplicate operation step parameter rules --- src/schemas/validation/schema.yaml | 52 +++++++------------ ...relation-id-non-receive-action.arazzo.yaml | 2 +- ...lid-async-parameter-without-in.arazzo.yaml | 17 ++++++ ...d-openapi-parameter-without-in.arazzo.yaml | 18 +++++++ ...workflow-step-with-operationId.arazzo.yaml | 4 ++ ...alid-workflow-success-criteria.arazzo.yaml | 4 ++ .../pass/async-parameter-with-in.arazzo.yaml | 18 +++++++ .../openapi-parameter-with-in.arazzo.yaml | 19 +++++++ .../workflow-parameter-without-in.arazzo.yaml | 27 ++++++++++ 9 files changed, 127 insertions(+), 34 deletions(-) create mode 100644 tests/schema/fail/invalid-async-parameter-without-in.arazzo.yaml create mode 100644 tests/schema/fail/invalid-openapi-parameter-without-in.arazzo.yaml create mode 100644 tests/schema/pass/async-parameter-with-in.arazzo.yaml create mode 100644 tests/schema/pass/openapi-parameter-with-in.arazzo.yaml create mode 100644 tests/schema/pass/workflow-parameter-without-in.arazzo.yaml diff --git a/src/schemas/validation/schema.yaml b/src/schemas/validation/schema.yaml index 6589abc..127a942 100644 --- a/src/schemas/validation/schema.yaml +++ b/src/schemas/validation/schema.yaml @@ -172,9 +172,6 @@ $defs: description: description: A description of the step. CommonMark syntax MAY be used for rich text representation type: string - operationId: - description: The name of an existing, resolvable operation, as defined with a unique operationId and existing within one of the sourceDescriptions - type: string timeout: description: The duration in milliseconds to wait before timing out the step type: integer @@ -233,29 +230,28 @@ $defs: - $ref: '#/$defs/selector-object' required: - stepId + operation-step-parameters: + type: array + uniqueItems: true + items: + oneOf: + - $ref: '#/$defs/reusable-object' + - $ref: '#/$defs/parameter-object' + required: + - in openapi-step-object: allOf: - $ref: '#/$defs/step-object-base' - type: object properties: + operationId: + description: The name of an existing, resolvable operation, as defined with a unique operationId and existing within one of the sourceDescriptions + type: string operationPath: description: A reference to a Source combined with a JSON Pointer to reference an operation type: string - - if: - oneOf: - - required: - - operationPath - - required: - - operationId - then: - properties: - parameters: - items: - oneOf: - - $ref: '#/$defs/reusable-object' - - $ref: '#/$defs/parameter-object' - required: - - in + parameters: + $ref: '#/$defs/operation-step-parameters' - oneOf: - required: - operationId @@ -268,6 +264,9 @@ $defs: - $ref: '#/$defs/step-object-base' - type: object properties: + operationId: + description: The name of an existing, resolvable operation, as defined with a unique operationId and existing within one of the sourceDescriptions + type: string channelPath: description: A reference to a Source combined with a JSON Pointer to reference an async channel type: string @@ -284,23 +283,10 @@ $defs: enum: - send - receive + parameters: + $ref: '#/$defs/operation-step-parameters' required: - action - - if: - oneOf: - - required: - - operationId - - required: - - channelPath - then: - properties: - parameters: - items: - oneOf: - - $ref: '#/$defs/reusable-object' - - $ref: '#/$defs/parameter-object' - required: - - in - if: required: - correlationId diff --git a/tests/schema/fail/invalid-async-correlation-id-non-receive-action.arazzo.yaml b/tests/schema/fail/invalid-async-correlation-id-non-receive-action.arazzo.yaml index cfdd9a6..2d69b4b 100644 --- a/tests/schema/fail/invalid-async-correlation-id-non-receive-action.arazzo.yaml +++ b/tests/schema/fail/invalid-async-correlation-id-non-receive-action.arazzo.yaml @@ -1,6 +1,6 @@ arazzo: 1.1.0 info: - title: Minimal Arazzo Example for AsyncAPI + title: CorrelationId should only be present when action is receive version: 1.0.0 sourceDescriptions: - name: exampleAPI diff --git a/tests/schema/fail/invalid-async-parameter-without-in.arazzo.yaml b/tests/schema/fail/invalid-async-parameter-without-in.arazzo.yaml new file mode 100644 index 0000000..0a12436 --- /dev/null +++ b/tests/schema/fail/invalid-async-parameter-without-in.arazzo.yaml @@ -0,0 +1,17 @@ +arazzo: 1.1.0 +info: + title: Async step parameter requires in + version: 1.0.0 +sourceDescriptions: + - name: eventAPI + url: https://events.com/asyncapi.yaml + type: asyncapi +workflows: + - workflowId: asyncWorkflow + steps: + - stepId: sendEvent + operationId: $sourceDescriptions.eventAPI.orderCreated + action: send + parameters: + - name: correlationId + value: abc123 diff --git a/tests/schema/fail/invalid-openapi-parameter-without-in.arazzo.yaml b/tests/schema/fail/invalid-openapi-parameter-without-in.arazzo.yaml new file mode 100644 index 0000000..2fae835 --- /dev/null +++ b/tests/schema/fail/invalid-openapi-parameter-without-in.arazzo.yaml @@ -0,0 +1,18 @@ +arazzo: 1.1.0 +info: + title: OpenAPI step parameter requires in + version: 1.0.0 +sourceDescriptions: + - name: userAPI + url: https://users.com/openapi.yaml + type: openapi +workflows: + - workflowId: openapiWorkflow + steps: + - stepId: getUsers + operationId: $sourceDescriptions.userAPI.listUsers + parameters: + - name: limit + value: 10 + successCriteria: + - condition: $statusCode == 200 diff --git a/tests/schema/fail/invalid-workflow-step-with-operationId.arazzo.yaml b/tests/schema/fail/invalid-workflow-step-with-operationId.arazzo.yaml index 194e0e0..b7a6284 100644 --- a/tests/schema/fail/invalid-workflow-step-with-operationId.arazzo.yaml +++ b/tests/schema/fail/invalid-workflow-step-with-operationId.arazzo.yaml @@ -2,6 +2,10 @@ arazzo: 1.1.0 info: title: Workflow step cannot have operationId version: 1.0.0 +sourceDescriptions: + - name: exampleAPI + url: https://example.com/asyncapi.yaml + type: asyncapi workflows: - workflowId: parentWorkflow steps: diff --git a/tests/schema/fail/invalid-workflow-success-criteria.arazzo.yaml b/tests/schema/fail/invalid-workflow-success-criteria.arazzo.yaml index 3f6e5e5..5201af4 100644 --- a/tests/schema/fail/invalid-workflow-success-criteria.arazzo.yaml +++ b/tests/schema/fail/invalid-workflow-success-criteria.arazzo.yaml @@ -2,6 +2,10 @@ arazzo: 1.1.0 info: title: Invalid workflow step success criteria version: 1.0.0 +sourceDescriptions: + - name: exampleAPI + url: https://example.com/asyncapi.yaml + type: asyncapi workflows: - workflowId: parentWorkflow steps: diff --git a/tests/schema/pass/async-parameter-with-in.arazzo.yaml b/tests/schema/pass/async-parameter-with-in.arazzo.yaml new file mode 100644 index 0000000..fb15fd1 --- /dev/null +++ b/tests/schema/pass/async-parameter-with-in.arazzo.yaml @@ -0,0 +1,18 @@ +arazzo: 1.1.0 +info: + title: Async step parameter with in + version: 1.0.0 +sourceDescriptions: + - name: eventAPI + url: https://events.com/asyncapi.yaml + type: asyncapi +workflows: + - workflowId: asyncWorkflow + steps: + - stepId: sendEvent + operationId: $sourceDescriptions.eventAPI.orderCreated + action: send + parameters: + - name: correlationId + in: header + value: abc123 diff --git a/tests/schema/pass/openapi-parameter-with-in.arazzo.yaml b/tests/schema/pass/openapi-parameter-with-in.arazzo.yaml new file mode 100644 index 0000000..3224b51 --- /dev/null +++ b/tests/schema/pass/openapi-parameter-with-in.arazzo.yaml @@ -0,0 +1,19 @@ +arazzo: 1.1.0 +info: + title: OpenAPI step parameter with in + version: 1.0.0 +sourceDescriptions: + - name: userAPI + url: https://users.com/openapi.yaml + type: openapi +workflows: + - workflowId: openapiWorkflow + steps: + - stepId: getUsers + operationId: $sourceDescriptions.userAPI.listUsers + parameters: + - name: limit + in: query + value: 10 + successCriteria: + - condition: $statusCode == 200 diff --git a/tests/schema/pass/workflow-parameter-without-in.arazzo.yaml b/tests/schema/pass/workflow-parameter-without-in.arazzo.yaml new file mode 100644 index 0000000..21749a8 --- /dev/null +++ b/tests/schema/pass/workflow-parameter-without-in.arazzo.yaml @@ -0,0 +1,27 @@ +arazzo: 1.1.0 +info: + title: Workflow step parameter does not require in + version: 1.0.0 +sourceDescriptions: + - name: userAPI + url: https://users.com/openapi.yaml + type: openapi +workflows: + - workflowId: parentWorkflow + steps: + - stepId: nestedWorkflow + workflowId: childWorkflow + parameters: + - name: userId + value: 10 + - workflowId: childWorkflow + inputs: + type: object + properties: + userId: + type: integer + steps: + - stepId: childStep + operationId: $sourceDescriptions.userAPI.listUsers + successCriteria: + - condition: $statusCode == 200 From 54148032281c0e2c3ee1374ccf01e4ce09579f8f Mon Sep 17 00:00:00 2001 From: Naresh Jain Date: Thu, 16 Apr 2026 00:19:40 +0530 Subject: [PATCH 17/21] chore: move pet-asyncapi.yaml to examples folder --- {src/specifications => examples/1.1.0}/pet-asyncapi.yaml | 0 src/arazzo.md | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename {src/specifications => examples/1.1.0}/pet-asyncapi.yaml (100%) diff --git a/src/specifications/pet-asyncapi.yaml b/examples/1.1.0/pet-asyncapi.yaml similarity index 100% rename from src/specifications/pet-asyncapi.yaml rename to examples/1.1.0/pet-asyncapi.yaml diff --git a/src/arazzo.md b/src/arazzo.md index 67c0e68..a32062c 100644 --- a/src/arazzo.md +++ b/src/arazzo.md @@ -223,7 +223,7 @@ sourceDescriptions: url: https://github.com/swagger-api/swagger-petstore/blob/master/src/main/resources/openapi.yaml type: openapi - name: asyncOrderApiDescription - url: https://github.com/OAI/Arazzo-Specification/blob/dev/src/specification/order-asyncapi.yaml + url: https://raw.githubusercontent.com/OAI/Arazzo-Specification/main/examples/1.1.0/pet-asyncapi.yaml type: asyncapi workflows: From cc7e8ff0c9a0264dcee6c0bdb4730f1c370b0c08 Mon Sep 17 00:00:00 2001 From: Naresh Jain Date: Fri, 17 Apr 2026 21:53:06 +0530 Subject: [PATCH 18/21] docs: clarify async workflow step dependencies and success criteria --- src/arazzo.md | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/src/arazzo.md b/src/arazzo.md index a32062c..c01822c 100644 --- a/src/arazzo.md +++ b/src/arazzo.md @@ -432,13 +432,49 @@ Describes a single workflow step which MAY be a call to an API operation ([OpenA | onSuccess | [[Success Action Object](#success-action-object) \| [Reusable Object](#reusable-object)] | An array of success action objects that specify what to do upon step success. If omitted, the next sequential step shall be executed as the default behavior. If multiple success actions have similar `criteria`, the first sequential action matching the criteria SHALL be the action executed. If a success action is already defined at the [Workflow](#workflow-object), the new definition will override it but can never remove it. If a Reusable Object is provided, it MUST link to a success action defined in the [components](#components-object) of the current Arazzo document. The list MUST NOT include duplicate success actions. | | onFailure | [[Failure Action Object](#failure-action-object) \| [Reusable Object](#reusable-object)] | An array of failure action objects that specify what to do upon step failure. If omitted, the default behavior is to break and return. If multiple failure actions have similar `criteria`, the first sequential action matching the criteria SHALL be the action executed. If a failure action is already defined at the [Workflow](#workflow-object), the new definition will override it but can never remove it. If a Reusable Object is provided, it MUST link to a failure action defined in the [components](#components-object) of the current Arazzo document. The list MUST NOT include duplicate failure actions. | | outputs | Map[`string`, {expression} \| [Selector Object](#selector-object)] | A map between a friendly name and a dynamic output value defined using a [Runtime Expression](#runtime-expressions) or [Selector Object](#selector-object). The name MUST use keys that match the regular expression: `^[a-zA-Z0-9\.\-_]+$`. | -| timeout | `integer` | The maximum number of milli-seconds to wait for the step to complete before aborting and failing the step. Consequently this will fail the workflow unless failureActions are defined. | +| timeout | `integer` | The maximum number of milli-seconds to wait for the step to complete before aborting and failing the step. Consequently this will fail the workflow unless `onFailure` actions are defined. | | correlationId | `string` | A correlationId in AsyncAPI links a request with its response (or more broadly, to trace a single logical transaction across multiple asynchronous messages). Only applicable to `asyncapi` steps with action `receive` and has to be in-sync with correlationId defined in the AsyncAPI document. | | action | `send or receive` | Describes the intent of the message flow. Indicates whether the step will send (publish) or receive (subscribe) to a message on a channel described in an AsyncAPI document, Only applicable for `asyncapi` steps. | | dependsOn | List[`string`] | A list of steps that MUST be completed before this step can be executed. `dependsOn` only establishes a prerequisite relationship for the current step and does not trigger execution of the referenced steps. Each value provided MUST be a `stepId`. The `stepId` value is case-sensitive. If the step depended on is defined within the **current workflow**, specify the `stepId` directly (e.g., `authStep`). If the step is defined in a **different workflow within the current Arazzo Document**, reference it using `$workflows..steps.`. If the step is defined in a **separate Arazzo Document**, the workflow MUST be defined in `sourceDescriptions` and referenced using `$sourceDescriptions...steps.` to avoid ambiguity. If your step depends on the output of a non-blocking/asynchronous step, then you SHOULD use `dependsOn` and refer to the async step using one of these patterns. | This object MAY be extended with [Specification Extensions](#specification-extensions). +##### Step Dependencies and Execution Order + +The `dependsOn` field at the step level is primarily intended to coordinate asynchronous operations. + +**Recommended Approach for Synchronous Workflows** + +For workflows containing only synchronous steps, the RECOMMENDED approach is to order steps sequentially in the steps array without using `dependsOn`. This provides the simplest and clearest execution model. Step-level `dependsOn` is typically unnecessary when all operations complete synchronously and execution follows a linear path. + +**Use Case: Async Coordination** + +When a step must wait for an asynchronous operation to complete before proceeding, `dependsOn` establishes a join point for in-flight async work. For example, a step that requests an order status SHOULD declare `dependsOn` on the step that receives order creation status from an async order placement, even if no explicit output reference exists. This ensures the async operation completes before the dependent step executes. + +**Authoring Guidance** + +For async workflows, authors SHOULD use `dependsOn` to explicitly declare when a step must wait for async work to complete, regardless of output references. This is the intended use case for step-level dependencies. + +**Tool Behavior** + +Tools MUST respect all declared `dependsOn` relationships. Tools MUST also treat runtime expression output references (e.g., `$steps.stepId.outputs.field`) as implicit dependencies and ensure the referenced step completes before the referencing step executes. + +Tools supporting only sequential execution MUST execute steps in an order that satisfies both explicit (`dependsOn`) and implicit (output reference) dependencies. + +**Validation Recommendations** + +Implementations SHOULD validate the following scenario: + +When no `dependsOn` is used in a workflow (sequential execution model), implementations SHOULD produce an error if a step references another step's outputs where the referenced step appears later in the steps array. This indicates a forward reference that cannot be satisfied in sequential execution. + +##### Defining Success for Asynchronous Steps + +For steps that reference AsyncAPI operations (via `operationId` or `channelPath`), tools will send or receive messages on the specified channel as defined by the referenced AsyncAPI description. For AsyncAPI send operations, the step completes immediately after the message is sent. Arazzo does not model broker acknowledgment or delivery confirmation. For AsyncAPI receive operations, step completion depends on message receipt as described below. + +Because AsyncAPI channels MAY define multiple message types, and because message payloads MAY represent either success or failure conditions, authors MUST use `successCriteria` to explicitly define what constitutes step completion for AsyncAPI receive steps. The `successCriteria` SHOULD evaluate the received message payload (for example, via `$message.payload`) to determine whether the step succeeded. + +If `correlationId` is specified, only messages matching the correlation identifier are considered. If no matching message is received within the `timeout` period, the step fails and triggers any defined `onFailure` actions. + ##### Step Object Examples A single step example: From b672729e721946432d37e97a33ad096125b9a9c7 Mon Sep 17 00:00:00 2001 From: Naresh Jain Date: Fri, 17 Apr 2026 21:56:29 +0530 Subject: [PATCH 19/21] docs: fix markdown headings --- src/arazzo.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/arazzo.md b/src/arazzo.md index c01822c..5139308 100644 --- a/src/arazzo.md +++ b/src/arazzo.md @@ -443,25 +443,25 @@ This object MAY be extended with [Specification Extensions](#specification-exten The `dependsOn` field at the step level is primarily intended to coordinate asynchronous operations. -**Recommended Approach for Synchronous Workflows** +###### Recommended Approach for Synchronous Workflows For workflows containing only synchronous steps, the RECOMMENDED approach is to order steps sequentially in the steps array without using `dependsOn`. This provides the simplest and clearest execution model. Step-level `dependsOn` is typically unnecessary when all operations complete synchronously and execution follows a linear path. -**Use Case: Async Coordination** +###### Use Case: Async Coordination When a step must wait for an asynchronous operation to complete before proceeding, `dependsOn` establishes a join point for in-flight async work. For example, a step that requests an order status SHOULD declare `dependsOn` on the step that receives order creation status from an async order placement, even if no explicit output reference exists. This ensures the async operation completes before the dependent step executes. -**Authoring Guidance** +###### Authoring Guidance For async workflows, authors SHOULD use `dependsOn` to explicitly declare when a step must wait for async work to complete, regardless of output references. This is the intended use case for step-level dependencies. -**Tool Behavior** +###### Tool Behavior Tools MUST respect all declared `dependsOn` relationships. Tools MUST also treat runtime expression output references (e.g., `$steps.stepId.outputs.field`) as implicit dependencies and ensure the referenced step completes before the referencing step executes. Tools supporting only sequential execution MUST execute steps in an order that satisfies both explicit (`dependsOn`) and implicit (output reference) dependencies. -**Validation Recommendations** +###### Validation Recommendations Implementations SHOULD validate the following scenario: From fe5913d7216f4149ea3e44e263873e50cc8322de Mon Sep 17 00:00:00 2001 From: Naresh Jain Date: Fri, 17 Apr 2026 23:23:14 +0530 Subject: [PATCH 20/21] docs: clarify async step dependencies and completion semantics --- src/arazzo.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/arazzo.md b/src/arazzo.md index 5139308..5d0380a 100644 --- a/src/arazzo.md +++ b/src/arazzo.md @@ -428,7 +428,7 @@ Describes a single workflow step which MAY be a call to an API operation ([OpenA | workflowId | `string` | The [workflowId](#fixed-fields-2) referencing an existing workflow within the Arazzo Description. If the referenced workflow is contained within an `arazzo` type `sourceDescription`, then the `workflowId` MUST be specified using a [Runtime Expression](#runtime-expressions) (e.g., `$sourceDescriptions..`) to avoid ambiguity or potential clashes. The field is mutually exclusive of the `operationId` and `operationPath` fields respectively. | | parameters | [[Parameter Object](#parameter-object) \| [Reusable Object](#reusable-object)] | A list of parameters that MUST be passed to an operation or workflow as referenced by `operationId`, `operationPath`, or `workflowId`. If a parameter is already defined at the [Workflow](#workflow-object), the new definition will override it but can never remove it. If a Reusable Object is provided, it MUST link to a parameter defined in the [components/parameters](#components-object) of the current Arazzo document. The list MUST NOT include duplicate parameters. | | requestBody | [Request Body Object](#request-body-object) | The request body to pass to an operation as referenced by `operationId` or `operationPath`. The `requestBody` is fully supported in HTTP methods where the HTTP 1.1 specification [RFC9110](https://tools.ietf.org/html/rfc9110#section-9.3) explicitly defines semantics for "content" like request bodies, such as within POST, PUT, and PATCH methods. For methods where the HTTP specification provides less clarity—such as GET, HEAD, and DELETE—the use of `requestBody` is permitted but does not have well-defined semantics. In these cases, its use SHOULD be avoided if possible. | -| successCriteria | [[Criterion Object](#criterion-object)] | A list of assertions to determine the success of the step. Each assertion is described using a [Criterion Object](#criterion-object). All assertions `MUST` be satisfied for the step to be deemed successful. `MUST` contain at least one [Criterion Object](#criterion-object) | +| successCriteria | [[Criterion Object](#criterion-object)] | A list of assertions to determine the success of the step. Each assertion is described using a [Criterion Object](#criterion-object). All assertions `MUST` be satisfied for the step to be deemed successful. If `successCriteria` is provided, it `MUST` contain at least one [Criterion Object](#criterion-object). | | onSuccess | [[Success Action Object](#success-action-object) \| [Reusable Object](#reusable-object)] | An array of success action objects that specify what to do upon step success. If omitted, the next sequential step shall be executed as the default behavior. If multiple success actions have similar `criteria`, the first sequential action matching the criteria SHALL be the action executed. If a success action is already defined at the [Workflow](#workflow-object), the new definition will override it but can never remove it. If a Reusable Object is provided, it MUST link to a success action defined in the [components](#components-object) of the current Arazzo document. The list MUST NOT include duplicate success actions. | | onFailure | [[Failure Action Object](#failure-action-object) \| [Reusable Object](#reusable-object)] | An array of failure action objects that specify what to do upon step failure. If omitted, the default behavior is to break and return. If multiple failure actions have similar `criteria`, the first sequential action matching the criteria SHALL be the action executed. If a failure action is already defined at the [Workflow](#workflow-object), the new definition will override it but can never remove it. If a Reusable Object is provided, it MUST link to a failure action defined in the [components](#components-object) of the current Arazzo document. The list MUST NOT include duplicate failure actions. | | outputs | Map[`string`, {expression} \| [Selector Object](#selector-object)] | A map between a friendly name and a dynamic output value defined using a [Runtime Expression](#runtime-expressions) or [Selector Object](#selector-object). The name MUST use keys that match the regular expression: `^[a-zA-Z0-9\.\-_]+$`. | @@ -471,7 +471,13 @@ When no `dependsOn` is used in a workflow (sequential execution model), implemen For steps that reference AsyncAPI operations (via `operationId` or `channelPath`), tools will send or receive messages on the specified channel as defined by the referenced AsyncAPI description. For AsyncAPI send operations, the step completes immediately after the message is sent. Arazzo does not model broker acknowledgment or delivery confirmation. For AsyncAPI receive operations, step completion depends on message receipt as described below. -Because AsyncAPI channels MAY define multiple message types, and because message payloads MAY represent either success or failure conditions, authors MUST use `successCriteria` to explicitly define what constitutes step completion for AsyncAPI receive steps. The `successCriteria` SHOULD evaluate the received message payload (for example, via `$message.payload`) to determine whether the step succeeded. +Because AsyncAPI channels MAY define multiple message types, and because message payloads MAY represent either success or failure conditions, authors SHOULD define `successCriteria` for AsyncAPI receive steps to explicitly evaluate the received message payload (for example, via `$message.payload`) and determine whether the step succeeded. + +Authors MAY omit `successCriteria` only when both of the following conditions are met: +- The channel defines a single message type that unambiguously represents successful completion +- The message payload does not contain fields indicating error states (e.g., status codes or error flags) + +When `successCriteria` is omitted, receiving any message matching the `correlationId` (if specified) within the `timeout` period is considered a successful step completion. If `correlationId` is specified, only messages matching the correlation identifier are considered. If no matching message is received within the `timeout` period, the step fails and triggers any defined `onFailure` actions. From 57f98de809aa332dfbad7aa8df756d5dd152fa69 Mon Sep 17 00:00:00 2001 From: Naresh Jain Date: Fri, 17 Apr 2026 23:24:21 +0530 Subject: [PATCH 21/21] docs: clarify async step dependencies and completion semantics --- src/arazzo.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/arazzo.md b/src/arazzo.md index 5d0380a..e6d2ae7 100644 --- a/src/arazzo.md +++ b/src/arazzo.md @@ -474,6 +474,7 @@ For steps that reference AsyncAPI operations (via `operationId` or `channelPath` Because AsyncAPI channels MAY define multiple message types, and because message payloads MAY represent either success or failure conditions, authors SHOULD define `successCriteria` for AsyncAPI receive steps to explicitly evaluate the received message payload (for example, via `$message.payload`) and determine whether the step succeeded. Authors MAY omit `successCriteria` only when both of the following conditions are met: + - The channel defines a single message type that unambiguously represents successful completion - The message payload does not contain fields indicating error states (e.g., status codes or error flags)