SuperAPI AI Directory

asyncapi-parser

Coding & development

View repository

Updated 10-16 09:50

About this skill

AsyncAPI Parser Skill

AsyncAPI version: This skill targets AsyncAPI 3.x (3.0 and 3.1). AsyncAPI 2.x is NOT supported by Drift — if the spec has asyncapi: "2.x.x", tell the user and stop.

Reference files

  • references/asyncapi-schema-patterns.md — how to read and enumerate AsyncAPI 3.x message schemas (oneOf / anyOf / allOf / discriminator / const / correlationId / optional payload fields)
  • references/asyncapi-drift-mapping.md — how to map each execution mode and payload variant to Drift YAML, including trigger/probe patterns, expected structure per mode, and naming conventions

Workflow

0. Navigate large specifications without loading them wholesale

For a specification over 1,000 lines or 100 KB, do not read or paste the whole file. Build a line-number index, then inspect only the operation and definitions that are reachable from it:

# Establish the document size and top-level section boundaries.
wc -l -c asyncapi.yaml
grep -nE '^(operations|channels|components):' asyncapi.yaml

# List AsyncAPI operation IDs without reading their bodies.
awk '/^operations:/{in_operations=1; next} in_operations && /^[^ ]/{exit} in_operations && /^  [A-Za-z0-9._-]+:$/ {print NR ":" $0}' asyncapi.yaml

For a requested operation, locate its line number, then use sed -n to read a bounded range ending at the next operation at the same indentation. Follow the same pattern for the referenced channel, message, and schema definitions. Never expand unrelated operations, channels, or every item under components merely to find a match.

Keep a compact fact ledger while resolving references:

item source line refs still to resolve resolved facts
operation action, channel, messages, reply
channel address
message correlation ID, headers, payload ref
schema variants, required fields, discriminator

Process the refs still to resolve column as a queue, deduplicating repeated $ref values. Stop when every reachable reference is resolved to primitives or the schema patterns needed to generate the requested tests. For a request to cover the entire specification, first index operation IDs, then process one operation at a time and emit a separate fact ledger entry and test block for each. This keeps very long documents within context while preserving complete operation coverage.

1. Locate the operation

Extract only what's needed:

# Find the operation block
grep -n "sendOrderCreated\|receiveInventoryAdjusted" asyncapi.yaml

# Read the operations block and its channel/messages refs
grep -n "^operations:" asyncapi.yaml

From the operation block extract:

  • action — send or receive
  • channel.$ref — resolves to a channel name in channels:
  • messages[] — list of $ref to message objects
  • reply block — present only for request-reply interactions

From the channel block:

  • address — the topic/queue name

From the message block (via components.messages):

  • correlationId.location — where Drift finds the correlation ID
  • headers schema — header fields
  • payload schema — the message payload (may be complex: oneOf, anyOf, allOf)

2. Resolve $refs recursively

  1. Grep for MessageName: in components.messages to find the definition
  2. If the payload itself contains refs, follow those into components.schemas
  3. Track visited refs. When a schema recursively refers to an active ancestor, preserve the $ref back-edge and stop expanding that branch.
  4. For external refs such as ./messages.yaml#/Order, open the referenced file and continue from its JSON Pointer. Report unresolved files or pointers as gaps; never treat them as empty schemas.
  5. Stop at primitive types (string, integer, boolean, array, object, const)

allOf: [$ref: Base, properties: {...}] is composition — merge all schemas into one full payload. See references/asyncapi-schema-patterns.md for all patterns.

3. Determine execution mode

Auto-selected by Drift based on action + presence of reply block:

operation.action reply block mode Drift role
send absent async-observe Drift subscribes and captures
receive absent async-inject (+ probe) or async-inject-capture (+ probe-topic) Drift publishes
send present async-request-reply Drift publishes request, captures reply

Critical: action reflects the application's perspective, not Drift's. send means your service publishes — Drift subscribes. receive means your service consumes — Drift publishes.

4. Enumerate payload variants

For each operation that has multiple message variants, enumerate structurally distinct schema variants. Aim for minimum tests that maximise schema coverage.

Pattern Tests to generate
oneOf / anyOf with N branches in payload N tests — one per branch
discriminator with N mapping values N tests — one per discriminator value
allOf (composition) 1 test — merge all schemas into one payload
const field 1 test (const is a fixed value — no variants)
Optional field cluster in payload 2 tests: one with all optional fields, one with required only
nullable payload field 1 null variant only if it changes behaviour

See references/asyncapi-schema-patterns.md for worked examples.

5. Generate Drift test cases

For each variant produce a Drift operation block. See references/asyncapi-drift-mapping.md for full patterns. Key conventions:

  • Name single-variant operations as {operationId}_{mode} — e.g. SendOrderCreated_Observe
  • Name multi-variant operations as {operationId}_{variant} — e.g. ReceiveInventoryAdjusted_commandType, ReceiveInventoryAdjusted_minimal
  • Always include correlation-id in parameters — it is required for message matching
  • Always set timeout-ms (default 5000ms; increase for slow services)
  • For async-observe: include a trigger hook — Drift cannot make your service publish
  • For async-request-reply: do not include a trigger — Drift publishes the request and captures the reply
  • For async-inject: include a probe hook to verify side effects, OR use probe-topic for race-condition-free capture
  • expected.headers + expected.payload for message capture modes; expected matches probe stdout JSON for async-inject mode
  • Omitting an expected.payload field lets Drift validate it against the AsyncAPI message schema automatically; add explicit field assertions only when asserting specific variant values (e.g. the discriminator property came back correctly)

Output format

Always produce:

  1. Analysis — operation name, action, channel address, execution mode, message schema patterns found, how many test variants will be generated and why
  2. Drift operations YAML — the complete operations: block, ready to paste into a test file
  3. Trigger/probe hooks — shell scripts or Lua function stubs if needed (label as FILL_IN where service-specific)
  4. Gaps — payload combinations intentionally excluded, with reason

Example

Given sendOrderCreated (action: send, payload has const: order.created on eventType):

operations:
  SendOrderCreated_Observe:
    target: async-send:sendOrderCreated:orderCreated
    description: "Observe the order.created event after trigger fires"
    parameters:
      correlation-id: send-order-created-001
      timeout-ms: 5000
      orderId: ORD-100
      customerId: CUST-9
    trigger:
      executable-type: command
      value: python3
      parameters:
        args:
          - ./hooks/trigger-send.py
          - --correlation-id
          - ${parameters.correlation-id}
          - --order-id
          - ${parameters.orderId}
          - --customer-id
          - ${parameters.customerId}
      timeout-ms: 2000
    expected:
      headers:
        correlation-id: ${parameters.correlation-id}
      payload:
        eventType: order.created
        orderId: ${parameters.orderId}
        customerId: ${parameters.customerId}
        status: created