Skip to content

Firecrawl + Mastra

Updated Feb 2026

Integrate Firecrawl with Mastra, the TypeScript framework for building AI agents and workflows. Create multi-step pipelines that search, scrape, and summarize web content.

Source: docs.firecrawl.dev/developer-guides/llm-sdks-and-frameworks/mastra

Installation

bash
npm install @mastra/core @mendable/firecrawl-js zod

Create a .env file:

env
FIRECRAWL_API_KEY=your_firecrawl_key
OPENAI_API_KEY=your_openai_key

Node < 20

If using Node < 20, install dotenv and add import 'dotenv/config' to your code.

Multi-Step Workflow

A complete workflow that searches the web, scrapes the top result, and summarizes the content using Mastra's step-based pipeline.

js
import { createWorkflow, createStep } from "@mastra/core/workflows";
import { z } from "zod";
import Firecrawl from "@mendable/firecrawl-js";
import { Agent } from "@mastra/core/agent";

const firecrawl = new Firecrawl({
    apiKey: process.env.FIRECRAWL_API_KEY
});

const agent = new Agent({
    name: "summarizer",
    instructions: "You create concise summaries of documentation.",
    model: "openai/gpt-4o",
});

// Step 1: Search with Firecrawl
const searchStep = createStep({
    id: "search",
    inputSchema: z.object({
        query: z.string(),
    }),
    outputSchema: z.object({
        url: z.string(),
        title: z.string(),
    }),
    execute: async ({ inputData }) => {
        console.log(`Searching: ${inputData.query}`);
        const searchResults = await firecrawl.search(inputData.query, { limit: 1 });
        const webResults = searchResults?.web;

        if (!webResults || !Array.isArray(webResults) || webResults.length === 0) {
            throw new Error("No search results found");
        }

        const firstResult = webResults[0];
        console.log(`Found: ${firstResult.title}`);
        return {
            url: firstResult.url,
            title: firstResult.title,
        };
    },
});

// Step 2: Scrape the URL
const scrapeStep = createStep({
    id: "scrape",
    inputSchema: z.object({
        url: z.string(),
        title: z.string(),
    }),
    outputSchema: z.object({
        markdown: z.string(),
        title: z.string(),
    }),
    execute: async ({ inputData }) => {
        console.log(`Scraping: ${inputData.url}`);
        const scrapeResult = await firecrawl.scrape(inputData.url, {
            formats: ["markdown"],
        });

        console.log(`Scraped: ${scrapeResult.markdown?.length || 0} characters`);
        return {
            markdown: scrapeResult.markdown || "",
            title: inputData.title,
        };
    },
});

// Step 3: Summarize with AI
const summarizeStep = createStep({
    id: "summarize",
    inputSchema: z.object({
        markdown: z.string(),
        title: z.string(),
    }),
    outputSchema: z.object({
        summary: z.string(),
    }),
    execute: async ({ inputData }) => {
        console.log(`Summarizing: ${inputData.title}`);
        const prompt = `Summarize in 2-3 sentences:\n\nTitle: ${inputData.title}\n\n${inputData.markdown}`;
        const result = await agent.generate(prompt);

        return { summary: result.text };
    },
});

// Create and run the workflow
export const workflow = createWorkflow({
    id: "firecrawl-workflow",
    inputSchema: z.object({ query: z.string() }),
    outputSchema: z.object({ summary: z.string() }),
    steps: [searchStep, scrapeStep, summarizeStep],
})
    .then(searchStep)
    .then(scrapeStep)
    .then(summarizeStep)
    .commit();

async function main() {
    const run = await workflow.createRunAsync();
    const result = await run.start({
        inputData: { query: "Firecrawl documentation" }
    });

    if (result.status === "success") {
        const { summarize } = result.steps;
        if (summarize.status === "success") {
            console.log(`\n${summarize.output.summary}`);
        }
    } else {
        console.error("Workflow failed:", result.status);
    }
}

main().catch(console.error);

How It Works

  1. Search -- Firecrawl searches the web for your query and returns the top result URL
  2. Scrape -- Firecrawl scrapes the URL and returns clean markdown content
  3. Summarize -- A Mastra Agent powered by GPT summarizes the content

Each step has typed input/output schemas using Zod, providing end-to-end type safety.

Further Reading