mastra-ai

mastra

11
0
# Install this skill:
npx skills add mastra-ai/skills --skill "mastra"

Install specific skill from multi-skill repository

# Description

Comprehensive guide for building AI applications with Mastra, the TypeScript AI framework for agents and workflows. Covers LLM agents with tools and memory, multi-step workflows with branching/parallel execution, storage backends (Postgres/LibSQL), RAG/vector search, and custom tool creation. Use when building conversational agents, automated workflows, RAG systems, or any Mastra TypeScript/JavaScript application. Includes 27+ production-ready code patterns, API verification guidance, troubleshooting, and best practices.

# SKILL.md


name: mastra
description: Comprehensive guide for building AI applications with Mastra, the TypeScript AI framework for agents and workflows. Covers LLM agents with tools and memory, multi-step workflows with branching/parallel execution, storage backends (Postgres/LibSQL), RAG/vector search, and custom tool creation. Use when building conversational agents, automated workflows, RAG systems, or any Mastra TypeScript/JavaScript application. Includes 27+ production-ready code patterns, API verification guidance, troubleshooting, and best practices.
license: Apache-2.0
metadata:
author: Mastra
version: "1.0.0"
repository: https://github.com/mastra-ai/skills


Mastra Development Guide

Comprehensive guide for building AI applications with Mastra.


Prerequisites

pnpm add @mastra/core zod

Install additional packages only when needed:
- Storage: @mastra/pg, @mastra/libsql, @mastra/mongodb
- RAG: @mastra/rag
- Memory: @mastra/memory


Critical Knowledge

⚠️ Always verify against current code:
1. Use mastra-embedded-docs-look-up skill for current API signatures
2. Check node_modules/@mastra/*/dist/docs/ for package-specific documentation
3. Search source code: node_modules/@mastra/*/src/
4. Fallback to docs: mastra.ai/docs

⚠️ ES2022 Required - CommonJS will fail. Must use "target": "ES2022".


Working Guidelines

  1. Minimal configuration: Only specify options that differ from defaults
  2. Check embedded docs first: Use mastra-embedded-docs-look-up skill
  3. Verify TypeScript config: Must be ES2022, not CommonJS
  4. Test in Studio: Run npm run dev → http://localhost:4111
  5. Model format: Always use provider/model (e.g., openai/gpt-4o)
  6. Environment variables: Load with dotenv/config or native .env support

Agent vs Workflow

Use When
Agent Open-ended tasks (support, research) - reasons, decides tools, retains memory
Workflow Defined sequences (pipelines, approvals) - orchestrates specific steps in order

TypeScript Config (Required)

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ES2022",
    "moduleResolution": "bundler"
  }
}

Critical: CommonJS causes errors. Must use ES2022.


Project Structure

src/mastra/
├── tools/       # Custom tools
├── agents/      # Agent configs
├── workflows/   # Workflows
└── index.ts     # Mastra instance

Environment Variables

OPENAI_API_KEY=...
ANTHROPIC_API_KEY=...
GOOGLE_GENERATIVE_AI_API_KEY=...

Verifying Current APIs

Before writing code, verify the current API:

# Check what's exported from @mastra/core
ls node_modules/@mastra/core/dist/docs/

# View SOURCE_MAP.json for complete API surface
cat node_modules/@mastra/core/dist/docs/SOURCE_MAP.json

# Search for specific exports
grep -r "export.*Agent" node_modules/@mastra/core/src/

Or use the skill: mastra-embedded-docs-look-up


Quick Reference

Basic Agent

new Agent({
  id: 'my-agent',
  name: 'My Agent',
  instructions: 'You are helpful',
  model: 'openai/gpt-4o',
  tools: { myTool }  // optional
})

Basic Workflow

createWorkflow({
  id: 'my-workflow',
  inputSchema: z.object({ input: z.string() }),
  outputSchema: z.object({ output: z.string() })
})
  .then(step1)
  .commit()

Structured Output

const response = await agent.generate('Extract: John, 30', {
  structuredOutput: {
    schema: z.object({
      name: z.string(),
      age: z.number()
    })
  }
})
console.log(response.object) // Access via .object property

Streaming

const stream = await agent.stream('Tell a story')
for await (const chunk of stream.fullStream) {
  console.log(chunk)
}

Workflow Patterns

Sequential Steps

const workflow = createWorkflow({
  id: 'sequential',
  inputSchema: z.object({ data: z.string() }),
  outputSchema: z.object({ result: z.string() })
})
  .then(step1)
  .then(step2)
  .then(step3)
  .commit();

Branching (Conditional)

const workflow = createWorkflow({
  id: 'branching',
  inputSchema: z.object({ value: z.number() }),
  outputSchema: z.object({ result: z.string() })
})
  .branch([
    // [condition, workflow/step to execute]
    [async ({ inputData }) => inputData.value > 10, pathA],
    [async ({ inputData }) => inputData.value <= 10, pathB],
  ])
  .commit();

Parallel Execution

