---
title: "Arazzo Goes Cross-Protocol"
description: "Version 1.1 ships AsyncAPI as a first-class source description, workflow-to-workflow chaining, and a Selector Object for pulling values out of responses. What started as an OpenAPI sidekick has graduated into a cross-protocol workflow spec."
canonicalUrl: "https://zuplo.com/blog/2026/05/21/arazzo-goes-cross-protocol"
pageType: "blog"
date: "2026-05-21"
authors: "martyn"
tags: "OpenAPI, API Design"
image: "https://zuplo.com/og?text=Arazzo%20Goes%20Cross-Protocol"
---
[Arazzo 1.1](https://www.openapis.org/blog/2026/05/19/announcing-arazzo-specification-1-1)
reaches across protocols: it describes workflows that span REST and event-driven
systems in one document, lets one workflow call another with typed inputs, and
gives you a proper way to extract values from responses without string
templating.

If you've only met Arazzo in passing, it's the OpenAPI Initiative's spec for
**sequences of API calls**. Where OpenAPI describes individual endpoints, Arazzo
describes the order you call them in: "log in, then create a cart, then add
items, then check out."

A document lists one or more **source descriptions** (the underlying specs that
define the operations it references) and a list of **workflows** made up of
**steps**. Each step points at a real operation, captures inputs and outputs,
and decides what happens next based on success criteria. 1.0 only knew about
OpenAPI sources; 1.1 widens the lens.

Arazzo documents are static YAML or JSON; a runner reads the document and
executes the steps. Tooling for 1.1 is still catching up, so the first useful
consumers are SDK generators, test harnesses, AI agents, and developer portals.

<CalloutAudience
  variant="bestFor"
  items={[
    `Teams describing APIs beyond endpoint contracts`,
    `Platforms mixing REST and event-driven systems (Kafka, MQTT, AMQP)`,
    `Anyone evaluating Arazzo for SDK, test, or AI agent flows`,
  ]}
/>

## AsyncAPI joins OpenAPI as a source description

The `sourceDescriptions` array, which used to accept only `openapi` and `arazzo`
entries, now accepts `asyncapi` too:

```yaml
arazzo: "1.1.0"
info:
  title: Order Workflow
  version: "1.0"
sourceDescriptions:
  - name: orders
    url: ./orders.openapi.yaml
    type: openapi
  - name: events
    url: ./orders.asyncapi.yaml
    type: asyncapi
```

With multiple source descriptions in play, steps reference operations using a
runtime expression: `$sourceDescriptions.<name>.<operationId>`. An AsyncAPI
operation defined in the `events` source above is reached as
`$sourceDescriptions.events.publishOrderCreated`. Steps that reference an
AsyncAPI operation get three new fields tuned for message flows:

- `action`: either `send` or `receive`, so the step knows whether it's
  publishing a message or waiting for one.
- `correlationId`: the value the workflow uses to match a published request to
  its eventual response (AsyncAPI's existing correlation primitive, surfaced
  into Arazzo).
- `timeout`: how long, in milliseconds, the runtime should wait for a `receive`
  step before failing the workflow.

```yaml
- stepId: publishOrderCreated
  operationId: $sourceDescriptions.events.publishOrderCreated
  action: send
  parameters:
    - name: orderId
      in: header
      value: $steps.createOrder.outputs.id
- stepId: awaitOrderConfirmed
  operationId: $sourceDescriptions.events.subscribeOrderConfirmed
  action: receive
  correlationId: $steps.publishOrderCreated.outputs.correlationId
  timeout: 30000
  successCriteria:
    - condition: $message.payload.status == "confirmed"
```

A checkout flow where Stripe confirms payment over a webhook, then an order
service emits an `order.created` event onto Kafka before the warehouse picks it
up: that's the shape Arazzo 1.0 couldn't describe in one document.

1.1 lets you describe both halves in a single workflow. The REST call and the
event that follows it live side by side, and the link between them, which
response value matches which event payload, is declared in the spec itself
rather than explained in a comment or a wiki page.

## Chained workflows now take typed inputs

Arazzo 1.0 already let Success and Failure Actions hand off to another workflow
via `workflowId`. What 1.1 adds is a `parameters` array on actions that
reference a `workflowId`, so the called workflow receives typed inputs instead
of inheriting whatever happens to be in scope:

```yaml
workflows:
  - workflowId: refreshAuthIfExpired
    inputs:
      type: object
      properties:
        refreshToken:
          type: string
    steps:
      - stepId: refresh
        operationId: refreshToken
        # ...

  - workflowId: placeOrder
    steps:
      - stepId: createOrder
        operationId: createOrder
        onFailure:
          - name: refreshThenRetry
            type: retry
            workflowId: refreshAuthIfExpired
            parameters:
              - name: refreshToken
                value: $inputs.refreshToken
            criteria:
              - condition: $statusCode == 401
```

The spec is precise about how the two action types behave:

| Action        | Behaviour                                                           | Use it for                                    |
| ------------- | ------------------------------------------------------------------- | --------------------------------------------- |
| `type: goto`  | One-way transfer to the named workflow. Control does not come back. | Branching to a different flow on a condition. |
| `type: retry` | Runs the named workflow, then returns to retry the failed step.     | Token refresh, rate-limit backoff.            |

With those two primitives you can extract recurring patterns like
reauthentication or rate-limit backoff into their own workflows and call them
from anywhere they apply, instead of duplicating recovery steps inside every
flow.

## Selector Object unifies JSONPath, XPath, and JSON Pointer

Arazzo 1.0 already supported JSONPath and XPath inside Criterion Objects, so
success criteria could match expressions like
`$.customers[?(@.primary == true)].email`. What it lacked was a way to use those
same expressions when pulling values **out** of a response into step outputs,
workflow outputs, request bodies, parameter values, or payload replacements.
Those extraction points were JSON Pointer only, which falls over the moment you
need a JSONPath filter ("the customer where `primary` is true") or XPath against
an XML response.

1.1 introduces the **Selector Object** to cover `jsonpath`, `xpath`, and
`jsonpointer` with one shape, wherever extraction happens:

```yaml
outputs:
  customerEmail:
    selector:
      context: $response.body
      type: jsonpath
      selector: "$.customers[?(@.primary == true)].email"
  legacyCustomerId:
    selector:
      context: $response.body
      type: xpath
      selector: "/customer/@id"
```

One mechanism for "reach into this response and grab the bit I need," instead of
templating brittle path strings.

## Expression Type Object pins JSONPath and XPath versions

Arazzo 1.1 renames the old Criterion Expression Type Object to the **Expression
Type Object** and extends it to cover selectors as well as conditions. You can
also pin the exact expression syntax:

- JSONPath: `rfc9535` or `draft-goessner-dispatch-jsonpath-00`
- XPath: `xpath-31`, `xpath-30`, `xpath-20`, `xpath-10`
- JSON Pointer: `rfc6901`

```yaml
selector:
  context: $response.body
  type:
    type: jsonpath
    version: rfc9535
  selector: "$.items[*].sku"
```

The difference between Goessner's original JSONPath draft and the formalised RFC
9535 is more than cosmetic. Pinning the version means a workflow runner can
refuse to execute a document it can't evaluate safely, instead of silently doing
the wrong thing.

## Other Arazzo 1.1 improvements

- **`in: querystring`** on Parameter Objects, aligning with OpenAPI 3.2. Lets
  you map an entire query string as one value instead of declaring each
  parameter separately.
- **`$self`** at the document root: a self-assigned URI that anchors relative
  references and makes cross-document resolution unambiguous when you're working
  across a fleet of Arazzo files.
- **Formal ABNF grammar** for runtime expressions, plus explicit truthy/falsy
  semantics for success criteria. Moves "what does this actually evaluate to?"
  out of the implementer's head and into the spec.
- **Source description resolution ordering** is now formally defined, so two
  conformant runners should resolve the same reference the same way.

If you're the person writing the runner, these are the difference between
guessing and following the spec.

## Arazzo roadmap: gRPC, GraphQL, MCP, A2A

What I'm most excited about isn't in 1.1 yet, it's on the roadmap. The release
notes flag gRPC, GraphQL, SOAP, plus MCP (Anthropic's Model Context Protocol,
the tool-calling layer agents like Claude and Cursor speak) and A2A (the
Agent-to-Agent protocol, originally from Google, now under the Linux
Foundation). On top of that: actor-in-loop capabilities, transformers,
functions, and loops.

Arazzo's ambition is to be **the** workflow description format for any protocol
worth scripting against. MCP and A2A on the roadmap is the clearest signal yet
that agent frameworks are moving from "let the LLM figure it out" to "give the
LLM a machine-readable workflow it can follow." That's the part I'll be watching
closely.

## Why Arazzo 1.1 matters for gateway teams

A machine-readable workflow spec has the same value as machine-readable
endpoints: something else can read it and do useful work. SDK generators, test
harnesses, AI agents, and developer portals can all consume an Arazzo document
and know how endpoints fit together, not just what each one returns.

With 1.1, that same document can describe the event-driven half of your platform
and chain reusable sub-flows, which moves Arazzo from "interesting-on-paper" to
a serious candidate for production documentation.

For the longer "what is Arazzo and why does it exist" framing, our
[overview of Arazzo and OpenAPI Overlay](/blog/openapi-arazzo-overlay-specifications-guide)
walks through both specifications together. For a hands-on introduction to
authoring Arazzo documents,
[Hunter Skrasek's API workflows post](/blog/api-workflows-and-arazzo) is the
quickest route in. The full
[Arazzo 1.1 specification](https://spec.openapis.org/arazzo/v1.1.0.html) is on
the OpenAPI Initiative site.