Welcome to this hands-on workshop! This project demonstrates how to build production-ready AI agents and workflows using Mastra to create a fun meme generation pipeline that turns workplace frustrations into shareable memes.
Watch the demo of this application runnning end to end:
π₯ Click above to watch the full workshop video!
While we've chosen a humorous implementation example, the patterns, architecture, and Mastra framework you'll learn here are ideal for creating enterprise-grade agentic applications. The same workflow concepts apply whether you're building customer support automation, data processing pipelines, or complex business logic orchestration.
- Mastra Agents: Build conversational AI agents that can understand user input
- Mastra Workflows: Create modular workflow steps that can be chained together
- Structured Generation: Use Vercel AI SDK with Zod schemas for reliable data extraction
- External API Integration: Connect to meme services (Imgflip) for meme generation
- Agentic Workflows: Chain multiple steps together to create complex workflows
Our workshop demonstrates a complete agentic workflow:
graph LR
A[User Input<br/>Work Frustrations] --> B[Extract Frustrations Step<br/>Structured Generation]
B --> C[Find Base Meme Step<br/>Imgflip API Search]
C --> D[Generate Captions Step<br/>AI Caption Creation]
D --> E[Generate Meme Step<br/>Imgflip Caption API]
E --> F[Shareable URL<br/>Ready to Share!]
- Frustration Extraction Step: Uses structured generation to parse user input into categorized frustrations
- Meme Search Step: Searches Imgflip's free API for appropriate base meme templates
- Caption Generation Step: Creates witty, contextual captions based on frustrations and meme template
- Meme Generation Step: Uses Imgflip's caption API to create memes with the base template and captions, returning a stable shareable URL
Here are some actual memes generated by our workshop application, showcasing how work frustrations get transformed into shareable humor:
When they move all the engineers to an open floor plan with noisy co-workers...
Being told you're excellent at your job but somehow still underpaid...
When you refer an engineer who constantly asks for your help but gets paid more than you...
That awkward moment when your mentee's starting salary is higher than your current one...
These examples demonstrate how our AI workflow transforms common workplace frustrations into contextually appropriate and genuinely funny memes that teams can actually share!
- Node.js 20.9.0+
- OpenAI API key (for caption generation)
- Optional: Imgflip account credentials (for better rate limits and reliability)
- Basic knowledge of Next.js and TypeScript
git clone <your-repo-url>
cd mastra-workshop-test
npm install
Create a .env
file with your API keys:
# OpenAI Configuration (required for caption generation)
OPENAI_API_KEY=your_openai_api_key_here
# Optional: Imgflip credentials for meme generation (recommended for better reliability)
IMGFLIP_USERNAME=your_imgflip_username
IMGFLIP_PASSWORD=your_imgflip_password
Note: The app will work without Imgflip credentials using a default account, but may be rate limited.
npm run dev
Visit http://localhost:4111 to start generating memes!
Our main agent understands user frustrations and orchestrates the meme generation process:
// Simplified agent structure
const memeGeneratorAgent = new Agent({
name: 'MemeGenerator',
instructions: 'Help users turn their work frustrations into funny memes',
workflows: {
'meme-generation': memeGenerationWorkflow,
},
});
Each step in our workflow is designed to be:
- Modular: Can be used independently or as part of the workflow
- Typed: Uses Zod schemas for input/output validation
- Testable: Can be tested in isolation using Mastra's built-in tools
- Reusable: Can be composed into different workflows
const extractFrustrationsStep = createStep({
id: 'extract-frustrations',
description: 'Extract and categorize user frustrations from raw input',
inputSchema: z.object({
userInput: z.string().describe('Raw user input about work frustrations'),
}),
execute: async ({ inputData }) => {
// Uses Vercel AI SDK with structured generation
const result = await generateObject({
model: openai('gpt-4'),
schema: frustrationsSchema,
prompt: `Extract frustrations from: ${inputData.userInput}`,
});
return result.object;
},
});
const findBaseMemeStep = createStep({
id: 'find-base-meme',
description: "Get a diverse selection of meme templates from Imgflip's free API",
inputSchema: frustrationsSchema.extend({
analysis: z.object({
message: z.string(),
}),
}),
execute: async ({ inputData }) => {
// Search Imgflip's free API for relevant meme templates
const response = await fetch('https://api.imgflip.com/get_memes');
const data = await response.json();
const selectedMemes = data.data.memes.slice(0, 10);
return { templates: selectedMemes };
},
});
const generateCaptionsStep = createStep({
id: 'generate-captions',
description: 'Generate meme captions based on frustrations and template',
inputSchema: z.object({
frustrations: frustrationsSchema,
baseTemplate: memeTemplateSchema,
}),
execute: async ({ inputData }) => {
// Generate contextual, funny captions using AI
const captions = await generateObject({
model: openai('gpt-4'),
schema: captionsSchema,
prompt: `Create funny captions for ${inputData.baseTemplate.name} based on: ${inputData.frustrations}`,
});
return captions.object;
},
});
const generateMemeStep = createStep({
id: 'generate-meme',
description: "Create a meme using Imgflip's caption API with the selected template and captions",
inputSchema: z.object({
baseTemplate: memeTemplateSchema,
captions: captionsSchema,
}),
execute: async ({ inputData }) => {
// Use Imgflip's caption_image API to create meme with specific template and text
const formData = new URLSearchParams();
formData.append('template_id', inputData.baseTemplate.id);
formData.append('username', process.env.IMGFLIP_USERNAME || 'imgflip_hubot');
formData.append('password', process.env.IMGFLIP_PASSWORD || 'imgflip_hubot');
formData.append('text0', inputData.captions.topText);
formData.append('text1', inputData.captions.bottomText);
const response = await fetch('https://api.imgflip.com/caption_image', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: formData,
});
const result = await response.json();
// Imgflip provides a stable, shareable URL that can be used directly
return { imageUrl: result.data.url, pageUrl: result.data.page_url };
},
});
Mastra provides excellent built-in capabilities for testing your workflows:
# Start the development server to test interactively
npm run dev
# Visit the Mastra playground at http://localhost:4111
# Use the chat interface to test the complete workflow
- Simple Frustration: "My meetings always run over time"
- Complex Frustration: "The deployment process is broken, code reviews take forever, and our standup meetings are pointless"
- Emotional Frustration: "I'm so tired of explaining the same thing over and over to different stakeholders"
- Corporate Humor: Professional-looking memes safe for work
- Developer Memes: Programming and tech-specific templates
- Remote Work: Memes about working from home challenges
- Meeting Memes: Specifically about meeting frustrations
- Slack Bot: Deploy as a Slack app for team use
- Teams Integration: Microsoft Teams bot for enterprise
- Discord Bot: For gaming/tech communities
- Web Widget: Embeddable meme generator for websites
- Agent Orchestration: How agents coordinate multiple workflow steps
- Structured Generation: Reliable data extraction from LLMs
- Workflow Composition: Building complex workflows from simple steps
- Error Handling: Graceful failure and recovery in agentic systems
- Testing Strategies: How to test AI-powered workflows
By the end of this workshop, you'll have:
- β Built a complete agentic workflow with multiple specialized steps
- β Integrated external APIs (Imgflip, OpenAI)
- β Used structured generation for reliable data extraction
- β Created a fun, shareable application that solves real problems
- β Learned Mastra's agent and workflow patterns
- β Gained experience with AI-powered workflows and step composition
Found an issue or want to improve the workshop? Please open an issue or submit a pull request!
MIT License - feel free to use this code for your own projects and workshops.
Happy meme generating! π Turn those work frustrations into laughs and learn about agentic AI workflows in the process!