Arazzo 1.1:新機能と、今動くもの

シェア

2026 年 5 月 19 日、OpenAPI Initiative は Arazzo 1.1.0 をリリースしました。Arazzo は、一連の API 呼び出しを記述するための OpenAPI Initiative のフォーマットです。ログインし、 注文を作り、支払うといった流れを、各ステップが次のステップに値を渡しながら表します。OpenAPI は 1 つのエンドポイントが何を 受け取り何を返すかを表し、Arazzo はどのエンドポイントをどの順で呼び、各呼び出しが成功したかをどう判断するかを表します。

1.1 は、2024 年の 1.0 以来初めての機能追加リリースです。私たちは自分たちの API に対して 1.1 のワークフローを書き、10 月 9 日リリースの Redocly CLI 2.62.1 で実行しました。ランナーは 1.1 のドキュメントを受け付け、シンプルな作成・取得・更新・ 削除のワークフローは通ります。ただし新機能のうち 2 つは、リンターは通るのに実際の実行では無視されます。この記事では、 変更点、ダウンロードして実行できるワークフロー、そして当面は避けたほうがよい 2 つの機能を紹介します。

Arazzo ファイルがすること

Arazzo ドキュメントは 1 つ以上の API 記述(たいていは OpenAPI ファイル)を参照し、ワークフローを並べます。各ワークフローは ステップのリストです。ステップは operationId で操作を指定し、パラメータとリクエストボディを埋め、何を成功とみなすか を書き、後のステップのためにレスポンスから値を保存します。

この 1 つのファイルは 3 つの場面で役立ちます。

  • テスト。ランナーが本物のサーバーに対してステップを実行し、成功条件を満たさなければ失敗します。この記事 ではこの使い方をします。
  • ドキュメント。読み手は、ある作業に必要な呼び出しの順序を知ることができます。これは OpenAPI ファイル では表せません。
  • AI エージェント。OpenAPI を読んだエージェントは各エンドポイントの役割はわかりますが、どう組み合わせる かは推測するしかありません。Arazzo のワークフローがそれを教えます。

Arazzo 1.1 の変更点

目玉は AsyncAPI への対応で、ワークフローの中で HTTP 呼び出しとメッセージチャネルを混在させられます。それ以外の変更の多くは、 HTTP ワークフローを書きやすくするものです。すべてリリースの告知に載っています。

変更内容
type: asyncapi のソースソース記述として、openapi や arazzo に加えて AsyncAPI ドキュメントを使えるようになりました。
channelPath、action、correlationId、timeoutメッセージを送受信するステップ。action は send か receive、correlationId は応答をリクエストに対応づけ、timeout はミリ秒単位の上限です。
dependsOnステップが開始前に終わっている必要のある他のステップを挙げられます。挙げたステップが実行されるわけではありません。
アクションの parameters別のワークフローを呼ぶ成功・失敗アクションが、そのワークフローに入力を渡せます。たとえばトークンを更新してからリトライする場合です。
Selector ObjectJSONPath、XPath、JSON Pointer でレスポンスや入力から値を取り出します。outputs、パラメータ値、リクエストボディで使えます。
Expression Type ObjectRFC 9535 の JSONPath や XPath 3.1 のように、クエリ言語のバージョンを固定します。1.0 の Criterion Expression Type Object に代わるものです。
in: querystringパラメータをクエリ文字列全体として送ります。OpenAPI 3.2 の同じ追加に合わせたものです。
$selfドキュメントを識別する URI。ファイルの置き場所に関係なく参照できるようになります。

仕様には、$steps.login.outputs.token のようなランタイム式の完全な文法、ソース記述を解決する順序、条件が真になる場合の厳密なルールも加わりました。フィールドが 増えるわけではありませんが、2 つのランナーで結果が食い違いかねなかったケースに決着をつけます。gRPC、GraphQL、MCP、ループ への対応は今後のバージョンのロードマップにあり、1.1 には入っていません。

私たちの API で実行できるワークフロー

このワークフローは api.testingapis.com に商品を作り、読み直し、価格を変え、削除し、消えたことを確かめます。無料のエンドポイントだけを使うので、アカウントも API キーもなしで実行できます。

products.arazzo.yaml
arazzo: 1.1.0
$self: https://testingapis.com/downloads/arazzo/products.arazzo.yaml
info:
  title: Product lifecycle on testingapis.com
  summary: Create a product, read it back, change its price, delete it and check that it's gone.
  version: 1.0.0
sourceDescriptions:
  - name: testingapis
    url: ./testingapis-products.openapi.json
    type: openapi
