When this skill is activated, always start your first response with the 🧢 emoji.
Mastra
Mastra is a TypeScript framework for building AI-powered applications. It provides a unified Mastra() constructor that wires together agents, workflows, tools, memory, RAG, MCP, voice, evals, and observability. Projects scaffold via npm create mastra@latest and run with mastra dev (dev server + Studio UI at localhost:4111). Built on Hono, deployable to Node.js 22+, Bun, Deno, Cloudflare, Vercel, Netlify, AWS, and Azure.
When to use this skill
Trigger this skill when the user:
- Creates or configures a Mastra agent with tools, memory, or structured output
- Defines workflows with steps, branching, loops, or parallel execution
- Creates custom tools with
createTooland Zod schemas - Sets up memory (message history, working memory, semantic recall)
- Builds RAG pipelines (chunking, embeddings, vector stores)
- Configures MCP clients to connect to external tool servers
- Exposes Mastra agents/tools as an MCP server
- Runs Mastra CLI commands (
mastra dev,mastra build,mastra init) - Deploys a Mastra application to any cloud provider
Do NOT trigger this skill for:
- General TypeScript/Node.js questions unrelated to Mastra
- Other AI frameworks (LangChain, CrewAI, AutoGen) unless comparing to Mastra
Setup & authentication
Environment variables
# Required - at least one LLM provider
OPENAI_API_KEY=sk-...
# Or: ANTHROPIC_API_KEY, GOOGLE_GENERATIVE_AI_API_KEY, OPENROUTER_API_KEY
# Optional
POSTGRES_CONNECTION_STRING=postgresql://... # for pgvector RAG/memory
PINECONE_API_KEY=... # for Pinecone vector store
Installation
# New project
npm create mastra@latest
# Existing project
npx mastra init --components agents,tools,workflows --llm openai
Basic initialization
import { Mastra } from '@mastra/core'
import { Agent } from '@mastra/core/agent'
import { createTool } from '@mastra/core/tool'
import { z } from 'zod'
const myAgent = new Agent({
id: 'my-agent',
instructions: 'You are a helpful assistant.',
model: 'openai/gpt-4.1',
tools: {},
})
export const mastra = new Mastra({
agents: { myAgent },
})
Always access agents via mastra.getAgent('myAgent') - not direct imports.
Direct imports bypass logger, telemetry, and registered resources.
Core concepts
Mastra instance - the central registry. Pass agents, workflows, tools, memory, MCP servers, and config to the new Mastra({}) constructor. Everything registered here gets wired together (logging, telemetry, resource access).
Agents - LLM-powered entities created with new Agent({}). They take instructions, a model string (e.g. 'openai/gpt-4.1'), and optional tools. Call agent.generate() for complete responses or agent.stream() for streaming. Both accept maxSteps (default 5) to cap tool-use loops.
Workflows - typed multi-step pipelines built with createWorkflow() and createStep(). Steps have Zod inputSchema/outputSchema. Chain with .then(), branch with .branch(), loop with .dountil()/.dowhile(), parallelize with .parallel(), iterate with .foreach(). Always call .commit() at the end.
Tools - typed functions via createTool({ id, description, inputSchema, outputSchema, execute }). The description field guides the LLM's tool selection.
Memory - four types: message history (recent messages), working memory (persistent user profile), observational memory (background summarization), and semantic recall (RAG over past conversations). Configure via new Memory({}).
MCP - MCPClient connects to external tool servers; MCPServer exposes Mastra tools/agents as an MCP endpoint. Use listTools() for static single-user setups, listToolsets() for dynamic multi-user scenarios.
Common tasks
Create an agent with tools
import { Agent } from '@mastra/core/agent'
import { createTool } from '@mastra/core/tool'
import { z } from 'zod'
const weatherTool = createTool({
id: 'get-weather',
description: 'Fetches current weather for a city',
inputSchema: z.object({ city: z.string() }),
outputSchema: z.object({ temp: z.number(), condition: z.string() }),
execute: async ({ city }) => {
const res = await fetch(`https://wttr.in/${city}?format=j1`)
const data = await res.json()
return { temp: Number(data.current_condition[0].temp_F), condition: data.current_condition[0].weatherDesc[0].value }
},
})
const agent = new Agent({
id: 'weather-agent',
instructions: 'Help users check weather. Use the get-weather tool.',
model: 'openai/gpt-4.1',
tools: { [weatherTool.id]: weatherTool },
})
Stream agent responses
const stream = await agent.stream('What is the weather in Tokyo?')
for await (const chunk of stream.textStream) {
process.stdout.write(chunk)
}
Define a workflow with steps
import { createWorkflow, createStep } from '@mastra/core/workflow'
import { z } from 'zod'
const summarize = createStep({
id: 'summarize',
inputSchema: z.object({ text: z.string() }),
outputSchema: z.object({ summary: z.string() }),
execute: async ({ inputData, mastra }) => {
const agent = mastra.getAgent('summarizer')
const res = await agent.generate(`Summarize: ${inputData.text}`)
return { summary: res.text }
},
})
const workflow = createWorkflow({
id: 'summarize-workflow',
inputSchema: z.object({ text: z.string() }),
outputSchema: z.object({ summary: z.string() }),
}).then(summarize).commit() // .commit() is required!
const run = workflow.createRun()
const result = await run.start({ inputData: { text: 'Long article...' } })
if (result.status === 'success') console.log(result.result)
Always checkresult.statusbefore accessingresult.resultorresult.error.
Possible statuses:success,failed,suspended,tripwire,paused.
Configure agent memory
import { Memory } from '@mastra/memory'
import { LibSQLStore, LibSQLVector } from '@mastra/libsql'
const memory = new Memory({
storage: new LibSQLStore({ id: 'mem', url: 'file:./local.db' }),
vector: new LibSQLVector({ id: 'vec', url: 'file:./local.db' }),
options: {
lastMessages: 20,
semanticRecall: { topK: 3, messageRange: 2 },
workingMemory: { enabled: true, template: '# User\n- Name:\n- Preferences:' },
},
})
const agent = new Agent({ id: 'mem-agent', model: 'openai/gpt-4.1', memory })
// Use with thread context
await agent.generate('Remember my name is Alice', {
memory: { thread: { id: 'thread-1' }, resource: 'user-123' },
})
Connect to MCP servers
import { MCPClient } from '@mastra/mcp'
const mcp = new MCPClient({
id: 'my-mcp',
servers: {
github: { command: 'npx', args: ['-y', '@modelcontextprotocol/server-github'] },
custom: { url: new URL('https://my-mcp-server.com/sse') },
},
})
const agent = new Agent({
id: 'mcp-agent',
model: 'openai/gpt-4.1',
tools: await mcp.listTools(), // static - fixed at init
})
// For multi-user (dynamic credentials per request):
const res = await agent.generate(prompt, {
toolsets: await mcp.listToolsets(),
})
await mcp.disconnect()
Run CLI commands
mastra dev # Dev server + Studio at localhost:4111
mastra build # Bundle to .mastra/output/
mastra build --studio # Include Studio UI in build
mastra start # Serve production build
mastra lint # Validate project structure
mastra migrate # Run DB migrations
Error handling
| Error | Cause | Resolution | |---|---|---| | Schema mismatch between steps | Step outputSchema doesn't match next step's inputSchema | Use .map() between steps to transform data | | Workflow not committed | Forgot .commit() after chaining steps | Add .commit() as the final call on the workflow chain | | maxSteps exceeded