- 
                Notifications
    
You must be signed in to change notification settings  - Fork 57
 
Description
Adding support for AsyncAPI definitions would extend the types of workflows that can be described with Arazzo, as many organizations are now combining Request/Response APIs (OpenAPI) with Event-Driven architectures (AsyncAPI).
The latest version of AsyncAPI is v3, but since v2 is still the most widely adopted version, the intention is to provide support for both versions as feasible, and prioritize v3 only when supporting both becomes impractical.
Required Changes to Arazzo Specification
- Add 
asyncapias a source definition type. - Extend the meaning of 
workflow.step.operationIdto include pointing to an AsyncAPIoperationId(either v2 or v3): - Extend the meaning of 
workflow.step.parameters.in:headershould also include AsyncAPI message headers.pathshould include AsyncAPIchannel.parameters, as they are similar to OpenAPIpathparameters (or consider adding achannelvalue for disambiguation).
 - Runtime expressions already include support for 
$message.bodyand$message.headerthis would be used for context in successCriterias 
Additional Considerations for Broker-Intermediated APIs
While AsyncAPI and OpenAPI are similar, and it’s tempting to use the operationId in AsyncAPI, there is a key difference: broker-mediated APIs are reciprocal (publishing/sending on one side is subscribing/receiving on the other).
- Sometimes, an API might only document one side’s perspective. For example:
- A service that publishes events might document its "publish" operations.
 - However, it might not document the "subscribe" operation that consumers would use to receive these events (consumers just use the "publish" operation documentation and tooling).
 
 - Teams and organizations may model this symmetry differently, and sometimes the "inverse" operation may not be defined at all.
 
To support this, we would need an alternative way to reference the reciprocal operation.
Additional Changes to Arazzo Specification
When the desired operationId is not documented in the existing AsyncAPI, we can support referencing the channel instead of the operation and specify the reciprocal action (send|receive).
- Add 
workflow.step.channelas a fixed field pointing to an AsyncAPI channel: - Add 
workflow.step.actionwith supported valuessend|receive. 
The combination of channel+action would be mutually exclusive with operationId, with operationId being the preferred option when available.
Meaning of AsyncAPI Steps
Send/Publish
A workflow step pointing to a Send/Publish operation will send a message with the workflow.step.requestBody.
workflow.step.parameters will also be used to populate AsyncAPI message.headers and channel.parameters.
The only meaningful successCriteria is "OK, message accepted," so it may be omitted.
This action is non-blocking and has no outputs; it will immediately continue to the next step, either onSuccess or onFailure.
This is an example of a workflow step sending a message:
  - stepId: "send_order_received"
    operationId: "$sourceDescriptions.OrdersAsyncAPI.onOrderEvent"
    requestBody:
      contentType: "application/json"
      payload: |-
        {
            "id": "{$steps.place_order.outputs.orderId}",
            "orderTime": "{$steps.place_order.outputs.order.orderTime}",
            "status": "RECEIVED",
            "customerDetails": {$steps.fetch_customer_details.outputs.customer},
            "restaurantDetails": {$steps.fetch_restaurant_details.outputs.restaurant},
            "orderItems": [
            {$inputs.menuItem}
            ]
        }
    onSuccess:
    - name: "goto_wait_for_downstream"
      type: "goto"
      stepId: "wait_RestaurantsStatusChannel_accepted"Receive/Subscribe
This is a blocking action: the workflow will wait until successCriteria is met or it times out.
In the following example, in the wait_KitchenOrdersStatusChannel_accepted step, the workflow would "wait until a message is received where the message’s body contains a customerOrderId that matches the orderId of the previous step’s output."
  - stepId: "wait_KitchenOrdersStatusChannel_accepted"
    channel: "$sourceDescriptions.RestaurantsOpenAPI.KitchenOrdersStatusChannel"
    action: "receive"
    successCriteria:
    - condition: "$message.body.customerOrderId == $steps.place_order.outputs.orderId"This step can include outputs using the contexts $message.body and $message.header
Support for Parallel Invocation: Forking and Joining
When using non-blocking steps, there may be a need for parallel invocation, involving forking and joining.
Parallel Invocation and Looping can also be applied to OpenAPI Request/Response steps.
Because of the complexity of this, we could address this in a separate issue for further discussion.