workflows:
  - workflowId: product-lifecycle
    inputs:
      type: object
      properties:
        title: { type: string, default: Arazzo test product }
        price: { type: number, default: 12.5 }
        newPrice: { type: number, default: 9.99 }
    steps:
      - stepId: createProduct
        operationId: Products_Create
        requestBody:
          contentType: application/json
          payload:
            title: $inputs.title
            price: $inputs.price
            category: electronics
        successCriteria:
          - condition: $statusCode == 201
        outputs:
          productId: $response.body#/data/id

      - stepId: readProduct
        operationId: Products_GetById
        parameters:
          - name: id
            in: path
            value: $steps.createProduct.outputs.productId
        successCriteria:
          - condition: $statusCode == 200
          - context: $response.body
            condition: $[?@.category == 'electronics' && @.inStock == false]
            type:
              type: jsonpath
              version: rfc9535
        onFailure:
          - name: cleanUp
            type: goto
            stepId: deleteProduct

      - stepId: changePrice
        operationId: Products_Update
        parameters:
          - name: id
            in: path
            value: $steps.createProduct.outputs.productId
        requestBody:
          contentType: application/json
          payload:
            title: $inputs.title
            price: $inputs.newPrice
            category: electronics
        successCriteria:
          - condition: $statusCode == 200
          - condition: $response.body#/data/price == $inputs.newPrice
        onFailure:
          - name: cleanUp
            type: goto
            stepId: deleteProduct

      - stepId: deleteProduct
        operationId: Products_Delete
        parameters:
          - name: id
            in: path
            value: $steps.createProduct.outputs.productId
        successCriteria:
          - condition: $statusCode == 200

      - stepId: confirmGone
        operationId: Products_GetById
        parameters:
          - name: id
            in: path
            value: $steps.createProduct.outputs.productId
        successCriteria:
          - condition: $statusCode == 404
    outputs:
      productId: $steps.createProduct.outputs.productId

参照先の OpenAPI ファイルと一緒にダウンロードし、同じフォルダに置いて実行してください。npx がランナーを取ってくるので、Node 22.12 以降があれば十分です。

Terminal
$ npx @redocly/cli@2.62.1 respect products.arazzo.yaml
出力(2026 年 10 月 13 日)
Running workflow products.arazzo.yaml / product-lifecycle

✓ POST /api/Products - step createProduct
  ✓ success criteria check - $statusCode == 201
  ✓ status code check - $statusCode in [200, 201, 400, 500]