const workflow = createWorkflow({
  id: 'parallel',
  inputSchema: z.object({ items: z.array(z.string()) }),
  outputSchema: z.object({ results: z.array(z.any()) })
})
  .parallel([step1, step2, step3]) // All execute concurrently
  .commit();

Foreach Loop

const workflow = createWorkflow({
  id: 'foreach',
  inputSchema: z.object({ items: z.array(z.string()) }),
  outputSchema: z.object({ results: z.array(z.string()) })
})
  .foreach(processItemStep) // Iterates over input array
  .commit();

Suspend/Resume (Human-in-the-loop)

const approvalTool = createTool({
  id: 'approval',
  inputSchema: z.object({ request: z.string() }),
  outputSchema: z.object({ approved: z.boolean() }),
  suspendSchema: z.object({ requestId: z.string() }),
  resumeSchema: z.object({ approved: z.boolean() }),
  execute: async (input, context) => {
    if (!context.resumeData) {
      // First call - suspend execution
      context.suspend({ requestId: 'req-123' });
      return;
    }
    // Resumed - use resumeData
    return { approved: context.resumeData.approved };
  }
});

// Resume later
await run.resume({ resumeData: { approved: true } });

Workflow State Management

const workflow = createWorkflow({
  id: 'stateful',
  inputSchema: z.object({ data: z.string() }),
  outputSchema: z.object({ result: z.string() }),
  stateSchema: z.object({ counter: z.number() })
})
  .then(createStep({
    id: 'increment',
    execute: async ({ state, setState }) => {
      await setState({ counter: (state.counter || 0) + 1 });
      return { result: 'incremented' };
    }
  }))
  .commit();

// Execute with initial state
const run = await workflow.createRun();
const result = await run.start({
  inputData: { data: 'test' },
  initialState: { counter: 0 }
});

Agent Patterns

Agent with Tools

// 1. Create tools
const weatherTool = createTool({
  id: 'get-weather',
  description: 'Get weather for a location',
  inputSchema: z.object({ location: z.string() }),
  outputSchema: z.object({ temp: z.number(), condition: z.string() }),
  execute: async ({ location }) => {
    // TODO: Fetch weather
    return { temp: 72, condition: 'sunny' };
  }
});

// 2. Create agent with tools
const agent = new Agent({
  id: 'weather-agent',
  name: 'Weather Assistant',
  instructions: 'You help users with weather information',
  model: 'openai/gpt-4o',
  tools: { weatherTool } // Assign tools
});

Agent with Memory

// 1. Configure storage
const storage = new PostgresStore({
  connectionString: process.env.DATABASE_URL
});
await storage.init();

// 2. Create memory
const memory = new Memory({
  id: 'chat-memory',
  storage,
  options: {
    lastMessages: 10 // Retrieve last 10 messages
  }
});

// 3. Create agent with memory
const agent = new Agent({
  id: 'chat-agent',
  instructions: 'You are a helpful assistant',
  model: 'openai/gpt-4o',
  memory
});

// 4. Use with consistent threadId
await agent.generate('Hello', {
  threadId: 'user-123-conversation',
  resourceId: 'user-123'
});

Agent with Memory + Tools

const agent = new Agent({
  id: 'full-agent',
  instructions: 'You are a helpful assistant with tools',
  model: 'openai/gpt-4o',
  tools: { weatherTool, searchTool },
  memory // Memory from previous example
});

await agent.generate('What\'s the weather in SF?', {
  threadId: 'user-123',
  resourceId: 'user-123'
});

Agent with Semantic Recall

// Requires vector store and embedder
const memory = new Memory({
  id: 'semantic-memory',
  storage: postgresStore,
  vector: chromaVectorStore, // Vector store for semantic search
  embedder: openaiEmbedder,  // Embedding model
  options: {
    lastMessages: 5,
    semanticRecall: true // Enable semantic search
  }
});

const agent = new Agent({
  id: 'semantic-agent',
  memory
});

Agent with Structured Output

const response = await agent.generate(
  'Extract user info: John Smith, age 30, lives in SF',
  {
    structuredOutput: {
      schema: z.object({
        name: z.string(),
        age: z.number(),
        location: z.string()
      })
    }
  }
);

console.log(response.object); // { name: 'John Smith', age: 30, location: 'SF' }

Memory Patterns

Basic Message History

const memory = new Memory({
  id: 'basic-memory',
  storage: postgresStore,
  options: {
    lastMessages: 10 // Retrieve last 10 messages
  }
});

Working Memory (Persistent State)

const memory = new Memory({
  id: 'working-memory',
  storage: postgresStore,
  options: {
    lastMessages: 10,
    workingMemory: {
      enabled: true,
      scope: 'resource', // 'resource' or 'thread'
      template: `User preferences: {preferences}`
    }
  }
});
const memory = new Memory({
  id: 'semantic-memory',
  storage: postgresStore,
  vector: chromaVectorStore, // REQUIRED
  embedder: openaiEmbedder,  // REQUIRED
  options: {
    lastMessages: 5,
    semanticRecall: true // REQUIRED
  }
});

Tool Patterns

Basic Tool

