AsyncAPI Authoring Skill
When to Use This Skill
Use this skill when:
-
Asyncapi Authoring tasks - Working on author and validate asyncapi 3.0 specifications for event-driven api design, message brokers, and async communication patterns
-
Planning or design - Need guidance on Asyncapi Authoring approaches
-
Best practices - Want to follow established patterns and standards
Overview
Author AsyncAPI 3.0 specifications for event-driven architectures and async communication patterns.
AsyncAPI 3.0 Structure
Root Document
asyncapi: "3.0.0"
info: title: "{Service Name} Events API" version: "1.0.0" description: | Event-driven API for {service} domain events and commands. contact: name: "{Team Name}" email: "{team@company.com}" license: name: "MIT"
servers: production: host: "kafka.example.com:9092" protocol: "kafka" description: "Production Kafka cluster" security: - $ref: "#/components/securitySchemes/sasl"
development: host: "localhost:9092" protocol: "kafka" description: "Local development"
defaultContentType: "application/json"
channels:
Channel definitions
operations:
Operation definitions
components:
Reusable components
Channels (AsyncAPI 3.0)
channels: orderEvents: address: "orders.events.{orderId}" description: "Channel for order lifecycle events" parameters: orderId: description: "Order unique identifier" schema: type: string format: uuid messages: orderCreated: $ref: "#/components/messages/OrderCreated" orderShipped: $ref: "#/components/messages/OrderShipped" orderDelivered: $ref: "#/components/messages/OrderDelivered" orderCancelled: $ref: "#/components/messages/OrderCancelled"
orderCommands: address: "orders.commands" description: "Channel for order command messages" messages: createOrder: $ref: "#/components/messages/CreateOrderCommand" cancelOrder: $ref: "#/components/messages/CancelOrderCommand"
inventoryUpdates: address: "inventory.updates.{productId}" description: "Real-time inventory level updates" parameters: productId: schema: type: string messages: inventoryChanged: $ref: "#/components/messages/InventoryChanged"
Operations (AsyncAPI 3.0)
operations:
Publishing operations (this service sends)
publishOrderCreated: action: send channel: $ref: "#/channels/orderEvents" summary: "Publish order created event" description: | Published when a new order is successfully created. Consumers should use this to trigger downstream processes. messages: - $ref: "#/channels/orderEvents/messages/orderCreated" tags: - name: "orders" - name: "lifecycle"
publishOrderShipped: action: send channel: $ref: "#/channels/orderEvents" summary: "Publish order shipped event" messages: - $ref: "#/channels/orderEvents/messages/orderShipped"
Receiving operations (this service receives)
receiveCreateOrderCommand: action: receive channel: $ref: "#/channels/orderCommands" summary: "Process create order commands" description: | Receives commands to create new orders. Will publish OrderCreated event on success. messages: - $ref: "#/channels/orderCommands/messages/createOrder"
Subscription operations
subscribeInventoryUpdates: action: receive channel: $ref: "#/channels/inventoryUpdates" summary: "Subscribe to inventory changes" description: | Subscribes to real-time inventory updates. Used to maintain local inventory cache. messages: - $ref: "#/channels/inventoryUpdates/messages/inventoryChanged"
Message Definitions
components: messages: OrderCreated: name: "OrderCreated" title: "Order Created Event" summary: "Indicates a new order has been created" contentType: "application/json" headers: $ref: "#/components/schemas/EventHeaders" payload: $ref: "#/components/schemas/OrderCreatedPayload" correlationId: location: "$message.header#/correlationId" traits: - $ref: "#/components/messageTraits/commonHeaders"
OrderShipped:
name: "OrderShipped"
title: "Order Shipped Event"
summary: "Indicates an order has been shipped"
contentType: "application/json"
headers:
$ref: "#/components/schemas/EventHeaders"
payload:
$ref: "#/components/schemas/OrderShippedPayload"
traits:
- $ref: "#/components/messageTraits/commonHeaders"
OrderCancelled:
name: "OrderCancelled"
title: "Order Cancelled Event"
summary: "Indicates an order has been cancelled"
contentType: "application/json"
headers:
$ref: "#/components/schemas/EventHeaders"
payload:
$ref: "#/components/schemas/OrderCancelledPayload"
CreateOrderCommand:
name: "CreateOrderCommand"
title: "Create Order Command"
summary: "Command to create a new order"
contentType: "application/json"
headers:
$ref: "#/components/schemas/CommandHeaders"
payload:
$ref: "#/components/schemas/CreateOrderPayload"
InventoryChanged:
name: "InventoryChanged"
title: "Inventory Changed Event"
summary: "Real-time inventory level update"
contentType: "application/json"
payload:
$ref: "#/components/schemas/InventoryChangedPayload"
Payload Schemas
components: schemas: # Event headers EventHeaders: type: object required: - eventId - eventType - timestamp - version properties: eventId: type: string format: uuid description: "Unique event identifier" eventType: type: string description: "Event type name" timestamp: type: string format: date-time description: "Event timestamp (ISO 8601)" version: type: string description: "Event schema version" example: "1.0" correlationId: type: string format: uuid description: "Correlation ID for tracing" causationId: type: string format: uuid description: "ID of the event/command that caused this"
CommandHeaders:
type: object
required:
- commandId
- commandType
- timestamp
properties:
commandId:
type: string
format: uuid
description: "Unique command identifier"
commandType:
type: string
description: "Command type name"
timestamp:
type: string
format: date-time
correlationId:
type: string
format: uuid
userId:
type: string
description: "User initiating the command"
# Event payloads
OrderCreatedPayload:
type: object
required:
- orderId
- customerId
- items
- totalAmount
- createdAt
properties:
orderId:
type: string
format: uuid
customerId:
type: string
format: uuid
items:
type: array
items:
$ref: "#/components/schemas/OrderItem"
totalAmount:
$ref: "#/components/schemas/Money"
shippingAddress:
$ref: "#/components/schemas/Address"
createdAt:
type: string
format: date-time
OrderShippedPayload:
type: object
required:
- orderId
- trackingNumber
- carrier
- shippedAt
properties:
orderId:
type: string
format: uuid
trackingNumber:
type: string
carrier:
type: string
enum:
- "fedex"
- "ups"
- "usps"
- "dhl"
estimatedDelivery:
type: string
format: date
shippedAt:
type: string
format: date-time
OrderCancelledPayload:
type: object
required:
- orderId
- reason
- cancelledAt
properties:
orderId:
type: string
format: uuid
reason:
type: string
enum:
- "customer_request"
- "payment_failed"
- "out_of_stock"
- "fraud_detected"
refundAmount:
$ref: "#/components/schemas/Money"
cancelledAt:
type: string
format: date-time
cancelledBy:
type: string
description: "User or system that cancelled"
# Command payloads
CreateOrderPayload:
type: object
required:
- customerId
- items
properties:
customerId:
type: string
format: uuid
items:
type: array
minItems: 1
items:
$ref: "#/components/schemas/OrderItemRequest"
shippingAddress:
$ref: "#/components/schemas/Address"
billingAddress:
$ref: "#/components/schemas/Address"
couponCode:
type: string
# Domain schemas
OrderItem:
type: object
required:
- productId
- productName
- quantity
- unitPrice
properties:
productId:
type: string
format: uuid
productName:
type: string
quantity:
type: integer
minimum: 1
unitPrice:
$ref: "#/components/schemas/Money"
OrderItemRequest:
type: object
required:
- productId
- quantity
properties:
productId:
type: string
format: uuid
quantity:
type: integer
minimum: 1
Money:
type: object
required:
- amount
- currency
properties:
amount:
type: number
format: decimal
minimum: 0
currency:
type: string
pattern: "^[A-Z]{3}$"
example: "USD"
Address:
type: object
required:
- street
- city
- country
properties:
street:
type: string
city:
type: string
state:
type: string
postalCode:
type: string
country:
type: string
pattern: "^[A-Z]{2}$"
InventoryChangedPayload:
type: object
required:
- productId
- previousQuantity
- newQuantity
- reason
- changedAt
properties:
productId:
type: string
format: uuid
previousQuantity:
type: integer
newQuantity:
type: integer
reason:
type: string
enum:
- "sale"
- "return"
- "restock"
- "adjustment"
- "reservation"
changedAt:
type: string
format: date-time
Message Traits and Security
components: messageTraits: commonHeaders: headers: type: object properties: x-trace-id: type: string description: "Distributed tracing ID" x-span-id: type: string description: "Span ID for tracing"
securitySchemes: sasl: type: scramSha256 description: "SASL/SCRAM-SHA-256 authentication"
apiKey:
type: apiKey
in: user
description: "API key authentication"
oauth2:
type: oauth2
flows:
clientCredentials:
tokenUrl: "https://auth.example.com/token"
scopes:
"events:publish": "Publish events"
"events:subscribe": "Subscribe to events"
serverBindings: kafka: schemaRegistryUrl: "https://schema-registry.example.com" schemaRegistryVendor: "confluent"
C# Models for AsyncAPI
namespace SpecDrivenDevelopment.AsyncApi;
/// <summary> /// Represents an AsyncAPI 3.0 specification document /// </summary> public record AsyncApiSpec { public required string AsyncApi { get; init; } = "3.0.0"; public required AsyncApiInfo Info { get; init; } public Dictionary<string, AsyncApiServer> Servers { get; init; } = []; public string? DefaultContentType { get; init; } public Dictionary<string, AsyncApiChannel> Channels { get; init; } = []; public Dictionary<string, AsyncApiOperation> Operations { get; init; } = []; public AsyncApiComponents? Components { get; init; } }
public record AsyncApiInfo { public required string Title { get; init; } public required string Version { get; init; } public string? Description { get; init; } public AsyncApiContact? Contact { get; init; } public AsyncApiLicense? License { get; init; } }
public record AsyncApiContact { public string? Name { get; init; } public string? Email { get; init; } public string? Url { get; init; } }
public record AsyncApiLicense { public required string Name { get; init; } public string? Url { get; init; } }
public record AsyncApiServer { public required string Host { get; init; } public required string Protocol { get; init; } public string? ProtocolVersion { get; init; } public string? Description { get; init; } public List<Dictionary<string, List<string>>>? Security { get; init; } public Dictionary<string, object>? Bindings { get; init; } }
public record AsyncApiChannel { public required string Address { get; init; } public string? Description { get; init; } public Dictionary<string, AsyncApiParameter>? Parameters { get; init; } public Dictionary<string, AsyncApiMessage>? Messages { get; init; } public Dictionary<string, object>? Bindings { get; init; } }
public record AsyncApiParameter { public string? Description { get; init; } public AsyncApiSchema? Schema { get; init; } public string? Location { get; init; } }
public record AsyncApiOperation { public required OperationAction Action { get; init; } public required AsyncApiChannelRef Channel { get; init; } public string? Summary { get; init; } public string? Description { get; init; } public List<AsyncApiMessageRef>? Messages { get; init; } public List<AsyncApiTag>? Tags { get; init; } public List<Dictionary<string, List<string>>>? Security { get; init; } public Dictionary<string, object>? Bindings { get; init; } }
public enum OperationAction { Send, Receive }
public record AsyncApiChannelRef { public string? Ref { get; init; } }
public record AsyncApiMessageRef { public string? Ref { get; init; } }
public record AsyncApiMessage { public string? Name { get; init; } public string? Title { get; init; } public string? Summary { get; init; } public string? Description { get; init; } public string? ContentType { get; init; } public AsyncApiSchema? Headers { get; init; } public AsyncApiSchema? Payload { get; init; } public AsyncApiCorrelationId? CorrelationId { get; init; } public List<AsyncApiMessageTraitRef>? Traits { get; init; } public Dictionary<string, object>? Bindings { get; init; } }
public record AsyncApiCorrelationId { public string? Description { get; init; } public required string Location { get; init; } }
public record AsyncApiMessageTraitRef { public string? Ref { get; init; } }
public record AsyncApiTag { public required string Name { get; init; } public string? Description { get; init; } }
public record AsyncApiSchema { public string? Type { get; init; } public string? Format { get; init; } public string? Description { get; init; } public List<string>? Enum { get; init; } public object? Default { get; init; } public object? Example { get; init; } public List<string>? Required { get; init; } public Dictionary<string, AsyncApiSchema>? Properties { get; init; } public AsyncApiSchema? Items { get; init; } public int? MinItems { get; init; } public int? MaxItems { get; init; } public int? MinLength { get; init; } public int? MaxLength { get; init; } public decimal? Minimum { get; init; } public decimal? Maximum { get; init; } public string? Pattern { get; init; } public List<AsyncApiSchema>? AllOf { get; init; } public List<AsyncApiSchema>? OneOf { get; init; } public List<AsyncApiSchema>? AnyOf { get; init; } public string? Ref { get; init; } }
public record AsyncApiComponents { public Dictionary<string, AsyncApiSchema>? Schemas { get; init; } public Dictionary<string, AsyncApiMessage>? Messages { get; init; } public Dictionary<string, AsyncApiParameter>? Parameters { get; init; } public Dictionary<string, AsyncApiSecurityScheme>? SecuritySchemes { get; init; } public Dictionary<string, AsyncApiMessageTrait>? MessageTraits { get; init; } public Dictionary<string, AsyncApiOperationTrait>? OperationTraits { get; init; } }
public record AsyncApiSecurityScheme { public required string Type { get; init; } public string? Description { get; init; } public string? In { get; init; } public string? Name { get; init; } public AsyncApiOAuthFlows? Flows { get; init; } }
public record AsyncApiOAuthFlows { public AsyncApiOAuthFlow? ClientCredentials { get; init; } }
public record AsyncApiOAuthFlow { public required string TokenUrl { get; init; } public required Dictionary<string, string> Scopes { get; init; } }
public record AsyncApiMessageTrait { public AsyncApiSchema? Headers { get; init; } public string? ContentType { get; init; } }
public record AsyncApiOperationTrait { public string? Summary { get; init; } public string? Description { get; init; } public List<AsyncApiTag>? Tags { get; init; } }
Event Design Patterns
Event Naming Conventions
event_naming: format: "{Aggregate}{Action}"
past_tense_events: description: "Events describe something that happened" examples: - "OrderCreated" - "OrderShipped" - "PaymentProcessed" - "UserRegistered" - "InventoryReserved"
command_naming: format: "{Action}{Aggregate}Command" examples: - "CreateOrderCommand" - "CancelOrderCommand" - "ProcessPaymentCommand"
channel_naming: pattern: "{domain}.{type}.{resource}" examples: - "orders.events" (all order events) - "orders.events.{orderId}" (specific order) - "orders.commands" (order commands) - "inventory.updates.{productId}" (inventory changes)
Event Envelope Pattern
event_envelope: description: "Standardized wrapper for all events"
structure: metadata: eventId: "UUID - unique event ID" eventType: "String - event type name" version: "String - schema version" timestamp: "ISO 8601 timestamp" correlationId: "UUID - request correlation" causationId: "UUID - causing event ID" source: "String - producing service"
data: "Actual event payload"
example: metadata: eventId: "550e8400-e29b-41d4-a716-446655440000" eventType: "OrderCreated" version: "1.0" timestamp: "2025-01-15T10:30:00Z" correlationId: "660e8400-e29b-41d4-a716-446655440001" source: "order-service" data: orderId: "order-123" customerId: "customer-456" totalAmount: amount: 99.99 currency: "USD"
Schema Evolution
schema_evolution: strategies: backward_compatible: description: "New schema can read old data" allowed_changes: - "Add optional fields" - "Add new enum values at end" - "Widen numeric ranges" disallowed_changes: - "Remove required fields" - "Change field types" - "Rename fields"
forward_compatible:
description: "Old schema can read new data"
approach: "Ignore unknown fields"
full_compatible:
description: "Both directions work"
best_practice: "Default for most systems"
versioning: header_based: example: "version: '1.0'"
channel_based:
example: "orders.events.v2"
semantic:
format: "major.minor"
major: "Breaking changes"
minor: "Backward-compatible additions"
Validation Checklist
asyncapi_validation_checklist: structure: - "Valid AsyncAPI 3.0.0 syntax" - "All required fields present" - "No undefined $ref references" - "Consistent naming conventions"
channels: - "Clear channel addressing scheme" - "Parameters defined for dynamic channels" - "All messages referenced exist"
operations: - "Action (send/receive) correctly specified" - "Channel reference valid" - "Summary and description provided" - "Appropriate tags assigned"
messages: - "Unique message names" - "Clear title and summary" - "Headers schema defined" - "Payload schema complete" - "Correlation ID specified where needed"
schemas: - "All required fields listed" - "Types and formats specified" - "Examples provided" - "Validation constraints appropriate"
security: - "Security schemes defined for production" - "Operations specify security requirements"
documentation: - "API description explains purpose" - "Contact information provided" - "Server URLs for all environments"
References
-
references/messaging-patterns.md
-
Event-driven messaging patterns
-
references/protocol-bindings.md
-
Protocol-specific configurations
Last Updated: 2025-12-26