Bora construir um Agente de Notícias Hiper-Personalizado? 🤖📰 (Codar Juntos)

Published: (December 19, 2025 at 09:37 PM EST)
4 min read
Source: Dev.to

Source: Dev.to

A ideia: Chega de newsletter genérica!

Você já percebeu que a maioria das newsletters de tech são genéricas demais ou só cobrem o que acontece no Vale do Silício? Decidi mudar isso criando um Software Agêntico que faz curadoria sob medida, e quero convidar você a codar comigo.

Não é só um chatbot. É um agente autônomo que:

  • Varre a web em tempo real usando Tavily.
  • Filtra por país e idioma: quer notícias sobre IA que saíram no Japão, mas resumidas em português? O agente resolve.
  • Sintetiza com Gemini 1.5 Pro – o “cérebro” que traduz, resume e formata.
  • Entrega via Resend – automação direto para a sua inbox (ou de uma audiência inteira).

Funcionalidades principais

  • Busca em tempo real na web (Tavily).
  • Filtragem por país e idioma.
  • Síntese e tradução com Gemini 1.5 Pro.
  • Envio de e‑mail automatizado (Resend + MJML).

Stack tecnológica

CamadaTecnologia
FrameworkNext.js (Vercel)
InteligênciaGemini SDK + Tavily API
Banco de dados & ORMMongoDB + Prisma
E‑mailResend (Audiences para escalabilidade)
Design de e‑mailMJML (responsivo)

Roadmap (tarefas)

  • Definir a arquitetura (Prisma + Mongo).
  • Criar o formulário de captura de preferências (temas, países, idiomas).
  • Orquestrar o loop do agente: pesquisa → resumo → tradução.
  • Configurar o Cron Job na Vercel para envio semanal automático.

Como você pode colar junto

  • Comente: qual feature você adicionaria a um agente de notícias?
  • Escolha a stack que mais te interessa (Prompt Engineering, Integração de APIs ou Frontend no Next.js).
  • GitHub: o repositório será liberado com a aplicação completa.

Objetivo inicial: ter o projeto rodando localmente e o banco pronto para receber inscritos.

Setup rápido

# Crie a aplicação Next.js
npx create-next-app@latest ai-newsletter

Instale as dependências:

npm install @prisma/client @google/generative-ai @tavily/core resend zod mjml

Configure o schema.prisma com o modelo Subscriber (ver exemplo abaixo).

Implementação

Interface do usuário

  • Formulário com:
    • Input de e‑mail.
    • Selects para País e Idioma.
    • Checkboxes para Temas de interesse.

API

  • Rota /api/subscribe salva o cadastro no MongoDB via Prisma.
// pages/api/subscribe.ts
import { NextApiRequest, NextApiResponse } from 'next';
import { prisma } from '../../lib/prisma';
import { z } from 'zod';

const schema = z.object({
  email: z.string().email(),
  country: z.string(),
  language: z.string(),
  topics: z.array(z.string()),
});

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  if (req.method !== 'POST') return res.status(405).end();

  const result = schema.safeParse(req.body);
  if (!result.success) return res.status(400).json(result.error.format());

  await prisma.subscriber.create({ data: result.data });
  return res.status(200).json({ message: 'Inscrição salva com sucesso!' });
}

Busca & Síntese (A “mágica” agêntica)

// lib/agent.ts
import { Tavily } from '@tavily/core';
import { Gemini } from '@google/generative-ai';

export async function generateNewsletter(preferences) {
  const searchResults = await Tavily.search({
    query: preferences.topics.join(', '),
    region: preferences.country,
    language: preferences.language,
  });

  const prompt = `
    Você é um assistente que deve:
    1. Resumir as notícias encontradas.
    2. Traduzir o resumo para ${preferences.language}.
    3. Formatar o conteúdo como e‑mail (HTML).
  `;

  const gemini = new Gemini({ model: 'gemini-1.5-pro' });
  const response = await gemini.generate({
    prompt,
    documents: searchResults,
  });

  return response.text; // HTML pronto para MJML
}

Prompt Engineering

  • O prompt acima instrui o Gemini a formatar especificamente para o idioma do usuário e a gerar HTML pronto para MJML.

Integração MJML

// lib/mjml.ts
import mjml2html from 'mjml';

export function renderEmail(htmlContent) {
  const mjmlTemplate = `
    <mjml>
      <mj-body>
        <mj-section>
          <mj-column>
            ${htmlContent}
          </mj-column>
        </mj-section>
      </mj-body>
    </mjml>
  `;
  const { html } = mjml2html(mjmlTemplate);
  return html;
}

Lógica de batch (envio)

// pages/api/send-newsletter.ts
import { prisma } from '../../lib/prisma';
import { generateNewsletter } from '../../lib/agent';
import { renderEmail } from '../../lib/mjml';
import { resend } from '../../lib/resend';

export default async function handler(req, res) {
  const subscribers = await prisma.subscriber.findMany();

  for (const sub of subscribers) {
    const content = await generateNewsletter(sub);
    const html = renderEmail(content);

    await resend.sendEmail({
      from: 'news@yourdomain.com',
      to: sub.email,
      subject: 'Sua newsletter personalizada',
      html,
    });
  }

  res.status(200).json({ message: 'Newsletters enviadas' });
}

Cron Job na Vercel

Crie o arquivo vercel.json:

{
  "crons": [
    {
      "path": "/api/send-newsletter",
      "schedule": "0 9 * * MON"
    }
  ]
}

Isso agenda a execução toda segunda‑feira às 9h.

Teste final

  1. Cadastre um e‑mail via formulário.
  2. Verifique a recepção da newsletter na caixa de entrada.

Próximos passos

  • Refatorar a orquestração usando queues (ex.: BullMQ).
  • Adicionar suporte a multiplas audiências no Resend.
  • Implementar cache de resultados de busca para reduzir custos.

Bora parar de só dar “oi” pro ChatGPT e começar a construir ferramentas que realmente entregam valor de forma autônoma. 🚀

Back to Blog

Related posts

Read more »