Arazzo 1.1: apa yang baru, dan apa yang berjalan hari ini

Bagikan

Pada 19 Mei 2026, OpenAPI Initiative merilis Arazzo 1.1.0. Arazzo adalah format OpenAPI Initiative untuk mendeskripsikan rangkaian panggilan API: login, lalu membuat pesanan, lalu membayarnya, dengan setiap langkah meneruskan nilai ke langkah berikutnya. OpenAPI menyatakan apa yang diterima dan dikembalikan satu endpoint. Arazzo menyatakan endpoint mana yang dipanggil, dalam urutan apa, dan bagaimana mengetahui apakah setiap panggilan berhasil.

Versi 1.1 adalah rilis fitur pertama sejak 1.0 pada 2024. Kami menulis workflow 1.1 terhadap API kami sendiri dan menjalankannya dengan Redocly CLI 2.62.1, yang rilis 9 Oktober. Runner-nya menerima dokumen 1.1, dan workflow sederhana membuat, membaca, mengubah, dan menghapus lulus. Dua fitur barunya lolos linter tetapi diabaikan saat workflow benar-benar dijalankan. Tulisan ini membahas apa yang berubah, workflow yang bisa Anda unduh dan jalankan, dan dua fitur yang sebaiknya dihindari dulu.

Apa yang dilakukan file Arazzo

Dokumen Arazzo menunjuk ke satu atau lebih deskripsi API, biasanya file OpenAPI, dan mendaftar workflow. Setiap workflow adalah daftar langkah. Sebuah langkah menyebut operasi lewat operationId-nya, mengisi parameter dan body request, menyatakan apa yang dihitung sebagai sukses, dan menyimpan nilai dari response untuk langkah selanjutnya.

Satu file itu berguna di tiga tempat:

  • Tes. Runner menjalankan langkah-langkahnya terhadap server sungguhan dan gagal jika kriteria sukses tidak terpenuhi. Begitulah kami memakainya di bawah.
  • Dokumentasi. Pembaca melihat urutan panggilan yang dibutuhkan sebuah tugas, sesuatu yang tidak bisa dinyatakan file OpenAPI.
  • Agen AI. Agen yang membaca OpenAPI tahu fungsi tiap endpoint, tetapi harus menebak cara menggabungkannya. Workflow Arazzo memberitahunya.

Apa yang berubah di Arazzo 1.1

Sorotan utamanya adalah dukungan AsyncAPI, sehingga workflow bisa mencampur panggilan HTTP dengan kanal pesan. Sebagian besar perubahan lainnya membuat workflow HTTP lebih mudah ditulis. Semuanya tercantum di pengumuman rilis:

PerubahanFungsinya
Sumber type: asyncapiDeskripsi sumber kini bisa berupa dokumen AsyncAPI, selain openapi dan arazzo.
channelPath, action, correlationId, timeoutLangkah yang mengirim atau menerima pesan. action bernilai send atau receive, correlationId mencocokkan balasan dengan request-nya, dan timeout adalah batas dalam milidetik.
dependsOnSebuah langkah bisa mendaftar langkah lain yang harus selesai sebelum ia mulai. Mendaftar sebuah langkah tidak menjalankannya.
parameters pada actionAction sukses atau gagal yang memanggil workflow lain bisa meneruskan input ke workflow itu, misalnya untuk memperbarui token lalu mencoba lagi.
Selector ObjectMengambil nilai dari response atau input dengan JSONPath, XPath, atau JSON Pointer. Berfungsi di outputs, nilai parameter, dan body request.
Expression Type ObjectMenetapkan versi bahasa query, seperti JSONPath menurut RFC 9535 atau XPath 3.1. Menggantikan Criterion Expression Type Object dari 1.0.
in: querystringMengirim parameter sebagai seluruh query string, sesuai tambahan yang sama di OpenAPI 3.2.
$selfURI yang mengidentifikasi dokumen, agar rujukan ke dokumen itu tidak bergantung pada lokasi file disimpan.

Spesifikasinya juga mendapat tata bahasa lengkap untuk ekspresi runtime seperti $steps.login.outputs.token, urutan yang pasti untuk menyelesaikan deskripsi sumber, dan aturan persis kapan sebuah kondisi dianggap benar. Ini tidak menambah field, tetapi menyelesaikan kasus di mana dua runner bisa berbeda pendapat. Dukungan untuk gRPC, GraphQL, MCP, dan loop ada di roadmap versi berikutnya dan tidak ada di 1.1.

Workflow yang bisa Anda jalankan terhadap API kami

Workflow ini membuat produk di api.testingapis.com, membacanya kembali, mengubah harganya, menghapusnya, dan memeriksa bahwa produk itu sudah hilang. Ia hanya memakai endpoint gratis, jadi berjalan tanpa akun atau API key.

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

Unduh bersama file OpenAPI yang ditunjuknya, taruh keduanya di satu folder, lalu jalankan. Node 22.12 atau lebih baru sudah cukup, karena npx mengambil runner-nya:

Terminal
$ npx @redocly/cli@2.62.1 respect products.arazzo.yaml
Output (13 Oktober 2026)
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

