Arazzo: The Missing Piece for AI-Assisted API Consumption

Arazzo: The Missing Piece for AI-Assisted API Consumption

Guillaume Pierson
• 8 min read

You’ve built an API. You’ve written the OpenAPI spec. You’ve even generated some SDK clients. And yet, your support inbox is full of “how do I…?” questions. Developers can see your endpoints but don’t understand how to chain them together.

Sound familiar? That’s the problem Arazzo solves.

The Problem with API Documentation Today

Think about a typical e-commerce API. It has endpoints for authentication, product search, cart management, checkout, and payment. Your OpenAPI spec documents each one beautifully—request parameters, response schemas, error codes.

But here’s what it doesn’t tell you:

  • Do I authenticate before searching, or after adding to cart?
  • Can I checkout without a shipping address, or will it fail silently?
  • What happens if payment fails—do I need to recreate the cart?
  • Which order ID do I pass from the checkout response to the payment endpoint?

These are the questions that turn a 5-minute integration into a 2-day ordeal. The answers exist—scattered across tutorials, sample code, and support tickets. But they’re not machine-readable. They’re not standardized. They’re not specifications.

Enter Arazzo: Workflows as Specification

Arazzo, released by the OpenAPI Initiative in May 2024 (with version 1.0.1 in January 2025), fills this gap. It’s a specification for describing how to chain API calls together to achieve a specific outcome.

Think of it this way:

  • OpenAPI: “Here are the LEGO bricks”
  • Arazzo: “Here’s how to build the castle”

An Arazzo description defines:

  • Steps: A sequence of API calls to execute
  • Dependencies: Which step must complete before another begins
  • Data flow: How to pass values from one response to the next request
  • Success criteria: What determines if a step succeeded
  • Failure handling: What to do when things go wrong

The specification is both human-readable and machine-readable—which means both developers AND their AI assistants can understand it.

Anatomy of an Arazzo Workflow

Let me walk you through the structure. An Arazzo document starts with metadata and references to the APIs it orchestrates. Let’s say we have an OpenAPI spec for a pet adoption service. The Arazzo document begins like this:

arazzo: 1.0.1
info:
title: Pet Adoption Workflow
version: 1.0.0
description: |
This workflow guides you through adopting a pet.
Each step depends on the successful completion of the previous one.
sourceDescriptions:
- name: petAdoptionAPI
url: ./openapi.yaml
type: openapi

Then comes the workflow definition with its ordered steps:

workflows:
- workflowId: pet-adoption-workflow
summary: Complete pet adoption process
description: |
To adopt a pet, you need to:
1. Search for available pets
2. Pass a background check
3. Complete training
4. Finalize the adoption

Steps and Operations

Each step references an operation from your OpenAPI spec:

steps:
- stepId: search-pets
operationId: petAdoptionAPI.searchPets
parameters:
- name: type
in: query
value: $inputs.petType

Success Criteria

You can define what “success” means for each step—not just HTTP 200:

- stepId: background-check
operationId: petAdoptionAPI.submitBackgroundCheck
successCriteria:
- condition: $statusCode == 201
- context: $response.body
condition: $.status == 'approved'
type: jsonpath

This says: The step succeeds when we get a 201 status AND the response body's status field equals 'approved'.. It’s more expressive than just checking status codes.

Data Flow Between Steps

Here’s where Arazzo shines—runtime expressions that wire outputs to inputs:

- stepId: adopt-pet
operationId: petAdoptionAPI.adoptPet
parameters:
- name: petId
in: path
value: $inputs.petId
- name: ownerId
in: path
value: $inputs.ownerId

The $inputs.petId expression references an input parameter provided when starting the workflow. Arazzo supports expressions for:

  • $inputs.* - Workflow input parameters
  • $steps.*.outputs.* - Outputs from previous steps
  • $response.body#/path - JSON Pointer into response bodies
  • $response.header.* - Response headers
  • $statusCode - HTTP status code

Failure Handling

Real workflows need to handle failures. Arazzo provides onFailure actions:

