<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: David San Nicolás Montero</title>
    <description>The latest articles on DEV Community by David San Nicolás Montero (@davidsnm).</description>
    <link>https://dev.to/davidsnm</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4143924%2F6ef75fc0-79dd-4d5b-9d4c-2550269b5c02.jpg</url>
      <title>DEV Community: David San Nicolás Montero</title>
      <link>https://dev.to/davidsnm</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/davidsnm"/>
    <language>en</language>
    <item>
      <title>Cómo construir una IA que genera presentaciones de Google Slides autónomamente en Node.js</title>
      <dc:creator>David San Nicolás Montero</dc:creator>
      <pubDate>Sat, 26 Sep 2026 08:29:25 +0000</pubDate>
      <link>https://dev.to/davidsnm/como-construir-una-ia-que-genera-presentaciones-de-google-slides-autonomamente-en-nodejs-166</link>
      <guid>https://dev.to/davidsnm/como-construir-una-ia-que-genera-presentaciones-de-google-slides-autonomamente-en-nodejs-166</guid>
      <description>&lt;p&gt;Los Modelos de Lenguaje (LLMs) son increíbles redactando propuestas comerciales, pero se estrellan cuando intentas que le den formato corporativo a ese texto. La mayoría de tutoriales te enseñan a generar texto en la terminal, pero en el mundo B2B real, los usuarios no leen terminales: leen presentaciones corporativas, PDFs y hojas de cálculo.&lt;/p&gt;

&lt;p&gt;Hoy vamos a construir un puente entre la Inteligencia Artificial &lt;a href="https://asistente-zyro-workspace.web.app/app.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Zyro&lt;/strong&gt;&lt;/a&gt; y Google Workspace. Te enseñaré cómo crear un &lt;em&gt;skill&lt;/em&gt; (habilidad) en Node.js que permite a un agente inteligente orquestar la API de Google Slides para generar presentaciones completas desde cero, aplicando tu plantilla corporativa.&lt;/p&gt;

&lt;p&gt;Para no reinventar la rueda con la gestión de &lt;em&gt;webhooks&lt;/em&gt;, esquemas OpenAPI y el enrutamiento de la IA, utilizaremos el &lt;strong&gt;&lt;a href="https://github.com/Davidsnm/zyro-skills-sdk" rel="noopener noreferrer"&gt;Zyro Skills SDK&lt;/a&gt;&lt;/strong&gt;, una librería &lt;em&gt;open-source&lt;/em&gt; diseñada para inyectar herramientas personalizadas en agentes autónomos de forma segura mediante &lt;em&gt;Function Calling&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  El concepto: Inversión de Control y Memoria Descentralizada
&lt;/h2&gt;

&lt;p&gt;En lugar de darle a la IA las llaves de tu Google Cloud (un riesgo de seguridad enorme), utilizaremos un patrón descentralizado. La IA decide &lt;strong&gt;qué&lt;/strong&gt; contenido debe ir en la presentación, pero es nuestro servidor Node.js quien ejecuta el &lt;strong&gt;cómo&lt;/strong&gt;. Además, el SDK de Zyro gestiona automáticamente un &lt;code&gt;session_id&lt;/code&gt; anónimo, permitiendo que nuestro &lt;em&gt;skill&lt;/em&gt; mantenga su propia base de datos (memoria descentralizada) sin sobrecargar el contexto del LLM.&lt;/p&gt;

&lt;h2&gt;
  
  
  Requisitos Previos
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Node.js instalado.&lt;/li&gt;
&lt;li&gt;Una Service Account de Google Cloud con la API de Google Slides y Google Drive habilitadas.&lt;/li&gt;
&lt;li&gt;El ID de una presentación de Google Slides que servirá como "Plantilla Maestra" corporativa.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Paso 1: Configuración del Proyecto
&lt;/h2&gt;

&lt;p&gt;Iniciamos nuestro proyecto e instalamos el SDK junto con la librería oficial de Google:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm init &lt;span class="nt"&gt;-y&lt;/span&gt;
npm &lt;span class="nb"&gt;install &lt;/span&gt;express cors googleapis dotenv

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Paso 2: Inicializar el SDK de Zyro
&lt;/h2&gt;

