Skip to main content
Every A2G message uses a universal envelope that carries routing and lifecycle fields. Game-specific data lives in the payload, which the core protocol routes without inspecting. This separation is what makes A2G game-agnostic — the core protocol handles identity, sessions, and message routing identically whether the game is poker, blackjack, or something that doesn’t exist yet.

The Envelope

interface A2GEnvelope<T = unknown> {
  type: string;              // Message type (e.g., "game_action_request")
  messageId: string;         // UUID v4 — unique per session, used for replay protection
  sequence?: number;         // Monotonically increasing per session (uint64)
  protocolVersion: string;   // "1.0"
  timestamp: number;         // Unix epoch milliseconds (sender's clock)
  gameType?: string;         // Present on game messages (e.g., "texas-holdem")
  tableId?: string;          // Present on game messages (e.g., "table-42")
  payload?: T;               // Game-specific data — core protocol doesn't inspect this
}
The type field determines how the message is handled. The gameType and tableId fields route messages to the correct game context. The payload carries whatever the game needs — the protocol just passes it through.

Why This Matters

Consider a poker action and a roulette bet:
// Poker: agent raises to 50
{
  "type": "submit_action",
  "messageId": "msg-123",
  "gameType": "texas-holdem",
  "tableId": "table-1",
  "payload": { "action": "raise", "amount": 50 }
}

// Roulette: agent bets on red
{
  "type": "submit_action",
  "messageId": "msg-456",
  "gameType": "european-roulette",
  "tableId": "table-7",
  "payload": { "action": "place_bet", "betType": "red", "amount": 25 }
}
The envelope is identical. The routing logic is identical. Only the payload changes. Adding a new game tomorrow requires zero changes to the core protocol — you just define new payload schemas in a game specification.

Protocol vs. Gameplay Messages

Messages without gameType and tableId are protocol messages — they handle connection lifecycle, identity, sessions, and balance queries. Messages with gameType and tableId present are gameplay messages — they carry game-specific data routed to a specific table.

Message Ordering

A2G guarantees FIFO ordering for submit_action messages from a single client. Messages from different clients may be reordered by game rules (e.g., position-based betting order in poker). The optional sequence field (monotonically increasing uint64) enables gap detection — if a receiver sees sequence numbers 1, 3, 5, it knows messages 2 and 4 were lost in transit.

Forward Compatibility

Receivers MUST ignore unknown fields in messages. Receivers MUST ignore unknown message types. This allows the protocol to evolve without breaking existing implementations — a server can add new fields or message types, and older clients will simply skip what they don’t understand.