Skip to content

Architecture

How it fits

Mastra’s architecture has one organizing idea: a single runtime owns execution. Your application code talks to that runtime; the runtime talks to agents, workflows, tools, storage, and the model providers. Get this boundary right and everything else stays clean.

The package boundary keeps the app layer and the Mastra layer separate. The app (routes, jobs, UI handlers) depends on the Mastra instance — never on individual steps or tools directly.

Mastra — package boundary

Package boundary map The web app calls server API routes, which call the LLM platform. The LLM platform uses shared contracts, database, blocks, surfaces, export, and observability packages or split locations. apps/web editor · hooks · UI present server/api auth · stream · run control present llm-platform runtime authority workflows · agents · tools shared schemas · contracts db package + app schema observability split today blocks schemas + registry renderers in web exports existing package rename candidate surfaces vocab + web shells split today
The app layer depends on the Mastra runtime; the runtime owns agents, tools, workflows, storage, and provider calls. Crossing the boundary the other way (a route importing a step) is the anti-pattern. Reuse — path exists Split — consolidate ownership Authority

Routes call the runtime. The runtime calls everything else.

Mastra runtime ownership

Runtime ownership diagram Server routes call a single runtime. The runtime coordinates workflows, agents, tools, storage, and observability. A red dashed line shows the anti-pattern where routes bypass the runtime and import step functions directly. User Prompt editor · chat · live cards Server Route auth · workspace · credits Runtime Registry brain: knows every part runManager commands Workflows steps · checkpoints Agents orchestrator + workers Tools search · image · validate Storage + DB snapshots · events · ledger Observability Langfuse · logs · cost anti-pattern: route imports step/tool directly
Press Play flow: a prompt enters at the server route, the Mastra runtime resolves the agent/workflow, tools and storage are invoked, and the result returns through the same runtime. Runtime authority Anti-pattern — bypasses the runtime

A typical request:

  1. Server route receives the prompt/request.
  2. It asks the Mastra instance for the agent or workflow (mastra.getAgentById(...) / mastra.getWorkflow(...)).
  3. The runtime executes — the agent reasons and calls tools; a workflow walks its steps (branching, parallel, or suspending for human input).
  4. Memory and storage are read/written through the runtime; telemetry is emitted for every call.
  5. The result returns up through the runtime to the route.

The runtime owns persistence: workflow snapshots (so a suspended run can resume), conversation threads (memory), and telemetry. Because it all goes through one place, swapping a storage backend is a config change, not a refactor of your routes.

Centralizing execution buys you: consistent config (one place sets models, storage, telemetry), testability (mock the runtime, not a web of imports), swappable backends, and a single trace per request. The moment a route imports a workflow step directly, you lose all four.


Next: Building agents — the minimal end-to-end agent.