A purple robot reading a story time book, with a bubble next to it that writes Gemini inside.

Crear un servicio de narración de historias con RCS Rich Cards y Gemini

Publicado el July 30, 2025

Tiempo de lectura: 7 minutos

Introducción

Este tutorial muestra cómo crear un servicio de narración de historias de IA generativa utilizando la API de Messages de Vonage para RCS y Gemini de Google DE GOOGLE. Aprenderás qué es RCS, cómo enviar y recibir mensajes RCS Rich Card y cómo integrar Gemini para generar historias cortas para dormir.

Inspirado por las rutinas de mi hijo pequeño a la hora de dormir, quería crear algo útil. Así que combiné la mensajería RCS con Gemini AI para desarrollar un sencillo servicio de cuentacuentos.

An android phone view showcasing an image that that shows Gemini and tell me a story with a generate story buttonRCS Story Demonstration

Puede encontrar el código fuente completo en el repositorio GitHub de Vonage Community.

Requisitos previos

Cómo hacer que RCS funcione en tu teléfono

Para enviar y recibir mensajes RCS en tu aplicación de Vonage, necesitas un agente RBM registrado y un teléfono con capacidades RCS.

Actualmente, RCS a través de Vonage sólo está disponible para cuentas administradas. Deberá comunicarte con tu administrador de cuenta para activar el modo para desarrolladores, que permite realizar pruebas con números de la lista permitida.

Si no tienes una cuenta administrada, comunícate con el Equipo de ventas de Vonage para obtener ayuda.

Terminología

RCS (Servicios de Comunicación Enriquecidos): Un estándar de la industria que mejora la mensajería tradicional con medios enriquecidos, contenido de marca y recibos de lectura. Si el dispositivo o la red del destinatario no es compatible con RCS, los mensajes vuelven automáticamente a SMS para garantizar su entrega.

Más información en nuestra documentación RCS.

SMS (Servicio de Mensajes Cortos): Los SMS tradicionales sólo admiten texto sin formato. RCS permite botones de marca, imágenes y actualizaciones del estado del mensaje. Aprende a enviar mensajes SMS con Node.js.

MMS (Servicio de Mensajería Multimedia): A diferencia de los MMS, que suelen tener menor calidad de medios y límites de tamaño de archivo, RCS admite medios de alta calidad y funciones como indicadores de escritura y actualizaciones del estado de entrega. Más información en lo que puedes hacer con MMS y cómo enviar MMS con Node.js.

  • Para crear una aplicación, vaya a la sección Crear una aplicación en el panel de Vonage y define un nombre para tu aplicación.

  • Si tiene intención de utilizar una API que utilice Webhooks, necesitará una clave privada. Haga clic en "Generar clave pública y privada"; la descarga debería iniciarse automáticamente. Guárdela de forma segura; esta clave no puede volver a descargarse si se pierde. Seguirá la convención de nomenclatura private_<id de su aplicación>.key. Esta clave puede utilizarse ahora para autenticar llamadas a la API. Nota: La clave no funcionará hasta que se guarde la aplicación.

  • Elija las funciones que necesite (por ejemplo, Voice, Messages, RTC, etc.) y proporcione los webhooks necesarios (por ejemplo, URL de eventos, URL de respuestas o URL de mensajes entrantes). Estos se describirán en el tutorial.

  • Para guardar e implementar, haz clic en "Generar nueva aplicación" para finalizar la configuración. Tu aplicación ahora está lista para usar con las API de Vonage.

Capacidad de la API de Messages

Iniciar una instancia de túnel ngrok

Si no has utilizado ngrok antes, puedes empezar aquí. He añadido los pasos para ejecutar una instancia debajo de la imagen en la siguiente sección.

Ejecute el siguiente comando para iniciar una instancia de túnel ngrok.

ngrok http 3000

En la salida, encontrarás una URL que empieza por https:// y termina en .ngrok.app/. Anótala, ya que la necesitarás en el siguiente paso para configurar tus webhooks.

Forwarding https://94cd51b63460.ngrok.app/ -> http://localhost:8000          

Configurar Webhooks

De vuelta en el panel de la API de Vonage, en tus aplicaciones, activa la opción Messages en capabilities y establece la URL pública de tu servidor desde ngrok como el punto final para los mensajes entrantes y los eventos: https://94cd51b63460.ngrok.app/webhooks/inbound para entrada y https://94cd51b63460.ngrok.app/webhooks/status para el estado. Si desea más información sobre webhooks, puedes encontrarla en nuestra documentación de Vonage.

Inbound and Status URL with an ngrok generated url appended by /webhooks/inbound and /webhooks/stats respectively.webhooks

Configuración inicial del proyecto para Vonage Messages API

Clonar el repositorio GitHub de Vonage Community para este proyecto y npm install las dependencias.

