Skip to content

Architecture

Pavel Erokhin edited this page Oct 22, 2026 · 5 revisions

The backend is one Bun process with MongoDB beside it. A question goes through it like this.

A question's way

  1. The plugin posts to /api/v2/chat. src/features/auth/caller.ts identifies the server by its license or PLUGIN_TOKEN and names its tenant; src/features/chat/ validates the body and opens the SSE stream.
  2. src/features/billing/gate.ts decides who pays: the plugin's own key, a license with money left, or the backend's key on a self-hosted backend. Limits count per tenant.
  3. src/agent/ assembles the prompt from src/prompts/*.md, the player's memories, and the session, then runs the Mastra agent.
  4. When the model calls a game tool, the bridge in src/features/chat/ sends a tool_call event and waits for the plugin's POST /api/v2/chat/{run}/tools/{call}.
  5. Server tools (search_web, exact_calculations, memories) run in src/features/tools/, and get_locations adds the death history from MongoDB.
  6. The answer streams back. Afterwards the session is saved to MongoDB, sealed, folded into a summary when it grows too long, and the run's numbers land in MongoDB.

The bridge keeps pending calls in memory, so the backend runs as one instance.

The code

Path What it does
src/application/ Entrypoint, routes, shared dependencies
src/features/chat/ POST /api/v2/chat: the SSE stream and the tool bridge
src/features/ask, src/features/askx v1 endpoints; their request and response shapes stay
src/features/tools/ Client tool definitions (run by the plugin) and the server tools
src/features/users/ Sessions and memories for /allay new, /allay memory, /allay forget; a player's export and erasure
src/features/auth/ Who sent a request, and its tenant
src/infrastructure/database/migrations.ts What runs on start, and the migrate command
src/agent/ The agent runner, prompt assembly, the session summarizer, askx command validation
src/prompts/*.md The system prompts, bundled into the build
src/infrastructure/ Sessions, memories, deaths, players' state, and export links in MongoDB, sealed by crypto/data.ts; the OpenRouter provider; traces, sealed by observability/sealing.ts
src/features/billing/, src/infrastructure/billing/ Who pays, plans, licenses, budget windows, payments
src/features/telegram/ The payment bot: Stars invoices, payments, renewals, refunds
src/features/settings/ Every setting with its type, bounds, and default (settings.definitions.ts)
src/features/admin/, src/infrastructure/admin/ The admin panel's API, accounts, sessions, the audit log
admin/ The panel: React, Vite, shadcn/ui, TanStack Router and Query
docs/protocol-v2.md The contract with the plugin

Prompts

The prompts live in src/prompts: minecraft-ask.md, minecraft-askx.md, minecraft-task.md for automation agents, and telegram.md. They ship inside the build. Each run appends who asks, their language, and the server version.

Settings

A setting is read through settings.get(...) where it's used: the environment first, then MongoDB, then the default. A save in the panel applies to the next run. Only what the backend needs to start reads process.env directly.

Storage

Everything is in MongoDB (since 6.8; Redis before):

  • Players' data, sealed (since 6.9): chat sessions and their summaries, public and task threads (keyed by tenant first), memories and places, deaths, players' state, and the words in Mastra's traces.
  • In the clear: licenses and payments, admin accounts, panel sessions (by the cookie's digest), the audit log, stored settings (their secrets sealed), the runs collection with its rollups (players as pseudonyms), the player directory that names pseudonyms for the panel, consents, and export links (by the token's digest).

Next: Building from source

Clone this wiki locally