// A scheduled Mastra workflow: every morning, fetch the top Hacker News // stories, have a model write a short digest, and save it to the agent's // workspace, where the agent can read it later. // From https://exe.dev/deploy/mastra/hn-digest.ts import { mkdir, writeFile } from 'node:fs/promises'; import { Agent } from '@mastra/core/agent'; import { createStep, createWorkflow } from '@mastra/core/workflows'; import { z } from 'zod'; const story = z.object({ title: z.string(), url: z.string(), points: z.number() }); const fetchStories = createStep({ id: 'fetch-stories', inputSchema: z.object({ count: z.number().int().min(1).max(30) }), outputSchema: z.object({ stories: z.array(story) }), execute: async ({ inputData }) => { const hn = 'https://hacker-news.firebaseio.com/v0'; const ids: number[] = await (await fetch(`${hn}/topstories.json`)).json(); const stories = await Promise.all( ids.slice(0, inputData.count).map(async (id) => { const item = await (await fetch(`${hn}/item/${id}.json`)).json(); return { title: item.title, url: item.url ?? `https://news.ycombinator.com/item?id=${id}`, points: item.score ?? 0, }; }), ); return { stories }; }, }); const writer = new Agent({ id: 'digest-writer', name: 'Digest writer', instructions: 'Write a short Markdown digest of the stories you are given: a one-line theme, then one bullet per story with its link and why it matters, in under 15 words.', model: 'openai/gpt-6-luna', }); const writeDigest = createStep({ id: 'write-digest', inputSchema: z.object({ stories: z.array(story) }), outputSchema: z.object({ file: z.string(), digest: z.string() }), execute: async ({ inputData }) => { const { text } = await writer.generate(JSON.stringify(inputData.stories)); const file = `workspace/digests/${new Date().toISOString().slice(0, 10)}.md`; await mkdir('workspace/digests', { recursive: true }); await writeFile(file, text + '\n'); return { file, digest: text }; }, }); export const hnDigest = createWorkflow({ id: 'hn-digest', inputSchema: z.object({ count: z.number().int().min(1).max(30) }), outputSchema: z.object({ file: z.string(), digest: z.string() }), schedule: { cron: '0 7 * * *', timezone: 'UTC', inputData: { count: 10 } }, }) .then(fetchStories) .then(writeDigest) .commit();