npm install express debug @vonage/messages @vonage/server-sdk dotenv

Crear el archivo de variables de entorno

Crear un archivo .env en la raíz del proyecto.

VONAGE_APPLICATION_ID=YOUR_VONAGE_APPLICATION_ID, can be found within the application you’ve created

VONAGE_PRIVATE_KEY=./private.key, is the path to the private.key file that was generated when you created your application

RCS_SENDER_ID=YOUR_RCS_SENDER_ID

PHONE_NUMBER=YOUR_PHONE_NUMBER_E164 that will receive the RCS messages

PORT=3000

VONAGE_API_SIGNATURE_SECRET= is the secret used to sign the request that corresponds to the signature secret associated with the api_key included in the JWT claims. You can identify your signature secret on the Dashboard settings

En tu proyecto, también encontrarás un archivo archivo vonage.js que contiene la configuración de Dotenv y del cliente de Vonage.

Añadir verificación JWT

Agrega una función de verificación JWT para verificar si la solicitud entrante (por ejemplo, mensaje o llamada) proviene de Vonage.

La variable VONAGE_API_SIGNATURE_SECRET es el secreto utilizado para firmar la solicitud correspondiente al secreto de firma asociado a la clave API incluida en las reivindicaciones JWT. Puede identificar su secreto de firma en los Configuración del panel de control.

Puede obtener más información sobre verificar la solicitud.

const verifyJWT = (req) => {
  // Verify if the incoming request came from Vonage
  const jwtToken = req.headers.authorization.split(" ")[1];
  if(!verifySignature(jwtToken, process.env.VONAGE_API_SIGNATURE_SECRET)) {
    console.error("Signature does not match");
    throw new Error("Not a Vonage API request");
  }

  console.log("JWT verified");
}

Asegúrese de instalar la dependencia @vonage/jwt.

npm install @vonage/jwt

Enviar un mensaje de tarjeta enriquecida RCS

En el archivo archivo server.js encontrarás el código finalizado con la integración de Gemini, pero quería darte un punto de partida sobre cómo enviar un Rich Card Message en RCS con un texto hardcoded para que puedas tener una primera experiencia con él y verlo funcionando antes de cualquier configuración más compleja, con todo lo que hemos configurado hasta ahora.

Empieza por añadir las importaciones y definir tus variables.

import Express from "express";

import { RCSCustom, RCSText } from "@vonage/messages";

import { vonage } from "./vonage.js";

import "dotenv/config";

const app = new Express();

const port = process.env.PORT || 3000;

const recipientNumber = process.env.PHONE_NUMBER;

if (!recipientNumber) {

  process.exit(1);

}

if (!process.env.RCS_SENDER_ID) {

  process.exit(1);

}

También utilizaremos una envoltura asíncrona para la gestión de errores en las rutas.

const catchAsync = (fn) => (req, res, next) => {

  fn(req, res, next).catch(next);

};

app.use(Express.json());

app.get(

  "/send-story-request",

  catchAsync(async (req, res) => {

    await sendBedtimeStoryRequest(recipientNumber);

    res.status(200).json({ message: "Bedtime story request sent!" });

  })

);

Cree el /webhooks/status punto final.

app.post(

  "/webhooks/status",

  catchAsync(async (req, res) => {

    res.status(200).json({ ok: true });

  })

);

Cree el /webhooks/inbound punto final.

app.post(

  "/webhooks/inbound",

  catchAsync(async (req, res) => {

    const { channel, message_type, reply, from } = req.body;

    if (channel === 'rcs' && message_type === 'reply' && reply) {

      const receivedId = reply.id;

      const receivedTitle = reply.title;

      if (receivedId === 'GENERATE_STORY_REQUEST' || receivedTitle === 'Generate Story') {

        const replyToNumber = from;

        const helloWorldMessage = "Hello world!";

        await sendRCSGreeting(replyToNumber, helloWorldMessage);

      } else {

        // Unhandled reply

      }

    } else if (channel === 'rcs' && message_type === 'text') {

      if (req.body.text && req.body.text.toLowerCase() === 'generate story') {

        await sendRCSGreeting(from, "Hello world!");

      } else {

        await sendRCSGreeting(from, "I received your message: " + req.body.text);

      }

    }

    res.status(200).json({ ok: true });

  })

);

Añade algunos mensajes de gestión de errores, y la aplicación escucha en el puerto definido (3000).

app.all("*", (req, res) => {

  res.status(404).json({

    status: 404,

    title: "Not Found",

  });

});

app.use((err, req, res, next) => {

  res.status(500).json({

    status: 500,

    title: "Internal Server Error",

    detail: err.message,

  });

});

app.listen(port);

Cree el sendBedtimeStoryRequest que envía un nuevo mensaje RCS Personalizado que dice 'Generador de cuentos para dormir', que contiene un botón para generar un nuevo cuento.

