Skip to content

AsyncAPI bridge

Status: target state, not implemented. The mapping is defined in ACTOR-COMMUNICATION-CONTRACT.md. No AsyncAPI bridge exists in the codebase. This page documents the target shape so the contract is settled before implementation.

AsyncAPI is the analog of OpenAPI for event-driven systems: it describes channels, messages, and the publish/ subscribe roles each party plays. Matrix's emits, streams, and subscribes declarations map directly to AsyncAPI primitives.

The mapping

Source: WORKSTREAMS/core-and-packaging/ACTOR-COMMUNICATION-CONTRACT.md § "How they map to protocol gateways".

Matrix declarationAsyncAPI primitive
static acceptsRequest channels (an op the actor receives)
static emitsPub channels (the actor publishes)
static streamsPub channels (durable; with retention metadata)
static subscribesSub channels (the actor consumes)
static blackboardPub/Sub channels (depending on access)
static state(no direct AsyncAPI primitive — use REST/OpenAPI instead)

Why AsyncAPI fits

  • Event-driven contracts. AsyncAPI is the standard for describing pub/sub APIs the way OpenAPI describes REST. A consumer reading the AsyncAPI doc knows which channels it can subscribe to and what messages flow.
  • Operations vs channels. AsyncAPI 3.x separates channel definition (the subject + message schema) from operations (publish/subscribe intent, by which party). This matches Matrix exactly: a subject is shared, and emits vs subscribes declares the role.
  • Multiple bindings. AsyncAPI supports multiple protocol bindings (NATS, MQTT, Kafka, AMQP). The Matrix AsyncAPI generator emits a NATS binding pointing at the actual subjects, so consumers using AsyncAPI tooling can connect to NATS directly.

Generated document shape

yaml
asyncapi: 3.0.0
info:
  title: COM.NIMBLETEC.RICHARD-SANTOMAURO/market.feed
  version: 1.0.0

servers:
  nats:
    host: hub.hivecast.ai:4222
    protocol: nats

channels:
  market.tick:
    address: COM.NIMBLETEC.RICHARD-SANTOMAURO.market.feed.$events
    messages:
      MarketTick:
        $ref: '#/components/messages/MarketTick'
  market.trades:
    address: COM.NIMBLETEC.RICHARD-SANTOMAURO.market.feed.$stream.market.trades
    messages:
      MarketTrade:
        $ref: '#/components/messages/MarketTrade'

operations:
  publishMarketTick:
    action: send
    channel: { $ref: '#/channels/market.tick' }
  subscribeMarketTick:
    action: receive
    channel: { $ref: '#/channels/market.tick' }

components:
  messages:
    MarketTick:
      contentType: application/json
      payload:
        $ref: '#/components/schemas/MarketTickSchema'
  schemas:
    MarketTickSchema:
      type: object
      properties:
        symbol: { type: string, description: 'Ticker symbol' }
        price:  { type: number, description: 'Trade execution price in USD' }
        # ...

The bridge generates this document from $introspect plus the actor's authority root and current registered subjects.

Frequency hints

The frequency field on emits declarations becomes a vendor-extension on the AsyncAPI message:

yaml
MarketTick:
  contentType: application/json
  payload: { ... }
  x-matrix-frequency: high

Consumer-side rate limiters and dashboards can use this to size buffers.

Stream retention

static streams declarations add retention metadata:

yaml
market.trades:
  address: COM.NIMBLETEC.RICHARD-SANTOMAURO.market.feed.$stream.market.trades
  x-matrix-stream:
    retention: '30d'
    maxBytes: '10GB'
    maxMsgs: 100000000

This signals to the consumer that the channel is durable and replayable, not just live fan-out.

Subscribe declarations

A static subscribes block becomes a receive operation referencing the appropriate external channel:

yaml
operations:
  receivePriceAlerts:
    action: receive
    channel:
      address: COM.NIMBLETEC.RICHARD-SANTOMAURO.market.feed.$state
    description: 'Watches market.last-price; fires alerts on threshold'

This documents the actor's INPUTS, which is critical for understanding event-driven services without reading code.

Marketplace blackboard

Blackboard declarations include pricing for marketplace facts:

yaml
channels:
  market.sentiment:
    address: COM.NIMBLETEC.RICHARD-SANTOMAURO.market.feed.$blackboard.market.sentiment
    x-matrix-blackboard:
      access: write-only
      visibility: marketplace
      pricing:
        model: subscription
        price: '$10/month'
        description: 'Real-time sentiment for all S&P 500 symbols. Free trial: 7 days.'

Consumer tooling can render the price and surface a "subscribe" call to the billing actor.

What is missing today

  • No AsyncAPI bridge actor in the codebase.
  • No CI step generating per-actor AsyncAPI documents.
  • The static blackboard framework methods (publishBlackboard, readBlackboard, watchBlackboard) are documented but not yet base- class helpers — so the bridge has nothing to read for blackboard channels in production code today.

See also