Beberapa bagian file ini melakukan lebih dari yang terlihat:

  • $response.body#/data/id adalah ekspresi runtime dengan JSON Pointer setelah #. Endpoint pembuatan kami membungkus produk baru dalam { message, data }, jadi ID-nya ada di /data/id. Setiap langkah berikutnya membacanya sebagai $steps.createProduct.outputs.productId.
  • Kriteria di readProduct memakai Expression Type Object yang baru untuk menyatakan bahwa query-nya adalah JSONPath RFC 9535. Kondisi JSONPath lulus jika filter cocok dengan setidaknya satu node, jadi $[?@.category == 'electronics' && @.inStock == false] memeriksa dua field sekaligus. Kami juga membalik nilai yang diharapkan untuk memastikan pemeriksaannya gagal saat seharusnya gagal, dan memang gagal.
  • Pemeriksaan ketiga di setiap langkah, status code check, tidak ada di file Arazzo. Redocly menambahkannya dari response yang tercantum di file OpenAPI, jadi kode status yang tidak didokumentasikan API akan menggagalkan langkah meskipun kriteria Anda sendiri lulus.

Workflow-nya bersih-bersih saat sebuah langkah gagal

Produk yang dibuat di API kami dipakai bersama: siapa pun yang mendaftar produk akan melihat produk Anda sampai dihapus. Tes yang berhenti di tengah jalan akan meninggalkan sampah, jadi readProduct dan changePrice punya action onFailure yang melompat ke deleteProduct. Untuk memeriksanya, kami mengubah pemeriksaan harga agar tidak mungkin lulus:

Output dengan langkah yang gagal
✗ 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

Workflow-nya tetap melaporkan kegagalan, tetapi produknya dihapus lebih dulu. Lakukan hal yang sama di workflow apa pun yang membuat data di lingkungan bersama.

Selector Object lolos lint tetapi tidak dijalankan

Selector Object adalah cara baru mengambil nilai dari response. Kami memakainya untuk membaca rating produk dengan JSON Pointer dan mengirimnya ke endpoint echo kami, yang mengembalikan apa pun yang diterimanya:

selector.arazzo.yaml (langkah)
- 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 meloloskan file ini. Endpoint echo seharusnya menerima {"rating": 4.3}. Inilah yang diterimanya:

Body request yang dikirim runner
{
  "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"
  }
}

Runner menyelesaikan context menjadi seluruh body response, lalu mengirim Selector Object itu sendiri alih-alih menerapkan selektornya. Tidak ada peringatan apa pun di output. Langkahnya gagal hanya karena kami memeriksa apa yang diterima server; workflow yang hanya memeriksa 200 akan lulus sambil mengirim data yang salah.

Sampai runner menyusul, pakai bentuk 1.0. Untuk JSON Pointer, bentuk itu malah lebih pendek:

Berfungsi di 1.0 dan 1.1
outputs:
  rating: $response.body#/rating/rate

Parameter yang diteruskan ke workflow hilang

Contoh yang dipakai pengumuman untuk parameters adalah action gagal yang memanggil workflow pembaruan token lalu mengulang langkah. Endpoint gratis kami tidak menerbitkan token, jadi kami menguji mekanisme yang sama dengan produk yang tidak ada: action gagal memanggil workflow report yang mengirim input reason-nya ke endpoint echo.

params.arazzo.yaml (langkah)
- 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

Runner memang memanggil workflow report lalu mengulang langkahnya, sesuai urutan yang dijelaskan spesifikasi. Tetapi endpoint echo menerima objek kosong:

Yang diterima endpoint echo
"contentType": "application/json",
"contentLength": 2,
"body": "{}",
"json": {}

reason tidak pernah tiba. Menjalankan report sendiri dengan --input reason=... berfungsi, jadi masalahnya ada pada penerusan parameters dari action. Untuk pembaruan token, artinya panggilan pembaruan terkirim tanpa refresh token.

Apa yang berjalan di Redocly CLI 2.62.1

Fitur Arazzo 1.1LintEksekusi
arazzo: 1.1.0DiterimaBerjalan
$selfDiterimaDiterima; tidak ada yang bisa diamati saat eksekusi
Expression Type ObjectDiterimaBerjalan, dan gagal saat seharusnya gagal
dependsOnDiterimaDiterima; langkah tetap berjalan berurutan
Selector ObjectDiterimaTidak diterapkan: objeknya dikirim sebagai data
parameters pada actionDiterimaWorkflow berjalan, input-nya kosong
Langkah AsyncAPIBelum diujiBelum diuji

Kami tidak menemukan entri changelog Redocly yang mengklaim dukungan Arazzo 1.1, jadi mungkin ini memang fitur yang belum dibuat. Alat lain yang tercantum di repositori Arazzo mungkin berperilaku berbeda, dan kami hanya menguji Redocly.

Menulis workflow 1.1 sekarang

  • Pakai arazzo: 1.1.0 dan fitur yang berjalan: Expression Type Object, $self, dan dependsOn.
  • Baca nilai response dengan ekspresi runtime seperti $response.body#/data/id, bukan Selector Object.
  • Tangani pembaruan token dengan login ulang di sebuah langkah, bukan lewat parameters pada action gagal.
  • Periksa apa yang diterima server, bukan hanya kode status. Lint yang lulus maupun 200 tidak menangkap satu pun masalah di tulisan ini. Endpoint echo kami yang menangkapnya.
  • Kunci versi runner, seperti yang kami lakukan dengan @redocly/cli@2.62.1, agar pembaruan runner tidak mengubah hasil Anda tanpa commit.

Jika workflow Anda menguji siklus membuat, membaca, mengubah, dan menghapus, pelajaran pengujian CRUD kami membahas pemeriksaan yang dibutuhkan setiap langkah. Membaca spesifikasi OpenAPI (dalam bahasa Inggris) menjelaskan nilai operationId yang dirujuk workflow, dan dokumentasi API produk mendaftar setiap field yang disentuh workflow di atas.