Integrate Mastra in Your NestJS Project
In this guide, you'll build a tool-calling AI agent using Mastra and NestJS. The NestJS server adapter registers Mastra's agent and workflow routes as a NestJS module, so they run inside your existing NestJS application.
Before you beginDirect link to Before you begin
- You'll need an API key from a supported model provider. If you don't have a preference, use OpenAI.
- Install Node.js
v22.13.0or later - Use the NestJS Express platform (
@nestjs/platform-express)
Create a new NestJS app (optional)Direct link to Create a new NestJS app (optional)
If you already have a NestJS app, skip to the next step.
Run the following command to create a new NestJS app:
- npm
- pnpm
- Yarn
- Bun
npx @nestjs/cli new mastra-nest
pnpm dlx @nestjs/cli new mastra-nest
yarn dlx @nestjs/cli new mastra-nest
bun x @nestjs/cli new mastra-nest
This creates a project called mastra-nest, but you can replace it with any name you want.
Initialize MastraDirect link to Initialize Mastra
Navigate to your NestJS project directory:
cd mastra-nest
Run mastra init. When prompted, choose a provider (e.g. OpenAI) and enter your key:
- npm
- pnpm
- Yarn
- Bun
npx mastra@latest init
pnpm dlx mastra@latest init
yarn dlx mastra@latest init
bun x mastra@latest init
This creates a src/mastra folder with an example weather agent and the following files:
index.ts- Mastra config, including memorytools/weather-tool.ts- a tool to fetch weather for a given locationagents/weather-agent.ts- a weather agent with a prompt that uses the tool
You'll pass the src/mastra/index.ts file to the NestJS adapter in the next step.
Add server adapterDirect link to Add server adapter
Install the NestJS server adapter package:
- npm
- pnpm
- Yarn
- Bun
npm install @mastra/nestjs@latest
pnpm add @mastra/nestjs@latest
yarn add @mastra/nestjs@latest
bun add @mastra/nestjs@latest
Open src/app.module.ts and register MastraModule:
import { Module } from '@nestjs/common'
import { MastraModule } from '@mastra/nestjs'
import { mastra } from './mastra'
@Module({
imports: [
MastraModule.register({
mastra,
}),
],
})
export class AppModule {}
MastraModule registers a catch-all controller (@All('*')). If it is imported before your app modules, it can intercept unrelated routes and return 404s. To avoid conflicts, import MastraModule last or mount it under a dedicated prefix (e.g., /api/v1/mastra).
Test your agentDirect link to Test your agent
By default, Mastra's endpoints are added under the /api subpath and use your agent/workflow IDs. The default weather-agent created by mastra init is available at /api/agents/weather-agent.
Start your NestJS server:
- npm
- pnpm
- Yarn
- Bun
npm run start
pnpm run start
yarn run start
bun run start
In a separate terminal window, use curl to ask the weather agent:
curl -X POST http://localhost:3000/api/agents/weather-agent/generate -H "Content-Type: application/json" -d "{\"messages\":[{\"role\":\"user\",\"content\":\"What is the weather like in Seoul?\"}]}"
Use Mastra in Your Own ServicesDirect link to Use Mastra in Your Own Services
The module exports two ways to access Mastra from your NestJS services: the MastraService wrapper and the MASTRA injection token.
MastraServiceDirect link to MastraService
MastraService is an injectable wrapper with convenience methods for common operations:
import { Injectable } from '@nestjs/common'
import { MastraService } from '@mastra/nestjs'
@Injectable()
export class AgentService {
constructor(private readonly mastraService: MastraService) {}
async chat(agentId: string, message: string) {
const agent = this.mastraService.getAgent(agentId)
return agent.generate({
messages: [{ role: 'user', content: message }],
})
}
async runWorkflow(workflowId: string, input: Record<string, unknown>) {
const workflow = this.mastraService.getWorkflow(workflowId)
return workflow.start({ inputData: input })
}
}
MastraService exposes:
getMastra()— returns the underlyingMastrainstancegetAgent(id)— shorthand formastra.getAgent(id)getWorkflow(id)— shorthand formastra.getWorkflow(id)getOptions()— returns the module configurationisShuttingDown—trueafter graceful shutdown begins
MASTRA tokenDirect link to MASTRA token
If you need the Mastra instance directly (e.g., to access storage, memory, or other core APIs), inject it with the MASTRA token:
import { Injectable, Inject } from '@nestjs/common'
import { MASTRA } from '@mastra/nestjs'
import type { Mastra } from '@mastra/core/mastra'
@Injectable()
export class MemoryService {
constructor(@Inject(MASTRA) private readonly mastra: Mastra) {}
async getThreadMessages(threadId: string) {
const memory = this.mastra.getMemory()
return memory?.getMessages({ threadId })
}
}
Both approaches use the same singleton Mastra instance registered by MastraModule.
Next stepsDirect link to Next steps
You now have a working Mastra agent running inside NestJS. To extend the project:
For details on the NestJS integration: