---
title: "Mastra for AI agents (2026): workflows suspend resume, durable execution, observational memory, model router and the Mastra 1.0 release — Cadenya"
url: "https://cadenya.com/other-content/mastra-for-ai-agents"
description: "Mastra for AI agents in 2026, since the Mastra 1.0 release: Mastra workflows suspend resume with PostgresStore and Postgres storage, durable agents and durable execution with Redis or Inngest, tool approval and human in the loop with listSuspendedRuns, observational memory and model router costs, MCP and OpenAPI tools, the Vercel, Netlify and Cloudflare deployers, Mastra Cloud pricing on the Mastra platform, and Cadenya, a hosted agent loop with tool approval and conversation state built in."
---

Mastra is a TypeScript framework for AI agents, and it runs inside a server process that you deploy. Since the Mastra 1.0 release, it covers agents with tools and a model router, observational memory, MCP, evals, and a local dev server. Mastra workflows suspend, resume, and survive a restart through a snapshot in your storage. So in production you run the rest yourself: a server or a deployer, plus Postgres storage (or another adapter) for snapshots and memory. Durable agents and durable execution across several instances add a shared cache and an event bus, such as Redis.

Pick Mastra when your team writes TypeScript and wants agents, workflows, memory, and evals in one framework, on the host you already use. Pick the Mastra platform when you want Mastra to build and host that server and bill it by the CPU hour. And if you’d rather host no server, database, or cache at all, Cadenya is a hosted agent loop with tool approval, conversation state, and context compaction built in, and a coding agent can set it up with no account, in a temporary workspace you claim later. [What it offers](#what-does-cadenya-offer-that-mastra-doesnt) is at the end.

Every price and limit below comes from each vendor’s own pages, checked on October 29, 2026.

## What Mastra does today, since the Mastra 1.0 release

`@mastra/core` 1.80.0 shipped on October 28, 2026, under Apache-2.0, and folders named `ee/` in the repo carry a separate license. It needs Node.js 22.13.0 or later, and Mastra also runs on Bun, Deno, and Cloudflare. Here’s what it includes:

1.  An **agent** takes instructions, tools, memory, and a `"provider/model"` string for the model router, then calls tools until the model gives a final answer.
2.  A **tool** is a `createTool()` call with an ID, a description, a Zod `inputSchema`, and an `execute` function.
3.  A **workflow** from `createWorkflow()` chains typed steps with branching, parallel steps, loops, and `suspend()`, on a built-in engine or on Inngest.
4.  **Memory** starts with message history, and agents can add observational memory, working memory, and semantic recall, all kept in your storage.
5.  **MCP** works in both directions: `MCPClient` connects agents to MCP servers, and `MCPServer` exposes your agents, tools, and workflows to MCP clients. Both speak the MCP `2026-07-28` revision over stdio or Streamable HTTP.
6.  **Evals** use scorers from `@mastra/evals` that grade outputs, usually from 0 to 1, on an agent or a workflow step, with a sampling rate.
7.  The **dev server**, `npx mastra dev`, opens Studio at `localhost:4111`, serves your agents, tools, and workflows under `/api`, and restarts when a file in `src/mastra/` changes.

What about OpenAPI tools? Mastra’s tools page covers tools you write with `createTool()`, tools from remote MCP servers, and ready-made Connect tools on the Mastra platform for services like Linear, Slack, and GitHub. **In Mastra, OpenAPI describes the server you deploy:** with `server.build.openAPIDocs` on, the server publishes a spec of its own routes at `/api/openapi.json`. [TypeScript AI agent frameworks compared](/other-content/typescript-ai-agent-frameworks-compared) covers the 1.0 changes and puts Mastra next to LangGraph.js, the AI SDK, and OpenAI Agents JS.

## Mastra observational memory and the model router: what they need and cost

Observational memory runs on model calls of its own: when message history passes 30,000 tokens, an Observer model writes short notes about what happened. When the notes pass 40,000 tokens, a Reflector model condenses them. With the default `model: 'auto'`, both use `google/gemini-2.5-flash` if `GOOGLE_GENERATIVE_AI_API_KEY` is set, and otherwise a low-cost model from your main model’s provider.

**It also needs one of six storage adapters:** `@mastra/pg`, `@mastra/libsql`, `@mastra/mysql`, `@mastra/mongodb`, `@mastra/convex`, or `@mastra/oracledb`. Semantic recall is off by default, and turning it on takes a vector store and an embedder.

The model router needs each provider’s key in an environment variable, such as `OPENAI_API_KEY` for any `openai/` model, and each provider bills you directly. On the Mastra platform, the gateway bills input and output tokens at “Market Rate + 5.5%”, or you bring your own key. [Agent memory and context windows](/other-content/agent-memory-and-context-windows) compares observational memory with LangGraph and the model APIs.

## Mastra deployers, server adapters and Mastra Cloud side by side

Mastra Cloud is now the Mastra platform, with separate Studio and Server products that you deploy with `mastra deploy` or on a push to GitHub. The framework itself deploys anywhere Node.js runs, in four main ways:

|  | What you deploy | Where state lives | What it costs |
| --- | --- | --- | --- |
| Mastra server | mastra build writes a Hono server to .mastra/output for a VM, container, or PaaS | Any storage adapter, with a local libSQL file kept to one process | Your hosting |
| Server adapters | Mastra’s routes inside your own Express, Hono, Fastify, Koa, NestJS, Next.js, Elysia, or TanStack Start app | Any storage adapter | Your hosting |
| Vercel, Netlify, and Cloudflare deployers | Serverless functions on Vercel or Netlify, or a Cloudflare Worker | A database hosted elsewhere, because the filesystem is ephemeral | Your plan on that platform |
| Server on the Mastra platform | mastra deploy builds a Docker image, and Mastra runs it at a stable URL | Hosted storage provisioned on deploy, plus hosted Turso, Neon, or Postgres databases | Starter: $0 with 24 CPU hours, then $0.35 an hour. Teams: $250 a month with 250 CPU hours, then $0.25 an hour |
| Cadenya | Nothing: the loop runs on Cadenya, and your app calls an API | On Cadenya: each objective keeps a durable event log | Free for 1,000 loops a month, $49 a month for 50,000, then $0.0015 a loop |

On the platform, hosted Postgres includes 5 compute hours, then $0.50 an hour on Starter or $0.40 on Teams. Hosted database storage past 1 GB is $1 a GB-month on Starter or $0.75 on Teams.

**Every option runs the agent loop inside a process you deploy.** So a deploy can end a turn in the middle. Mastra’s docs say a plain `agent.stream()` call “can’t resume after its server process exits,” and the client has to retry or reconcile that turn. Durable agents keep the turn, with more infrastructure (two sections down).

## Mastra workflows: suspend, resume and Postgres storage

[TypeScript AI agent frameworks compared](/other-content/typescript-ai-agent-frameworks-compared) shows the `PostgresStore` setup.

A suspended Mastra workflow is a snapshot in your storage, keyed by its run ID. It holds each step’s status and output, the suspend and resume payloads, and the retry attempts left. [Durable execution for AI agents](/other-content/durable-execution-for-ai-agents) shows the `suspend()` and `resume()` calls.

For production, Mastra’s storage guide asks for a managed database with backups, monitoring, and connection pooling, and it names PostgreSQL as a good default. `PostgresStore` creates tables such as `mastra_workflow_snapshot`, `mastra_threads`, and `mastra_messages` on first use, and `disableInit: true` turns that off when your CI runs migrations. And `MastraCompositeStore` can route storage domains (memory, workflows, scores, schedules, and more) to different backends.

After a restart, your code finds the suspended run in storage and resumes it with Mastra’s state reader:

```
import { createWorkflowStateReader } from '@mastra/core/workflows'

const workflow = mastra.getWorkflow('testWorkflow')
const state = await workflow.getWorkflowRunById('run-123')

if (state?.status === 'suspended') {
  const reader = createWorkflowStateReader(state)
  const suspendedStep = reader.getSuspendedStep()
  const approvalLabel = reader.getResumeLabel('approve')

  const run = await workflow.createRun({ runId: state.runId })
  await run.resume({
    step: approvalLabel?.stepId ?? suspendedStep?.path,
    resumeData: { approved: true },
    forEachIndex: approvalLabel?.foreachIndex,
  })
}
```

**A running step is a different case.** A run holds a storage lease while it works. If a process stops renewing that lease but keeps executing the step, Mastra’s docs warn that recovery “can run that step a second time.” So keep steps with side effects idempotent, and [retries and idempotency for agent tool calls](/other-content/retries-and-idempotency-for-agent-tool-calls) shows how.

## Mastra durable agents and durable execution in production

A regular Mastra agent’s stream ends with its process. A durable agent runs the loop inside a workflow, publishes each chunk to an event bus, and lets a client reconnect with `observe(runId)`. Mastra ships three kinds:

1.  `createDurableAgent()` serves local development and single-process servers, with no extra infrastructure.
2.  `createEventedAgent()` starts the workflow in the background and hands you the chunks through the event bus.
3.  `createInngestAgent()` from `@mastra/inngest` runs the loop on Inngest with step memoization and retries.

**The defaults keep everything in one process:** an in-memory replay cache and a Node.js `EventEmitter` as the event bus. A second instance needs three shared pieces: a cache such as `RedisServerCache` from `@mastra/redis`, a distributed event bus such as `RedisStreamsPubSub`, and run storage. Recovery across replicas also needs a store with run fencing, like `@mastra/pg`, `@mastra/libsql`, or `@mastra/mongodb` on a replica set, or an event bus whose lease every replica shares.

Crash recovery stays off until you turn it on:

```
import { Mastra } from '@mastra/core'
import { PostgresStore } from '@mastra/pg'

export const mastra = new Mastra({
  agents: { myAgent: durableAgent },
  storage: new PostgresStore({ connectionString: process.env.DATABASE_URL! }),
  recovery: { durableAgents: 'auto' },
})
```

With it on, the server re-drives runs stuck in `running` from their last snapshot when it boots. The docs warn that recovery “can reissue LLM calls (with real cost) and re-execute tool calls,” so tools with side effects need to be idempotent. Splitting workflow steps, schedules, and background tools into worker processes adds a distributed event bus, shared storage, and a network path to the API.

## Mastra tool approval and human in the loop after a restart

Mastra pauses a tool call in two ways. `requireApproval` on a tool, or `requireToolApproval` on a call, stops it before `execute` runs, and a tool can also call `suspend()` inside `execute` to ask the user for data. [TypeScript AI agent frameworks compared](/other-content/typescript-ai-agent-frameworks-compared) shows the approve and decline calls.

In production, the decision often arrives after a page refresh, after a restart, or on another instance. `listSuspendedRuns()` finds the pending run for a thread in storage:

```
// In the request handler that receives the user's decision
const { runs } = await agent.listSuspendedRuns({
  threadId: 'thread-123',
  resourceId: 'user-456',
})

const run = runs[0]
const toolCall = run?.toolCalls[0]

if (run && toolCall) {
  let stream
  if (toolCall.requiresApproval) {
    // Suspended by requireApproval: approve or decline the tool call
    stream = await agent.approveToolCall({ runId: run.runId, toolCallId: toolCall.toolCallId })
  } else {
    // Suspended by suspend(): resume with the data the tool asked for
    console.log('Tool asked:', toolCall.suspendPayload)
    stream = await agent.resumeStream({ name: 'San Francisco' }, { runId: run.runId })
  }
  for await (const chunk of stream.textStream) process.stdout.write(chunk)
}
```

Each run lists its suspended tool calls with `requiresApproval`, so your handler knows whether to approve or to resume with data. The same lookup works over HTTP as `GET /agents/:agentId/suspended-runs`. **Suspended runs only survive a restart on a persistent storage provider**, so this is one more job for your Postgres storage.

Two details matter for a chat or Slack agent. An approval request from a subagent goes up to the supervisor, so you answer it once, at the top. And `autoResumeSuspendedTools: true` resumes a `suspend()` tool from the user’s next message on the same thread, but it never approves a `requireApproval` tool. [Human-in-the-loop approvals for AI agents](/other-content/human-in-the-loop-approvals-for-ai-agents) compares how other frameworks pause and resume a tool call.

## What does Cadenya offer that Mastra doesn’t?

Mastra gives you the agent loop as a library, and you run the server and the database around it, plus a cache and an event bus once you scale out. **Cadenya runs the loop for you, with tool approval, conversation state, and context compaction built in, and nothing to host.** Use it in place of a Mastra server. Here’s what that covers:

1.  **There’s nothing else to run.** You add no Postgres for snapshots, no Redis cache or event bus, no worker, no Inngest, and no Mastra server to build. The loop runs on Cadenya and your app stays a stateless web tier, so your deploys and restarts never touch a running objective.
2.  **There’s no server to license.** Cadenya hosts the engine, so there’s no `ee/` folder to check, and the TypeScript, Python, Ruby, and Go SDKs are Apache-2.0.
3.  **You keep no old code alive while runs wait.** Cadenya picks the variation once, when it creates the objective, and the objective keeps that configuration snapshot even if you edit the variation later.
4.  **Approvals wait outside your process.** When a tool needs approval, Cadenya parks the loop on `toolApprovalRequested`, and several tool calls can wait at once. Your backend answers through the API or a webhook handler, with no run state in your app.
5.  **The SDKs ship often.** All four SDKs are at 1.9.0, and the TypeScript SDK has shipped 113 versions since April 2026. It runs on Node.js 18, where Mastra’s packages ask for 22.13.0.
6.  **The price fits in one line.** Free covers 1,000 loops a month with no card, and Growth is $49 a month for 50,000 loops, then $0.0015 a loop. A loop is one LLM request made during an objective, so there are no CPU hours or database rows to estimate.
7.  **The agent loop is already written.** Cadenya calls the model, runs the tools, streams its events over server-sent events, and compacts the context window as a conversation grows. Each objective keeps a durable event log, and a waiting objective resumes with its history when your user sends a Continue message.
8.  **Tools come from your OpenAPI spec or an MCP server.** Point a tool set at an OpenAPI 3 document, and Cadenya reads every operation and checks a URL source for changes each hour. A tool set can also take an MCP server’s URL as its source.
9.  **The approval screen comes included.** The React UI kit’s `ConversationsPanel` supplies the conversation list, message thread, composer, tool approvals, and live event stream. A denial carries a memo that steers the agent (“Use the read-only lookup tool instead.”).
10.  **You pick any model from your own provider.** The model is a setting on a variation, chosen from the AI providers in your workspace, and you pay your provider directly. Your code points at the agent, so a model change happens in a variation, not in a deploy.

[How objectives work](/docs/guides/the-basics/objectives) covers the event log, approvals, and Continue, and the free plan needs no card.

No account yet? A coding agent can create a temporary workspace with `cadenya workspaces create --temporary`, run its first objectives there, and hand you a link to claim it, as [auth.md](https://cadenya.com/auth.md) explains. To create an account, sign up at [app.cadenya.com/signup](https://app.cadenya.com/signup?utm_source=cadenya.com&utm_medium=article&utm_campaign=mastra-for-ai-agents), then copy your API key from the API keys page at `app.cadenya.com/account/apiKeys`.