const calculatorTool = createTool({
  id: 'calculator',
  description: 'Perform basic math operations',
  inputSchema: z.object({
    operation: z.enum(['add', 'subtract', 'multiply', 'divide']),
    a: z.number(),
    b: z.number()
  }),
  outputSchema: z.object({ result: z.number() }),
  execute: async ({ operation, a, b }) => {
    switch (operation) {
      case 'add': return { result: a + b };
      case 'subtract': return { result: a - b };
      case 'multiply': return { result: a * b };
      case 'divide': return { result: a / b };
    }
  }
});

Tool with Context Access

const toolWithContext = createTool({
  id: 'context-aware',
  inputSchema: z.object({ query: z.string() }),
  outputSchema: z.object({ result: z.string() }),
  execute: async (input, context) => {
    // Access mastra instance
    const agent = context.mastra.getAgent('other-agent');

    // Access memory
    const messages = await context.memory?.listMessages();

    // Access request context
    const userId = context.requestContext?.get('userId');

    return { result: 'done' };
  }
});

Suspending Tool (Human-in-the-loop)

const approvalTool = createTool({
  id: 'approval',
  inputSchema: z.object({ action: z.string() }),
  outputSchema: z.object({ approved: z.boolean() }),
  suspendSchema: z.object({ actionId: z.string() }),
  resumeSchema: z.object({ approved: z.boolean() }),
  execute: async (input, context) => {
    if (!context.agent?.resumeData) {
      // Suspend and wait for approval
      const actionId = generateId();
      context.agent.suspend({ actionId });
      return;
    }

    // Resumed with approval decision
    return { approved: context.agent.resumeData.approved };
  }
});

Storage Patterns

Postgres Storage

import { PostgresStore } from '@mastra/pg';

const storage = new PostgresStore({
  connectionString: process.env.DATABASE_URL
});
await storage.init(); // Creates tables

const mastra = new Mastra({
  storage
});

LibSQL Storage (SQLite-compatible)

import { LibSQLStore } from '@mastra/libsql';

const storage = new LibSQLStore({
  id: 'my-db',
  url: 'file:./local.db' // or libsql://...
});
await storage.init();

Agent-Specific Storage

const mastra = new Mastra({
  storage: postgresStore, // Default storage
  agents: {
    chatAgent: new Agent({
      id: 'chat-agent',
      memory: new Memory({
        id: 'chat-memory',
        storage: libsqlStore // Different storage for this agent
      })
    })
  }
});

RAG Patterns

import { createVectorQueryTool } from '@mastra/rag';

// 1. Create vector query tool
const searchTool = createVectorQueryTool({
  vectorStoreName: 'my-vector-store',
  indexName: 'documents',
  vector: chromaVectorStore,
  embedder: openaiEmbedder,
  topK: 5
});

// 2. Use with agent
const agent = new Agent({
  id: 'rag-agent',
  instructions: 'You help users find information in our docs',
  tools: { searchTool }
});

// Agent can now query documents via the tool
await agent.generate('What is in the documentation about authentication?');

Graph RAG (Advanced)

import { GraphRAG } from '@mastra/rag';

// Create graph RAG with embedding dimension and similarity threshold
const graphRag = new GraphRAG(1536, 0.7); // OpenAI embedding dimension

// Add nodes with embeddings
graphRag.addNode({
  id: 'doc1',
  content: 'Document content about authentication',
  embedding: await embedder.embed('Document content...')
});

// Add relationships between documents
graphRag.addEdge({ source: 'doc1', target: 'doc2', weight: 0.8 });

// Query the graph
const nodes = graphRag.getNodes();
const edges = graphRag.getEdges();

Key Conventions

  1. Use mastra.getAgent('name') / mastra.getWorkflow('name') not direct imports
  2. Always use env vars for API keys
  3. ES2022 modules required (not CommonJS)
  4. Test with Studio: npm run dev → http://localhost:4111

Common Errors

"Cannot find module" or "ES Module" errors

  • Cause: CommonJS config
  • Fix: Set "target": "ES2022", "module": "ES2022" in tsconfig.json

"Property X does not exist on type Y"

  • Cause: Outdated API usage or incorrect type
  • Fix: Use mastra-embedded-docs-look-up skill to check current API

Agent not using assigned tools

  • Cause: Tools not registered in Mastra instance or agent config
  • Fix: Add tools to new Mastra({ tools: { ... } }) and reference in agent

Memory not persisting across conversations

  • Cause: Missing storage configuration or threadId
  • Fix: Configure storage backend and pass consistent threadId to agent.generate()

See references/common-errors.md for comprehensive troubleshooting.



Documentation Resources

For API signatures and detailed types:
- Use mastra-embedded-docs-look-up skill
- Check node_modules/@mastra/core/dist/docs/

For project initialization:
- Use create-mastra skill

For detailed patterns:
- See reference files in references/patterns/ directory


Resources

# Supported AI Coding Agents

This skill is compatible with the SKILL.md standard and works with all major AI coding agents:

Learn more about the SKILL.md standard and how to use these skills with your preferred AI coding agent.