const sendBedtimeStoryRequest = async (number) => {

  const message = new RCSCustom({

    to: number,

    from: process.env.RCS_SENDER_ID,

    custom: {

      contentMessage: {

        richCard: {

          standaloneCard: {

            cardOrientation: "VERTICAL",

            cardContent: {

              title: "Bedtime Story Generator",

              description: 'Tap "Generate Story" for a magical tale!',

              media: {

                height: "MEDIUM",

                contentInfo: {

                  fileUrl:

                    "https://cdn-icons-png.flaticon.com/512/2917/2917637.png",

                },

              },

              suggestions: [

                {

                  reply: {

                    text: "Generate Story",

                    postbackData: "GENERATE_STORY_REQUEST",

                  },

                },

              ],

            },

          },

        },

      },

    },

  });

  try {

    await vonage.messages.send(message);

  } catch (err) {

    if (err.response) {

      err.response.text().catch(() => {});

    }

  }

};

Crea el sendRCSGreeting que envía un mensaje RCS utilizando la API de Messages de Vonage.

const sendRCSGreeting = async (to, messageText) => {

  const message = new RCSText({

    to: to,

    from: process.env.RCS_SENDER_ID,

    text: messageText,

  });

  try {

    await vonage.messages.send(message);

  } catch (err) {

    if (err.response) {

      err.response.text().catch(() => {});

    }

  }

};

Para ejecutar la aplicación, inicie el servidor:

node server.js

A continuación, visita la siguiente URL en tu navegador, que activa el primer mensaje al teléfono del usuario, invitándole a generar una historia. La confirmación JSON en el navegador, junto con el mensaje RCS recibido en el teléfono, son señales de que el sistema funciona.

http://localhost:3000/send-story-request

Integrar Google Gemini

Ahora que ya tenemos la mensajería RCS y el webhook funcionando, vamos a añadir Google Gemini a nuestro servicio de narración.

Al navegar a AI Studio, inicie sesión y cree un nuevo chat, podrá ver <\>Obtener código</\> en la parte superior derecha y seleccionar el lenguaje de programación que prefiera. Elija el modelo. He utilizado "Gemini 1.5 Flash Experimental", pero puedes elegir el que tenga más sentido para tu proyecto.

Para obtener más información, visite la página de documentación de la API Gemini para desarrolladores.

Instalar el SDK de Gemini

npm install @google/generative-ai

Añada su clave API Gemini a .env.

GEMINI_API_KEY="YOUR_GEMINI_API_KEY"

Inicializar Gemini

import { GoogleGenerativeAI } from "@google/generative-ai";

const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY);

const geminiModel = genAI.getGenerativeModel({ model: "gemini-1.5-flash" });

Generar historias con Gemini

Con Gemini inicializado, actualizamos nuestro /webhooks/inbound controlador. Cuando el usuario haga clic en "Generar cuento", en lugar de responder "¡Hola mundo!", ahora llamaremos a geminiModel.generateContent con un mensaje específico para un cuento.

El texto generado se envía de vuelta al usuario utilizando sendGeneratedStory. También hemos añadido un tratamiento para los usuarios que puedan escribir "Generar historia" manualmente.

La función sendGeneratedStory ahora toma el texto de la historia generada y utiliza RCSText para enviarlo de vuelta como un mensaje de texto RCS regular.

Probar el servicio de narración

Para ejecutar la aplicación, (re)inicia el servidor:

node server.js

A continuación, visite la siguiente URL en su navegador: http://localhost:3000/send-story-request

Desde tu dispositivo, recibirás un mensaje RCS. Toca "Generar historia" para recibir un cuento para dormir creado por Gemini.

A message is received on the phone device, the user clicks on the message, they click on the generate story button and then a story message is received.RCS Project

Conclusión

Este tutorial te mostró cómo construir un servicio de narración de historias impulsado por Gemini usando la API RCS de Vonage. La última vez que hice algo relacionado con RCS fue en 2020. Participé en un taller donde a cada asistente se le envió una tarjeta SIM habilitada para RCS. Fue agradable volver a trabajar con RCS, y no puedo esperar a escribir más entradas de blog sobre esto.

¿Tienes alguna pregunta o algo que compartir? Únete a la conversación en Slack de la comunidad de Vonagey mantente actualizado con el Boletín para desarrolladoressíguenos en X (antes Twitter)suscríbete a nuestro canal de YouTube para ver tutoriales en video, y sigue la página de página para desarrolladores de Vonage en LinkedInun espacio para que los desarrolladores aprendan y se conecten con la comunidad. Mantente conectado, comparte tu progreso y entérate de las últimas noticias, consejos y eventos para desarrolladores.

Compartir:

https://a.storyblok.com/f/270183/400x400/3f6b0c045f/amanda-cavallaro.png
Amanda CavallaroDefensor del Desarrollador