&lt;p&gt;Creamos nuestro archivo index.js. Aquí instanciamos la clase principal ZyroSkill, que levantará un servidor Express configurado para escuchar al orquestador de la IA.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const { ZyroSkill } = require('./src/index'); // Ajusta la ruta a tu SDK
const { google } = require('googleapis');

// 1. Inicializar el SDK
const slidesSkill = new ZyroSkill({
    name: "Generador de Presentaciones Corporativas",
    description: "Permite al orquestador clonar plantillas de Google Slides e inyectar contenido dinámico generado por la IA.",
    port: process.env.PORT || 3000
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Paso 3: Registrar la Acción para Google Slides
&lt;/h2&gt;

&lt;p&gt;Utilizamos el método registerAction de tu SDK. Aquí definimos el esquema JSON que la IA debe respetar al enviarnos los datos, y la función asíncrona que ejecutará la clonación del documento en Google Drive.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
// 2. Definir Acción: Crear Presentación
slidesSkill.registerAction(
'generar_google_slides',
'Genera una presentación comercial en Google Slides a partir del nombre del cliente y los textos clave.',
{
type: 'object',
properties: {
clientName: {
type: 'string',
description: 'Nombre de la empresa cliente para el título del archivo'
},
diapositivas: {
type: 'array',
description: 'Lista de textos a inyectar en las diapositivas',
items: { type: 'string' }
}
},
required: ['clientName', 'diapositivas']
},
async (parameters, context) =&amp;gt; {
const { session_id } = context;
const { clientName, diapositivas } = parameters;
// 3. Autenticación silenciosa con Google Service Account
    const auth = new google.auth.GoogleAuth({
        keyFile: './google-credentials.json',
        scopes: [
            '[https://www.googleapis.com/auth/presentations](https://www.googleapis.com/auth/presentations)', 
            '[https://www.googleapis.com/auth/drive](https://www.googleapis.com/auth/drive)'
        ]
    });

    const drive = google.drive({ version: 'v3', auth });
    const slides = google.slides({ version: 'v1', auth });
try {
console.log([Sesión: ${session_id}] Generando propuesta para: ${clientName});

        // 4. Clonar la Plantilla Maestra en Drive
        const copyResponse = await drive.files.copy({
            fileId: process.env.TEMPLATE_ID,
            requestBody: { name: `Propuesta Comercial - ${clientName}` }
        });

        const newPresentationId = copyResponse.data.id;

        // 5. Dar permisos para que cualquiera con el enlace pueda editar
        await drive.permissions.create({
            fileId: newPresentationId,
            requestBody: {
                role: 'writer',
                type: 'anyone'
            }
        });
// 6. Preparar las sustituciones de texto para Slides
const requests = [
{
replaceAllText: {
containsText: { text: '{{CLIENTE}}', matchCase: true },
replaceText: clientName
}
}
];

        // Añadimos un reemplazo automático por cada elemento del array
        diapositivas.forEach((texto, index) =&amp;gt; {
            requests.push({
                replaceAllText: {
                    containsText: { text: `{{TEXTO_${index + 1}}}`, matchCase: true },
                    replaceText: texto
                }
            });
        });

        // 7. Inyectar los textos generados por la IA en la presentación
        await slides.presentations.batchUpdate({
            presentationId: newPresentationId,
            requestBody: { requests }
        });

        // 8. Devolver el resultado limpio al Orquestador
            return {
                mensaje: 'Presentación clonada y generada correctamente.',
                url_documento: 'https://docs.google.com/presentation/d/' + newPresentationId + '/edit'
            };

        } catch (error) {
            console.error('Error en API de Google:', error);
            throw new Error('Fallo al generar la presentación: ' + error.message);
        }
    }
);

// Arrancamos el servidor de Skills
slidesSkill.start();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>node</category>
      <category>ai</category>
      <category>googleworkspace</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
