Skip to content

Exporting documents

The plugin adds an asyncapi export command to the Litestar CLI. This application describes a broker request and reply with explicit contracts and has no routes:

# /// script
# requires-python = ">=3.11"
# dependencies = ["litestar[standard]", "litestar-asyncapi"]
# [tool.uv.sources]
# litestar-asyncapi = { path = "../.." }
# ///
"""A typed broker request/reply contract; declaring it creates no broker client."""

from dataclasses import dataclass

from litestar import Litestar

from litestar_asyncapi import (
    AsyncAPIConfig,
    AsyncAPIPlugin,
    ChannelDefinition,
    MessageDefinition,
    OperationDefinition,
    ReplyDefinition,
)

__all__ = ("app",)


@dataclass
class QuoteRequest:
    sku: str
    quantity: int


@dataclass
class Quote:
    sku: str
    total: float


config = AsyncAPIConfig(
    title="Pricing broker",
    channels=[
        ChannelDefinition(
            key="quote-requests",
            address="pricing.requests",
            operations=[
                OperationDefinition(
                    action="receive",
                    operation_id="handleQuoteRequest",
                    messages=[MessageDefinition(name="QuoteRequest", payload=QuoteRequest)],
                    reply=ReplyDefinition("quotes", messages=["Quote"]),
                )
            ],
        ),
        ChannelDefinition(
            key="quotes",
            address="pricing.quotes",
            operations=[
                OperationDefinition(
                    action="send", operation_id="sendQuote", messages=[MessageDefinition(name="Quote", payload=Quote)]
                )
            ],
        ),
    ],
)
app = Litestar(plugins=[AsyncAPIPlugin(config)])

Export its document from a checkout of this repository:

uv run litestar --app docs.examples.contracts:app asyncapi export --output asyncapi.json
uv run litestar --app docs.examples.contracts:app asyncapi export --format yaml --output asyncapi.yaml

The exported document

The export is the same canonical document that the documentation routes serve. Its operations section:

{
  "operations": {
    "handleQuoteRequest": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/quote-requests"
      },
      "messages": [
        {
          "$ref": "#/channels/quote-requests/messages/QuoteRequest"
        }
      ],
      "reply": {
        "channel": {
          "$ref": "#/channels/quotes"
        },
        "messages": [
          {
            "$ref": "#/channels/quotes/messages/Quote"
          }
        ]
      }
    },
    "sendQuote": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/quotes"
      },
      "messages": [
        {
          "$ref": "#/channels/quotes/messages/Quote"
        }
      ]
    }
  }
}

How it works

The command loads the application through Litestar's own --app option or autodiscovery, builds the document and writes it without starting a server. It does not need the documentation routes, so it works with DocsConfig(enabled=False).

Without --output, the document goes to stdout. --format yaml writes YAML instead of JSON. An existing file is replaced only with --overwrite; otherwise the command fails with a message on stderr and a non-zero exit code, as it does when the document cannot be built.

Exports use the application's type encoders and the servers declared in the configuration, so a committed export matches what the running application serves. To check it in continuous integration, export to a file and compare it with the committed copy, or validate it with the AsyncAPI CLI, which also handles conversion and code generation.

Inside Python, AsyncAPIPlugin.get_asyncapi_schema(app) returns the same document as a dictionary and get_asyncapi_json(app) as JSON bytes.

Recap

  • litestar asyncapi export writes the document as JSON or YAML without starting a server.
  • Existing files are kept unless --overwrite is given.
  • Next, browse the runnable examples; the CLI reference lists every option.