Customer Story
How MagicSchool AI develops insights using Trigger.dev

Staff Software Engineer, MagicSchool AI

Ben Duggan, Staff Software Engineer at MagicSchool AI, shares how they use Trigger.dev and Vercel's AI SDK to extract insights from millions of student interactions.
MagicSchool: Transforming Education with AI
MagicSchool is the fastest-growing ed-tech company ever. Within just two years, our platform has grown to serve over 4.5 million teachers worldwide and is independently rated as the most secure AI platform.
We’ve built a one-stop shop for AI in education—a continually updated suite of AI tools that helps teachers save time, promote responsible AI literacy, and unlock new learning opportunities for students. Our mission is to lighten teachers’ workloads and help them focus on what matters most: their students.
Developing Insights from Student Interactions
Teachers need quick, clear insights into how students engage with AI tools.
Monitoring each interaction is too time-consuming for time-strapped educators, so we wanted to build real-time summaries that are sent directly to teachers.
These summaries highlight a student’s engagement level—from distracted to highly engaged—while also noting new interests and flagging concerning behaviors, if present. For example, a summary might inform teachers of new interests such as high engagement in a thread about climate change, or it might alert the teacher that a student is exclusively trying to get the AI to make fart jokes.
These high-level insights can save teachers hours of reviewing each message while also keeping them informed. This also gives educators piece of mind in deploying tools like MagicSchool, as they know they can have a safe environment for students to engage with AI and build AI Literacy.
To accomplish this, we fire off a trigger each time an AI response completes on a student thread and update the summary row to "pending" in our database.
const client = createServiceRoleSupabaseClient();await client .from("assistant_thread_summaries") .upsert( { thread_id: threadId, message_id: messageId, status: "pending" }, { onConflict: "thread_id" } );// Realtime broadcast to the teacher that we're summarizing this threadawait client.channel(channels.teacherRoomChannel(roomId)).send({ type: "broadcast", event: "threadSummarized", payload: { threadId, status: "pending" },});// Enqueue the taskawait summarizeStudentThreadTask.trigger({ threadId });
This trigger then queries all the relevant data and runs our analysis prompt. We use Zod schemas alongside Vercel’s AI SDK generateObject
function to get structured output from LLMs. It has unmarshalling, data validation, and retry logic all baked in, so we don't have to worry about these calls failing to generate valid objects anymore. Once the summary finishes generating, it’s saved to the database, and we broadcast another message to notify teachers about the new summary. Here’s a simplified version of the trigger code:
const summarizationSchema = z.object({ engagementLevel: z.enum(['distracted', 'minimal', 'moderate', 'high']), summary: z.string(),});export const summarizeStudentThreadTask = task<string, SummarizeStudentThreadTaskPayload>({ id: 'summarize-student-thread', run: async (payload, { ctx }) => { const client = createServiceRoleSupabaseClient(); const data = client.from; // ... fetch all the data // Generate the summary const { result: completion } = await wrappedGenerateObject( { functionName: 'summarizeThread', userId, toolId }, { schemaName: 'threadSummarization', schemaDescription: "JSON object representing the summary of a thread and a student's engagement", schema: summarizationSchema, prompt: buildSummarizationPrompt(payload, data), } ); // Save the summary into the DB await client.from('thread_summaries').insert({ thread_id: payload.threadId, ...completion, }); // Alert the teachers that the summary has been completed await client .channel(channels.teacherRoomChannel(roomId)) .send({ type: 'broadcast', event: 'threadSummarized', payload: { threadId, status: 'finished' } }); },};
Here's a short clip showing how this all gets put together:

Conclusion
With Trigger.dev, we’ve summarized over a million student interactions in just a couple of weeks.
With these tasks being I/O-bound, they are ideal for small machine presets—keeping costs low while ensuring reliability. Trigger.dev’s flexibility with machine sizes and running time also leaves the door open for more advanced processing like generating detailed reports to help teachers plan follow-up activities or revisit key topics based off these summaries.
We’re incredibly thankful for tools like Trigger.dev that are empowering us to bring AI-driven solutions to educators and students at scale. Together, we’re helping teachers save time, stay informed, and create better learning outcomes across the globe.