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 whenUse Substructure when
The agent is a feature of your appThe agent is a teammate in Slack
You want memory, RAG, and evals in your repoYou want Slack, MCP auth, and history already built
Your team is TypeScriptYour 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

MastraSubstructure
The agent isTypeScript in your processA file in your repo
LanguageTypeScriptAny language, over HTTP
ModelsA router with 600+ modelsAny provider, one line
Memory, RAG, evalsFirst-partyNot included
Loop controlWorkflows in your codeEvery step, over the wire

Running it

MastraSubstructure
DurabilitySnapshots at await suspend()Every step, before it runs
ResumeYour code calls itThe engine does it
DeploymentA Hono server you hostThe cloud, or one binary

Surfaces and price

MastraSubstructure
SlackChannels; one app per agentOne app per workspace
MCP authConfigured in your codeThe engine's
Browser clientsAG-UIAG-UI
LicenceApache 2.0, plus a source-available layerOpen source, the full product
PriceMetered events, CPU-hours, egressFlat, bring your own key

What you write

agents/oncall.ts
export const oncall = new Agent({
    name: "oncall",
    instructions: "You are the on-call assistant.",
    model: "openai/gpt-5",
    tools: { getIncident },
});
subs.toml
[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.