Mastra vs LangChain.js and LangGraph.js for production TypeScript agents: workflows, memory, human-in-the-loop, deployment, and when to pick each.

TL;DR: Mastra is a TypeScript-native, batteries-included agent framework that bundles agents, step-based workflows, memory, evals, a local Studio and an HTTP server in one Apache-2.0 package. LangChain.js is a modular MIT-licensed toolkit whose createAgent runs on LangGraph.js, a lower-level graph runtime with checkpointers and interrupts. Choose Mastra for a fast, opinionated path to a deployed TypeScript agent service. Choose LangChain.js plus LangGraph.js when you need explicit control flow, the widest integration catalog, or parity with a Python LangChain codebase.
Both frameworks answer the same question for TypeScript developers: how do you turn a model API into an agent that calls tools, remembers context, survives restarts and runs in production? They answer it with different philosophies.
Mastra is an open-source TypeScript framework for building AI agents and workflows, created in 2024 by the team behind Gatsby. Its core package, @mastra/core, is Apache-2.0 licensed and at version 1.78 as of October 2026, and its GitHub repository has passed 28,000 stars. Mastra is TypeScript-first rather than a port: there is no Python sibling to stay in sync with. You define agents with new Agent(), tools with createTool(), and workflows with createWorkflow() and createStep(), then register them on a single Mastra instance that also owns storage, logging and the HTTP server. Model access goes through Mastra's model router using provider/model strings, and it builds on Vercel AI SDK provider interfaces under the hood.
LangChain.js is the JavaScript and TypeScript implementation of LangChain, MIT licensed, with the langchain package at version 1.5 and roughly 18,000 GitHub stars. Since the 1.0 release, its primary agent entry point is createAgent, described in the docs as "a model calling tools in a loop" wrapped in a configurable harness of prompt, tools and middleware. That agent runs on LangGraph.js (@langchain/langgraph, version 1.5), the lower-level runtime that provides graph state, checkpointers, stores, interrupts and streaming. LangChain.js also brings the largest integration catalog in the JS ecosystem: model providers, vector stores, document loaders and retrievers.
So "Mastra vs LangChain" is really two comparisons. At the high level, Mastra's Agent competes with LangChain's createAgent. At the orchestration level, Mastra's workflow engine competes with LangGraph.js.
The minimal tool-calling agent is close in both frameworks. The difference is where it lives, not how long it is.
Here is a Mastra agent with one typed tool. Mastra requires tools to be built with createTool(); plain object tool definitions are not executed.
The same agent in LangChain.js uses createAgent and the tool() helper:
Two small details reveal the philosophies. Mastra's tool carries an outputSchema, so the tool's return value is typed end to end, and the agent is meant to be registered on a Mastra instance where Studio, the server and storage can find it. LangChain's agent is a standalone graph you can invoke anywhere, and its behavior is extended by passing middleware rather than by registering it into an application container.
Note the model string separator: Mastra uses provider/model with a slash, while LangChain uses provider:model with a colon. It is a trivial difference that causes real confusion when porting code between them.
This is the heart of the "Mastra vs LangGraph.js" question, because orchestration is where most production complexity ends up.
Mastra workflows are chains of typed steps. Each step is created with createStep() and declares an inputSchema and outputSchema. You compose steps with createWorkflow() and fluent operators such as .then(), .branch() and .parallel(), then call .commit(). Because every step boundary has a schema, TypeScript checks that the output of one step fits the input of the next. The mental model is a typed pipeline: data flows forward through declared stages, and agents or tools are called from inside steps.
LangGraph.js graphs are state machines. You define a state schema, add nodes that read and update that state, and connect them with edges, including conditional edges that route on the current state and cycles that loop back. Every node sees the same shared state object rather than just the previous node's output. The mental model is a flowchart with memory: any node can be revisited, and the topology of what can happen next is explicit.
The practical trade-off:
If your production workflow can be drawn as a left-to-right diagram with a few forks, Mastra's model will feel natural. If it needs arrows pointing backwards, LangGraph.js expresses that more directly.
Both frameworks support durable pauses, which is a hard requirement for any agent that takes consequential actions such as refunds, emails or deployments.
In Mastra, a step declares a resumeSchema and calls suspend() when it needs input. The workflow's current execution state is saved as a snapshot in the configured storage provider, so it survives deployments and restarts. Later, from an HTTP endpoint, a queue consumer or a timer, you call run.resume() with data matching the schema:
Passing the step object to resume() gives full type safety on resumeData.
In LangGraph.js, a node calls interrupt() with a JSON-serializable payload. The checkpointer saves graph state, the caller receives the payload under __interrupt__, and you resume by invoking the graph again with new Command({ resume: value }) and the same thread_id:
One behavior to design around: when LangGraph.js resumes, the interrupted node restarts from its beginning, so any code before interrupt() runs again. Keep side effects after the interrupt, or make them idempotent. Mastra's suspend pattern has the same practical implication, because the step's execute runs again with resumeData populated. In both frameworks, the safe pattern is identical: decide, pause, then act.
At the createAgent level, LangChain.js also offers human-in-the-loop middleware that pauses before selected tool calls, which covers the common "approve this tool call" case without hand-writing a graph.
Mastra treats memory as an agent feature. You install @mastra/memory, attach a Memory instance to an agent, and pass a resource (the user) and a thread (the conversation) on each call. On top of plain message history, Mastra offers working memory for structured user facts, semantic recall that retrieves past messages by meaning, and observational memory, which uses background agents to compress history into a dense observation log so the context window stays small. All of it is persisted through the storage provider registered on the Mastra instance, the same storage that holds workflow snapshots.
LangGraph.js treats memory as graph persistence. It separates two systems. Checkpointers persist a thread's graph state at each step, which gives you conversation continuity, human-in-the-loop, time travel and fault tolerance, keyed by thread_id. Stores persist application-defined data across threads, such as user preferences and shared facts. You choose the backend: MemorySaver for development (it loses everything on restart), and Postgres or SQLite checkpointers for production.
The difference matters operationally. Mastra gives you a higher-level, more opinionated memory model with fewer decisions to make. LangGraph.js gives you lower-level primitives that you assemble, which is more work but makes every checkpoint inspectable and replayable. Teams that need to audit exactly what state an agent held at step 7 of a run tend to value LangGraph's checkpoint model; teams that want "the agent remembers the user" with minimal setup tend to value Mastra's.
There is no universal winner, but the decision usually comes down to five questions.
1. Is your team TypeScript-only? Mastra was designed for TypeScript from the first commit, and its types run through tools, steps and resume data. LangChain.js is fully typed too, but its concepts and docs are shared with Python LangChain. If you have Python services using LangGraph, staying on LangChain.js keeps one mental model across both languages.
2. How complex is your control flow? Mostly linear pipelines with branches and parallel steps favor Mastra's workflow engine. Cyclic agent loops, supervisor routing and multi-agent graphs favor LangGraph.js.
3. How much do you want bundled? Mastra ships an HTTP server, a local Studio, evals, tracing and storage wiring in the same framework. LangChain.js leaves serving to you or to LangSmith's deployment product, and its strongest observability story is LangSmith, which is a hosted service. Count the pieces you would otherwise assemble yourself.
4. How many integrations do you need? If your agent needs an unusual vector store, document loader or retriever, LangChain.js is far more likely to have an existing adapter. Mastra covers the mainstream providers well and can call any TypeScript library from a tool, but it does not try to match LangChain's catalog.
5. How much churn can you absorb? Both projects release frequently. Mastra's core moved through dozens of minor 1.x versions in 2026, and LangChain.js changed its agent API substantially at 1.0. Pin versions, read changelogs before upgrading, and keep agent logic behind your own interfaces so a framework upgrade does not ripple through your codebase.
A practical rule of thumb:
Yes, though it is rarely worth running two orchestration layers. The most common combination is narrower: use Mastra as the agent and workflow layer, and call a LangChain.js retriever, document loader or text splitter from inside a Mastra tool or step when Mastra lacks a specific integration. Because a Mastra tool's execute function is plain TypeScript, any library works there.
The reverse also works: a LangGraph.js node can call any TypeScript code, including a Mastra agent. But running Mastra workflows and LangGraph.js graphs in the same service doubles your persistence models, your tracing setup and your upgrade surface. Pick one orchestration layer and treat the other framework, if at all, as a library of components.
For broader context on where both frameworks sit next to Vercel AI SDK, GenKit and LlamaIndex.TS, see our JavaScript and TypeScript GenAI frameworks comparison. For the same model-driven versus graph-driven trade-off in an AWS context, see Strands Agents vs LangGraph.
Migrations between the two are mostly mechanical at the agent layer and conceptual at the orchestration layer.
Port one workflow end to end, including its human-in-the-loop path and a restart test, before committing to a full migration.
Mastra is an integrated, TypeScript-native framework that bundles agents, typed step workflows, memory, evals, a local Studio and an HTTP server behind one Mastra instance. LangChain.js is a modular toolkit: createAgent provides the agent loop with middleware, and LangGraph.js provides the stateful graph runtime with checkpointers and interrupts. Mastra optimizes for a fast, opinionated path to a running service; LangChain.js optimizes for composability, explicit control flow and integration breadth.
Neither is better in general; they suit different workflow shapes. Mastra's workflows chain typed steps with branching and parallelism, which is easier to read and type-check for mostly linear processes. LangGraph.js models workflows as state machines with conditional edges and cycles, which suits agent loops that revisit earlier stages and supervisor-style multi-agent systems. Both support durable human-in-the-loop pauses, so choose based on whether your workflow needs backward arrows.
Mastra reached 1.x and is used for production agent services, with storage-backed workflow snapshots, built-in tracing and a deployable server. Its main production risk is release velocity: @mastra/core shipped many minor versions during 2026. Pin exact versions, run your own integration tests on upgrade, and verify suspend and resume behavior across a restart before relying on it for consequential actions.
No. Mastra does not depend on LangChain or LangGraph. It has its own agent loop, workflow engine and memory system, and its model layer builds on Vercel AI SDK provider interfaces, exposed through Mastra's provider/model router strings. You can still call LangChain.js components such as retrievers or document loaders from inside a Mastra tool, because tool execute functions are ordinary TypeScript.
Mastra includes tracing, metrics and evals in the framework and surfaces them in its local Studio, so you get visibility without an external account. LangChain.js integrates most deeply with LangSmith, a hosted platform with strong tracing, datasets and evaluation tooling. If you want observability self-contained in your stack, Mastra is simpler; if you already use LangSmith, LangChain.js gives you richer hosted tooling with almost no setup.
Yes, at the agent and tool layer the switch is mostly mechanical, because both use Zod schemas and similar agent options. Orchestration is harder: LangGraph.js graphs with cycles and shared state need to be redesigned as Mastra steps, not translated line by line, and persisted checkpoints or snapshots cannot be converted. Keeping business logic in plain functions that tools call keeps the switching cost low.
Aaron is an engineering leader, software architect, and founder with 18 years building distributed systems and cloud infrastructure. Now focused on LLM-powered platforms, agent orchestration, and production AI. He shares hands-on technical guides and framework comparisons at fp8.co.
Compare top JS/TS GenAI frameworks for 2026. Vercel AI SDK, LangChain.js, Mastra, GenKit, and LlamaIndex.TS benchmarked.
AI EngineeringCompare Strands Agents vs LangGraph for AI agents: model-driven simplicity vs graph-based control, with code examples and trade-offs.
AI EngineeringCompare Anthropic SDK, OpenAI SDK, Vercel AI SDK, and AWS Bedrock SDK for TypeScript apps. Which LLM SDK wins on type safety, streaming, and production features?
AI Engineering