Substructure vs. Mastra for AI agents
Checked August 7, 2026
Mastra is for TypeScript teams building an agent into their own app: agents, workflows, memory, RAG, evals, and observability in one package, with a stable 1.0 since January 2026. Substructure is for teams who want the agent itself: config in git, running in Slack, with every step of the loop open to your code, in any language.
| Use Mastra when | Use Substructure when |
|---|---|
| The agent is a feature of your app | The agent is a teammate in Slack |
| You want memory, RAG, and evals in your repo | You want Slack, MCP auth, and history already built |
| Your team is TypeScript | Your code is Go, Ruby, or anything on HTTP |
What Substructure does that Mastra does not
- Restarts a dead run by itself. Mastra persists snapshots at suspension points, and resume is a call your code makes. Their deployment docs point at Inngest for production durability.
- Installs Slack in one command. Channels is a real Slack story, but you create the Slack app, wire the signing secret, and run one app per agent.
- Holds the MCP credentials. In Mastra you configure OAuth in code.
- Runs your code in any language. Mastra is TypeScript, in your process.
- Charges one flat price. Mastra Platform meters observability events, CPU-hours, and egress, with always-on servers at $100 per project and a Team tier at $250 a month.
Side by side
Building the agent
| Mastra | Substructure | |
|---|---|---|
| The agent is | TypeScript in your process | A file in your repo |
| Language | TypeScript | Any language, over HTTP |
| Models | A router with 600+ models | Any provider, one line |
| Memory, RAG, evals | First-party | Not included |
| Loop control | Workflows in your code | Every step, over the wire |
Running it
| Mastra | Substructure | |
|---|---|---|
| Durability | Snapshots at await suspend() | Every step, before it runs |
| Resume | Your code calls it | The engine does it |
| Deployment | A Hono server you host | The cloud, or one binary |
Surfaces and price
| Mastra | Substructure | |
|---|---|---|
| Slack | Channels; one app per agent | One app per workspace |
| MCP auth | Configured in your code | The engine's |
| Browser clients | AG-UI | AG-UI |
| Licence | Apache 2.0, plus a source-available layer | Open source, the full product |
| Price | Metered events, CPU-hours, egress | Flat, bring your own key |
What you write
export const oncall = new Agent({
name: "oncall",
instructions: "You are the on-call assistant.",
model: "openai/gpt-5",
tools: { getIncident },
});[agent.oncall]
llm = "openrouter"
model = "moonshotai/kimi-k3"
system = "You are the on-call assistant."
mcp = [{ id = "sentry", tools = { read_only = true } }]
[agent.oncall.slack]
name = "Oncall"Add a worker URL to that file and the engine sends every decision to your
endpoint as JSON, one step at a time.
Where Mastra is the better choice
- The best TypeScript developer experience in this space.
- One command scaffolds a project, and the Studio playground is excellent.
- Memory, RAG, scorers, and tracing are all first-party.
- A large community and a fast release cadence.
Questions
Can my worker be TypeScript? Yes, and it can also be Rails, Go, or Python. It is a stateless HTTP endpoint.
Do I lose the model router? You name the model in config and change it in one line. There is no autocomplete over 600 of them.
Can I use both? Yes. A worker can call a Mastra agent you already have.
The quick start takes about five minutes.