✓ GET /api/Products/{id} - step readProduct
  ✓ success criteria check - $statusCode == 200
  ✓ success criteria check - $[?@.category == 'electronics' && @.inStock == fal...
  ✓ status code check - $statusCode in [200, 404, 500]

✓ PUT /api/Products/{id} - step changePrice
  ✓ success criteria check - $statusCode == 200
  ✓ success criteria check - $response.body#/data/price == $inputs.newPrice
  ✓ status code check - $statusCode in [200, 404, 500]

✓ DELETE /api/Products/{id} - step deleteProduct
  ✓ success criteria check - $statusCode == 200
  ✓ status code check - $statusCode in [200, 404, 500]

✓ GET /api/Products/{id} - step confirmGone
  ✓ success criteria check - $statusCode == 404
  ✓ status code check - $statusCode in [200, 404, 500]

Workflows: 1 passed, 1 total
Steps: 5 passed, 5 total
Checks: 12 passed, 12 total
Time: 922ms

ファイルのいくつかの部分は、見た目以上の仕事をしています。

  • $response.body#/data/id は、# の後に JSON Pointer を付けたランタイム式です。私たちの作成エンドポイントは 新しい商品を { message, data } で包むので、ID は /data/id にあります。後のステップはすべて$steps.createProduct.outputs.productId としてこれを読みます。
  • readProduct の条件では、新しい Expression Type Object を使ってクエリが RFC 9535 の JSONPath であることを示して います。JSONPath の条件はフィルターが 1 つ以上のノードに一致すれば通るので、$[?@.category == 'electronics' && @.inStock == false] で 2 つのフィールドを一度に確認できます。期待値を逆にして、失敗すべきときに失敗することも確かめました。ちゃんと失敗しました。
  • 各ステップの 3 つ目のチェック status code check は Arazzo ファイルにはありません。Redocly が OpenAPI ファイルに 載っているレスポンスから追加するもので、API が記述していないステータスコードが返ると、自分の条件が通ってもステップは 失敗します。

ステップが失敗したらワークフローが後片付けする

私たちの API で作った商品は共有されます。削除されるまで、商品を一覧した人には誰にでも見えます。途中で止まったテストはゴミ を残すので、readProduct と changePrice には deleteProduct に飛ぶ onFailure アクションを付けています。確認のため、価格のチェックを通らないように変えました。

ステップが失敗したときの出力
✗ PUT /api/Products/{id} - step changePrice
  ✓ success criteria check - $statusCode == 200
  ✗ success criteria check - $response.body#/data/price == $inputs.price
  ✓ status code check - $statusCode in [200, 404, 500]

Running failure action cleanUp for the step changePrice

✓ DELETE /api/Products/{id} - step deleteProduct
  ✓ success criteria check - $statusCode == 200

✓ GET /api/Products/{id} - step confirmGone
  ✓ success criteria check - $statusCode == 404

ワークフローは失敗を報告しますが、その前に商品は削除されています。共有環境にデータを作るワークフローでは、同じようにして ください。

Selector Object はリンターを通るが実行されない

Selector Object は、レスポンスから値を取り出す新しい方法です。JSON Pointer で商品の評価を読み、受け取ったものをそのまま 返す echo エンドポイントに送ってみました。

selector.arazzo.yaml(ステップ)
- stepId: getProduct
  operationId: Products_GetById
  parameters:
    - { name: id, in: path, value: 1 }
  outputs:
    rating:
      context: $response.body
      selector: /rating/rate
      type: jsonpointer
- stepId: echoIt
  operationId: Echo_Echo_POST
  requestBody:
    contentType: application/json
    payload:
      rating: $steps.getProduct.outputs.rating

redocly lint はこのファイルを通します。echo エンドポイントは {"rating": 4.3} を受け取るはずです。実際に届いたのはこれでした。

ランナーが送ったリクエストボディ
{
  "rating": {
    "context": {
      "id": 1,
      "title": "Wireless Noise-Cancelling Headphones",
      "price": 249.99,
      ...
      "rating": { "rate": 4.3, "count": 127 },
      "inStock": true,
      "createdAt": "2025-06-12T10:30:00Z"
    },
    "selector": "/rating/rate",
    "type": "jsonpointer"
  }
}

ランナーは context をレスポンスボディ全体に解決し、セレクターを適用せずに Selector Object そのものを送りました。 出力には何の警告もありません。ステップが失敗するのは、サーバーが受け取った内容を私たちが確認したからにすぎません。200 しか確認しないワークフローなら、間違ったデータを送りながら通ってしまいます。

ランナーが追いつくまでは 1.0 の書き方を使いましょう。JSON Pointer なら、そのほうが短くもなります。

1.0 でも 1.1 でも動く
outputs:
  rating: $response.body#/rating/rate

ワークフローに渡したパラメータが消える

告知で parameters の例として挙げられているのは、トークン更新のワークフローを呼んでからステップをリトライする失敗アクションです。私たちの無料 エンドポイントはトークンを発行しないので、存在しない商品で同じ仕組みを試しました。失敗アクションが report ワークフローを呼び、そのワークフローが入力の reason を echo エンドポイントに送ります。

params.arazzo.yaml(ステップ)
- stepId: getMissing
  operationId: Products_GetById
  parameters:
    - { name: id, in: path, value: 99999 }
  successCriteria:
    - condition: $statusCode == 200
  onFailure:
    - name: reportAndRetry
      type: retry
      retryLimit: 1
      workflowId: report
      parameters:
        - name: reason
          value: not found

ランナーは仕様どおりの順で report ワークフローを呼び、ステップをリトライします。しかし echo エンドポイントが受け取った のは空のオブジェクトでした。

echo エンドポイントが受け取ったもの
"contentType": "application/json",
"contentLength": 2,
"body": "{}",
"json": {}

reason は届きませんでした。report を単独で --input reason=... 付きで実行すると動くので、問題はアクションから parameters を渡すところにあります。トークン更新なら、更新の呼び出しが refresh token なしで送られることになります。

Redocly CLI 2.62.1 で動いたもの

Arazzo 1.1 の機能Lint実行
arazzo: 1.1.0受け付ける動く
$self受け付ける受け付ける。実行時に観察できることはない
Expression Type Object受け付ける動き、失敗すべきときに失敗する
dependsOn受け付ける受け付ける。ステップはどのみち順に実行される
Selector Object受け付ける適用されない。オブジェクトがデータとして送られる
アクションの parameters受け付けるワークフローは動くが、入力が空
AsyncAPI のステップ未検証未検証

Arazzo 1.1 への対応をうたう Redocly の changelog の項目は見つからなかったので、単にまだ作られていない機能なのかもしれません。Arazzo のリポジトリに載っている他のツールは違う動きをする可能性があり、私たちが試したのは Redocly だけです。

今 1.1 のワークフローを書くなら

  • arazzo: 1.1.0 と、実際に動く機能(Expression Type Object、$self、dependsOn)を使う。
  • レスポンスの値は Selector Object ではなく、$response.body#/data/id のようなランタイム式で読む。
  • トークンの更新は、失敗アクションの parameters ではなく、ステップの中でログインし直して扱う。
  • ステータスコードだけでなく、サーバーが受け取った内容を確認する。この記事の問題は、通った lint も 200 も見つけられませんでした。見つけたのは echo エンドポイントです。
  • @redocly/cli@2.62.1 のようにランナーのバージョンを固定し、ランナーの更新でコミットなしに結果が変わらないようにする。

ワークフローで作成・取得・更新・削除のサイクルをテストするなら、CRUD テストのレッスンで各ステップに必要なチェックを説明しています。OpenAPI 仕様の読み方(英語)ではワークフローが参照する operationId を説明し、商品 API のドキュメントには上のワークフローが触れるすべてのフィールドが載っています。