Last updated

Arazzo basics: Structure and syntax

Ready to get your hands dirty with Arazzo? This guide will walk you through the nuts and bolts of the Arazzo Specification—its structure, its syntax, and how it all fits together. If you've worked with OpenAPI before, you'll feel right at home: Arazzo uses the same YAML or JSON format and builds on OpenAPI's foundation. Let's dive into what makes an Arazzo file tick and get you ready to write your first workflow.

The big picture

An Arazzo file is a structured document that describes API workflows—sequences of calls with clear steps, dependencies, and outcomes. It's designed to be both human-readable (for you) and machine-readable (for tools). At its core, every Arazzo file has a few key pieces:

  • arazzo: The version of the spec you're using (e.g., "1.0.1").
  • info: Metadata like the title and version of your workflow.
  • sourceDescriptions: Links to OpenAPI or Arazzo files your workflows rely on.
  • workflows: The heart of Arazzo—where you define the sequences of API calls.
  • components: Optional reusable bits you can reference elsewhere.

Think of it like a playbook: it tells you (or a tool) how to run the game, step by step. Let's break these down.

The anatomy of an Arazzo file

Here's what each section does, with a simple example to tie it together.

  1. arazzo (Required) This is the version marker. It tells everyone which Arazzo spec you're following. As of February 2025, the latest is 1.0.1 (a patch over the 1.0.0 release from 2024). It's always at the top:
arazzo: "1.0.1"
  1. info (Required) This is your workflow's ID card—basic metadata to keep things organized. It needs a title and version, but you can add a description or summary for clarity:
info:
  title: "Simple Workflow"
  version: "1.0.0"
  description: "A basic workflow to buy a ticket and confirm it's valid."
  1. sourceDescriptions (Required) This section points to the OpenAPI files your workflow uses. It's how Arazzo connects to existing API definitions. Each entry has a name (for reference) and a url (where the file lives) and a type (currently the only valid values are openapi or arazzo):
sourceDescriptions:
  - name: "warpAPI"
    url: "./warp/openapi.yaml"
    type: openapi
  1. workflows (Required) Here's where the magic happens. The workflows section is an array of workflow objects, each defining a sequence of API calls. Every workflow needs:
  • workflowId: A unique identifier.
  • summary: A human-friendly overview.
  • description: A detailed explanation of the workflow.
  • steps: The actual sequence of operations.
  • dependsOn: Which workflow(s) it relies on (optional).

Inside steps, each step has:

  • stepId: A unique name for the step.
  • operationId: Links to an OpenAPI operation (from your sourceDescriptions).
  • parameters: Inputs for the call (static or dynamic).
  • outputs: What data it produces (optional).

Steps run in sequence by default, with each step using data from previous steps through runtime expressions.

  1. components (Optional) This is for reusable pieces—like parameters or steps—you might want to reference across workflows. It's like OpenAPI's components, but for Arazzo-specific stuff. We'll keep it simple and skip this for now.

A simple example

Let's put it together with a basic workflow for a time travel API: setting an anchor in time. Assume we've got an OpenAPI file with operation setAnchor.

arazzo: 1.0.1
info:
  title: Warp API
  version: 1.0.0
sourceDescriptions:
  - name: api-reference
    type: openapi
    url: openapi.yaml
workflows:
  - workflowId: missionLostInvention
    summary: Lost invention
    description: |-
      Travel back to the year 1889 and retrieve the blueprint for Nikola Tesla's lost invention before it's destroyed in a mysterious fire.
    inputs:
      type: object
      properties:
        token:
          type: string
          description: JWT Bearer token
          format: password
    parameters:
      - name: Authorization
        in: header
        value: "Bearer {$inputs.token}"
    steps:
      - stepId: setAnchorToCurrentTime
        operationId: api-reference.setAnchor
        description: Set an anchor to the current time.
        outputs:
          anchor_id: $response.body#/id
      - stepId: jumpTo1889
        operationId: api-reference.timeTravel
        description: "Travel to 1889 using the created timeline."
        requestBody:
          payload:
            destination: $steps.setAnchorToCurrentTime.outputs.anchor_id
# to be continued -- see a full walkthrough of this example in the next article

What's happening here?

  1. Top Level: We declare Arazzo 1.0.1 and give our workflow a title and version.
  2. Source: We link to Warp's OpenAPI file.
  3. Workflow: We define one workflow, missionLostInvention.
    • Step 1: setAnchorToCurrentTime calls setAnchor to set an anchor point in time.
    • Step 2: jumpTo1889 calls timeTravel to travel to 1889 using the created timeline.

The $ syntax is a runtime expression—think of it as a placeholder that grabs data dynamically when the workflow runs.

How it ties to OpenAPI

Arazzo doesn't reinvent the wheel—it leans on OpenAPI. The operationId in each step (setAnchor and timeTravel) matches an operationId in the linked api-reference