- stepId: background-check
operationId: petAdoptionAPI.submitBackgroundCheck
onFailure:
- name: backgroundCheckFailed
type: end
- name: retryBackgroundCheck
type: retry
retryAfter: 5
retryLimit: 3
criteria:
- condition: $statusCode == 503

This defines two failure handlers: end the workflow if the check fails, but retry up to 3 times if we get a 503 (service unavailable). We can also imagine more complex error handling strategies with special cases where you will need to call alternative endpoints or notify users.

Putting It All Together

Now that we’ve seen the individual pieces, let’s look at the complete workflow. I built a demo API for pet adoption with this business logic:

  1. Search for available pets by type (cats or dogs)
  2. Background check the prospective owner (80% pass rate, 20% fail)
  3. Training certification for the owner
  4. Adoption finalization
arazzo: 1.0.1
info:
title: Pet Adoption Workflow
version: 1.0.0
sourceDescriptions:
- name: petAdoptionAPI
url: ./openapi.yaml
type: openapi
workflows:
- workflowId: pet-adoption-workflow
inputs:
type: object
properties:
petType:
type: string
enum: [cat, dog]
petId:
type: string
ownerId:
type: string
steps:
- stepId: search-pets
operationId: petAdoptionAPI.searchPets
parameters:
- name: type
in: query
value: $inputs.petType
successCriteria:
- condition: $statusCode == 200
outputs:
availablePets: $response.body
- stepId: background-check
operationId: petAdoptionAPI.submitBackgroundCheck
parameters:
- name: ownerId
in: path
value: $inputs.ownerId
successCriteria:
- condition: $statusCode == 201
- context: $response.body
condition: $.status == 'approved'
type: jsonpath
onFailure:
- name: backgroundCheckFailed
type: end
- stepId: training
operationId: petAdoptionAPI.completeTraining
parameters:
- name: ownerId
in: path
value: $inputs.ownerId
successCriteria:
- condition: $statusCode == 201
- stepId: adopt-pet
operationId: petAdoptionAPI.adoptPet
parameters:
- name: petId
in: path
value: $inputs.petId
- name: ownerId
in: path
value: $inputs.ownerId
successCriteria:
- condition: $statusCode == 200
outputs:
adoptionId: $response.body#/id
outputs:
adoptionId: $steps.adopt-pet.outputs.adoptionId

This is executable documentation. The workflow declares inputs, chains data through steps, validates success criteria, handles failures, and exposes outputs—all in a format that both humans and machines can read.

Generating Client Code with AI

If you publish an API, Arazzo explains clearly how to use your API in different scenarios. It is enough for an AI coding assistant to read both the Arazzo and OpenAPI specs and generate correct client code that implements the workflow, including error handling and data dependencies.

Let me show you. With the pet adoption API running locally, I asked my AI coding assistant:

“Write a small program in TypeScript to adopt Shadow, this cat is lovely.”

The AI read both the OpenAPI and Arazzo specs, understood the workflow, and generated this:

async function main() {
console.log("🐾 Starting Pet Adoption Workflow for Shadow\n");
// Step 1: Find Shadow
const pets = await searchPets();
const shadow = pets.find(
(pet) => pet.name.toLowerCase() === "shadow" && pet.status === "available"
);
// Step 2: Background check with retry (it might fail! 😅 - the spec says it should stop but we retry for testing)
let backgroundCheck: BackgroundCheckResponse;
let attempts = 0;
do {
attempts++;
backgroundCheck = await submitBackgroundCheck(ownerId);
if (backgroundCheck.status === "rejected") {
console.log(" Retrying background check...");
}
} while (backgroundCheck.status === "rejected" && attempts < 10);
// Step 3: Training
const training = await completeTraining(ownerId);
// Step 4: Adopt!
const adoption = await adoptPet(shadow.id, ownerId);
console.log("🐾 Shadow has found a home! 🏠");
}

The AI added retry logic because it knew from the Arazzo spec that the background check could fail. It understood the workflow dependencies. It wired the pet ID from search to adoption.

This is what Arazzo enables.

The Shift for API Providers

