• Arazzo 1.0 & 1.1
  • Swift 6
  • Apple platforms & Linux
  • MIT

Arazzo workflows,
as Swift values.

Read, build, validate and evaluate OpenAPI Arazzo descriptions with typed Codable models, a runtime-expression parser that follows the specification's grammar, and validation that tells you exactly where a document goes wrong.

Workflow.swift
import ArazzoKit
import ArazzoKitYAML

let document = try Arazzo.Document(yaml: yamlString)

for issue in document.validate() {
    print(issue)  // [error] /workflows/0/steps/1/…
}

var context = Arazzo.EvaluationContext()
context.statusCode = 200
context.response = .init(body: ["pets": [["id": 1]]])

try Arazzo.Condition(
    "$statusCode == 200 && $response.body#/pets/0/id == 1"
).evaluate(in: context)  // true

What is Arazzo

OpenAPI describes endpoints.
Arazzo describes how to use them together.

Arazzo is the OpenAPI Initiative's specification for workflows: sequences of API calls where each step can read the outputs of the steps before it, check success criteria, and retry or jump on failure. Version 1.1 adds AsyncAPI channels. It is how you write down "log in, then find a pet, then order it" in a form tools can check, document and run.

loginUser

Calls loginUser on the pet store's OpenAPI description and keeps the token: $response.body#/token.

findPets

Sends Authorization: {$steps.loginUser.outputs.token} and succeeds when $statusCode == 200.

placeOrder

Orders $steps.findPets.outputs.petId, retries twice on a 503, and returns the order as a workflow output.

swift-arazzo gives each of those pieces a Swift type: the document, its workflows and steps, every runtime expression, every criterion and action, so your tool can work with workflows instead of with YAML.

Features

Everything the specification defines, typed.

In the spirit of OpenAPIKit: a Swift type for every object in the specification, with validation for the rules a type system cannot express.

Arazzo 1.0 and 1.1, completely

Every object, including 1.1's AsyncAPI steps, Selector Objects, Expression Type Objects, querystring parameters and $self. Using 1.1 features in a 1.0 document is flagged.

Validation that points at the problem

18 built-in rules: MUST becomes an error, SHOULD a warning, each reported at a JSON Pointer path. Unknown steps and sources, cycles, forward references, broken expressions. Add your own rules in a few lines.

Runtime expressions as a typed AST

$steps.login.outputs.token#/access parses to a value you can switch over, following the specification's ABNF. Templates know the range of every segment, so editors can highlight and diagnose in place.

Criteria you can evaluate

Simple conditions with the specification's comparison rules, regex criteria, and JSONPath through swift-jsonpath, which passes all 715 cases of the RFC 9535 compliance suite. XPath plugs in through a protocol.

Lossless round trips

Decode and encode JSON or YAML without losing key order, specification extensions or unknown-but-allowed content. Lenient by default so one typo never stops you from reading a document; strict on request.

Linux first-class, Swift 6 ready

Strict concurrency, every type Sendable and Hashable. The core module depends only on swift-jsonpath and uses FoundationEssentials on Linux, with no ICU. YAML support is an optional package trait, and the result-builder DSL a separate product.

Code tour

Short, typed, and checked by the compiler.

These snippets come from the README, which the test suite compiles and runs, so they stay correct.

Decode YAML or JSON, then navigate with enums instead of optional strings: a step's target is one of four cases, never two at once.

let document = try Arazzo.Document(yaml: yamlString)          // YAML (or JSON) text
let workflow = document.workflow(id: "loginUserAndRetrievePet")!
let step = workflow.step(id: "getPetStep")!

switch step.target {
case .operationId(let id):    print("calls", id)
case .operationPath(let path): print("calls", path)
case .channelPath(let path):   print("async channel", path)
case .workflowId(let id):      print("runs workflow", id)
}

if case .selector(let selector)? = step.outputs["petId"] {
    print(selector.context, selector.selector, selector.type.kind)
}

Built for

Tools that read, write or run workflows.

Editors and IDE tooling

Lossless round trips keep a user's file as they wrote it, and expression templates carry the range of every segment and error for highlighting and inline diagnostics.

Linters and CI checks

Run validateOrThrow() in a command-line tool or a test, and fail the build with a JSON Pointer path to every problem, on macOS or in a Linux container.

API test runners and workflow engines

Evaluate criteria, render templates, resolve parameters and order steps. Your runner sends the requests; swift-arazzo works out what to send and whether it succeeded.

Agents and code generation

Give an agent a validated, typed plan of API calls instead of free-form text, or generate Arazzo descriptions and check them before anyone runs them.

Quality and speed

Tested against the specification. Measured on every change.

8descriptions decoded, round-tripped and validated in the tests: the specification's published examples and a fixture using every 1.1 feature
715 / 715RFC 9535 JSONPath compliance cases passed by swift-jsonpath
4CI builds on every change: Linux on Swift 6.0, 6.1 and 6.2, and macOS, plus API-breakage and DocC checks
2.2×faster validation in 0.1.1, with half the allocations
Benchmark (p50, Apple silicon)0.1.00.1.1
Parse 12 runtime expressions12.9 µs3.1 µs
Parse 4 conditions18.8 µs5.0 µs
Validate a large description (~500 KB)17.4 ms7.8 ms
Execution order and effective parameters, same description4.9 ms2.0 ms

Benchmarks use package-benchmark and live in the repository: swift package --package-path Benchmarks benchmark.

Install

Add it to your package.

Package.swift
dependencies: [
    .package(url: "https://github.com/mackoj/swift-arazzo.git", from: "0.1.3"),
],
targets: [
    .target(name: "MyTool", dependencies: [
        .product(name: "ArazzoKit", package: "swift-arazzo"),
        .product(name: "ArazzoKitYAML", package: "swift-arazzo"), // optional
        .product(name: "ArazzoKitBuilder", package: "swift-arazzo"), // optional
    ]),
]
  • Swift 6.0+ on Linux, macOS 13+, iOS 16+, tvOS 16+, watchOS 9+ and visionOS 1+.
  • ArazzoKit: models, expressions, evaluation and validation. Depends only on swift-jsonpath.
  • ArazzoKitYAML: YAML decoding and encoding on Yams, behind the YAML package trait (on by default). Turn it off with traits: [] to skip building Yams.
  • ArazzoKitBuilder: a result-builder DSL that writes documents in Swift. Depends only on ArazzoKit.
  • API reference on the Swift Package Index; guide and examples in the README.