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.
What talks to what
Section titled “What talks to what”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
How one request flows
Section titled “How one request flows”Routes call the runtime. The runtime calls everything else.
Mastra runtime ownership
A typical request:
- Server route receives the prompt/request.
- It asks the Mastra instance for the agent or workflow (
mastra.getAgentById(...)/mastra.getWorkflow(...)). - The runtime executes — the agent reasons and calls tools; a workflow walks its steps (branching, parallel, or suspending for human input).
- Memory and storage are read/written through the runtime; telemetry is emitted for every call.
- The result returns up through the runtime to the route.
Persistence & storage
Section titled “Persistence & storage”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.
Why one runtime
Section titled “Why one runtime”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.