Consider this new workflow:

  1. You ship OpenAPI specs (you probably already do)
  2. You add Arazzo workflows describing common use cases
  3. Your consumers point their AI assistant at both specs
  4. The AI generates working integration code, with proper error handling

No SDK maintenance. No outdated code samples. No “check the docs” support tickets. The AI reads your specs and writes correct client code in any language.

Instead of writing client libraries, you write specifications that let AI write client libraries.

Yes, you’re trading one maintenance burden (SDK code) for another (Arazzo specs). But specifications are lighter-weight, version alongside your API naturally, and work with any AI assistant rather than requiring language-specific SDK updates.

The Reality: An Emerging Ecosystem

Let’s be clear: Arazzo is new. The specification was released in May 2024, with version 1.0.1 in January 2025. The tooling ecosystem is still emerging. Tools exist for viewing and visualizing workflows, but there’s nothing yet for automatically generating client code from Arazzo specs. For now, you’ll be writing specs by hand and manually implementing the workflows they describe.

The maintenance burden is real. Every time your API evolves, you need to update both the OpenAPI spec AND the Arazzo workflows. You’ll need processes to keep them in sync, test them, and version them alongside your API.

But here’s the bet: as AI coding assistants become ubiquitous, having machine-readable workflow specifications becomes increasingly valuable. You’re investing early in a standard that makes your API not just documented, but executable.

Try It Yourself

I’ve published the complete demo on GitHub: marmelab/arazzo.

You can run the API server and the (mostly generated) JS client:

Terminal window
# Terminal 1: Start the server
cd server && npm install && npm start
# Terminal 2: Adopt Shadow
cd client && npm install && node adopt-shadow.ts

You’ll see:

🐾 Starting Pet Adoption Workflow for Shadow
📋 Step 1: Searching for available pets...
✅ Found Shadow! Pet ID: pet-3
📋 Step 2: Submitting background check...
Attempt 1... Status: rejected
Attempt 2... Status: approved
✅ Background check approved!
📋 Step 3: Completing training...
✅ Training completed!
📋 Step 4: Adopting Shadow...
🎉 Congratulations! You have successfully adopted Shadow!
🐾 Workflow completed successfully! Shadow has found a home! 🏠

The Future: AsyncAPI Support

The Arazzo specification is actively evolving. The upcoming 1.1.0 release focuses on one major feature: support for AsyncAPI.

This is significant because modern APIs increasingly combine HTTP endpoints with event-driven patterns—webhooks, WebSockets, message queues. A checkout workflow might call a REST endpoint, then wait for a webhook confirmation. A real-time dashboard might subscribe to a WebSocket stream after authenticating via HTTP.

With AsyncAPI support, Arazzo workflows will be able to span both synchronous and asynchronous operations:

# Future Arazzo 1.1.0 (speculative syntax)
sourceDescriptions:
- name: orderAPI
url: ./openapi.yaml
type: openapi
- name: orderEvents
url: ./asyncapi.yaml
type: asyncapi
workflows:
- workflowId: place-order
steps:
- stepId: submit-order
operationId: orderAPI.createOrder
- stepId: wait-for-confirmation
operationId: orderEvents.onOrderConfirmed
# Wait for async event before proceeding

This will make Arazzo a comprehensive solution for describing modern API ecosystems—not just HTTP, but the full spectrum of API interactions.

Conclusion

Arazzo solves a real problem: the gap between “here are my endpoints” and “here’s how to use them together.” It’s what API documentation should be but rarely is.

For API providers, the proposition is compelling: ship Arazzo workflows alongside your OpenAPI spec, and you enable AI-assisted integration for all your users. No more hand-holding through multi-step processes. No more SDK maintenance. Just specifications that machines can read and execute.

For developers consuming APIs, Arazzo means your AI assistant finally understands not just what an API can do, but how to do it correctly.

The OpenAPI Initiative has given us a new tool. It’s up to us to use it.

Shadow has a home now. And your API documentation could be next.

Authors

Guillaume Pierson

Full-stack web developer at marmelab, Guillaume was initially a Java guy. Fan of anime and video games, he can develop an AI that beats you every time.