Cómo crear un starter

En este documento, se explica cómo compilar un activador que permita que tu app o servicio notifique a Google Workspace Studio cuando se produce un evento y que inicie la ejecución de un flujo. En la API, los activadores se denominan workflowTriggers.

Un activador inicia un flujo, mientras que un paso es una sola tarea en la secuencia de tareas que abarca un flujo. Cuando compilas un activador, permites que los usuarios configuren flujos automatizados que reaccionen a eventos en tiempo real de tu app o servicio.

Para compilar un activador, debes declararlo en el archivo de manifiesto del complemento y, luego, implementar devoluciones de llamada de ciclo de vida en Google Apps Script o activar el activador publicando cargas útiles en el endpoint de API de Google Workspace Studio.

Requisitos previos

  • Una Cuenta de Google con acceso a Workspace Studio
  • Un proyecto de Google Cloud.

Habilita la API

En tu proyecto de Google Cloud, habilita la API de Google Workspace Studio:

Habilita la API

Cambia a un proyecto estándar de Google Cloud (solo Google Apps Script)

De forma predeterminada, los proyectos de Apps Script usan un proyecto predeterminado de Cloud que no admite la habilitación de APIs ni la configuración de pantallas de consentimiento de OAuth. Si compilas tu activador con Apps Script, debes cambiar a un proyecto estándar de Google Cloud:

  1. En el editor de Apps Script, haz clic en Configuración del proyecto .
  2. En Proyecto de Google Cloud Platform (GCP), haz clic en Cambiar proyecto.
  3. Ingresa el número de tu proyecto estándar de Cloud y haz clic en Establecer proyecto.
  4. Después de cambiar de proyecto, vuelve a autorizar tu secuencia de comandos ejecutando cualquier función en el editor y otorgando los permisos solicitados.

Para obtener más información, consulta Cambia a un proyecto estándar de Google Cloud.

Cómo configurar la pantalla de consentimiento de OAuth

Para comunicarse con el endpoint de API de Workspace Studio, tu app o servicio debe autenticarse con OAuth 2.0. Configura la pantalla de consentimiento de OAuth de tu proyecto y agrega el siguiente permiso de OAuth exclusivo:

https://www.googleapis.com/auth/workspace.studio.trigger

Este permiso autoriza a la app a llamar a la API de Workspace Studio y activar los flujos que el usuario configuró para ese activador.

Para obtener más información, consulta Cómo configurar la pantalla de consentimiento de OAuth y elegir permisos.

Acceso sin conexión y tokens de actualización

Dado que los activadores notifican a Workspace Studio de forma asíncrona cuando se produce un evento en el servicio externo (lo que puede ocurrir horas, días o meses después de que un usuario configura un flujo), tu servicio debe proporcionar un token de acceso de OAuth 2.0 válido cuando llame al extremo de la API.

El token de acceso que proporciona Google en el objeto de evento del complemento (por ejemplo, durante la configuración del activador o las solicitudes de devolución de llamada de ciclo de vida) es de corta duración y solo es válido por 1 hora. No es suficiente para activar eventos de activador de forma asíncrona en el futuro. Para llamar a la API de Workspace Studio con el tiempo, tu servicio requiere un token de actualización sin conexión para generar tokens de acceso nuevos a pedido.

La forma en que controlas la autorización y obtienes un token de actualización depende del tiempo de ejecución del complemento:

  • Complementos HTTP (tiempos de ejecución alternativos): Para los complementos HTTP, tu servicio de backend debe implementar un flujo de autorización de OAuth 2.0 independiente de la autorización integrada del complemento para solicitar acceso sin conexión (access_type=offline) y recibir un token de actualización.

    Puedes solicitar a los usuarios que autoricen esta conexión mostrando una tarjeta de acceso o autorización cuando el usuario configure el activador en Workspace Studio. Para obtener más información sobre cómo mostrar tarjetas de autorización y controlar el flujo de OAuth, consulta Conecta tu complemento de Google Workspace a un servicio externo (tratando a Google Workspace como el servicio externo al que te conectas).

    Tu servicio de backend debe almacenar el token de actualización de forma segura (por ejemplo, en la base de datos de tu servicio junto con el triggerId) y usarlo para recuperar un token de acceso nuevo cada vez que se produzca un evento antes de enviar solicitudes al notifyUri del activador o al endpoint de API de triggers.fire.

  • Complementos de Google Apps Script: Los complementos basados en Google Apps Script que usan activadores programados (controlados por tiempo) para sondear eventos pueden omitir la implementación de un flujo de OAuth independiente. Dado que los activadores programados se ejecutan directamente en el entorno de ejecución de Google Apps Script, Google Apps Script administra y actualiza automáticamente los tokens de OAuth con los permisos declarados en el manifiesto. Puedes recuperar un token de acceso de OAuth con ScriptApp.getOAuthToken().

Define el activador en el archivo de manifiesto

Para definir un activador, agrégalo al archivo de manifiesto del complemento (appsscript.json) dentro del bloque addOns.studio.flows.workflowElements. Esta configuración es obligatoria para los tiempos de ejecución de Apps Script y HTTP (tiempos de ejecución alternativos). Configura el elemento como workflowTrigger en lugar de workflowAction (que se usa cuando se define un paso). Para obtener más información, consulta Estructura del manifiesto para complementos de Google Workspace.

Dentro del bloque workflowTrigger, especifica lo siguiente:

  • inputs: Variables que el usuario configura en la tarjeta de configuración (como el nombre del proyecto, el filtro de recursos, etcétera)
  • outputs: Variables que el activador puede mostrar a los pasos posteriores del flujo
  • onConfigFunction: El nombre de la función de devolución de llamada que muestra la interfaz de configuración del usuario
  • onManageFunction: El nombre de la función de devolución de llamada que invoca Google para controlar la creación y eliminación de suscripciones de activadores

En la siguiente muestra de código, se muestra una definición de manifiesto de ejemplo para un activador de eventos:

JSON

{
  "timeZone": "America/Los_Angeles",
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8",
  "oauthScopes": [
    "https://www.googleapis.com/auth/script.external_request",
    "https://www.googleapis.com/auth/workspace.studio.trigger"
  ],
  "urlFetchWhitelist": [
    "https://workspacestudio.googleapis.com/"
  ],
  "addOns": {
    "common": {
      "name": "Trigger App",
      "logoUrl": "https://fonts.gstatic.com/s/i/short-term/release/googlesymbols/start/default/24px.svg",
      "useLocaleFromApp": true
    },
    "studio": {
      "flows": {
        "workflowElements": [
          {
            "id": "triggerDemo",
            "state": "ACTIVE",
            "name": "Event Trigger",
            "description": "Fires when a event occurs in the app.",
            "workflowTrigger": {
              "inputs": [
                {
                  "id": "projectId",
                  "description": "The project identifier to watch.",
                  "cardinality": "SINGLE",
                  "dataType": {
                    "basicType": "STRING"
                  }
                }
              ],
              "outputs": [
                {
                  "id": "eventName",
                  "description": "The name of the triggered event.",
                  "cardinality": "SINGLE",
                  "dataType": {
                    "basicType": "STRING"
                  }
                },
                {
                  "id": "eventMessage",
                  "description": "Detailed event message description.",
                  "cardinality": "SINGLE",
                  "dataType": {
                    "basicType": "STRING"
                  }
                }
              ],
              "onConfigFunction": "onConfigTrigger",
              "onManageFunction": "onManageTrigger"
            }
          }
        ]
      }
    }
  }
}

Administra el ciclo de vida de la suscripción del activador

Cuando un usuario configura y habilita un flujo que contiene tu activador, o si el flujo está inhabilitado o borrado, Google llama a tu complemento con la función de devolución de llamada onManageFunction declarada en el manifiesto.

El objeto de evento de ciclo de vida

La función de devolución de llamada recibe un WorkflowEventObject que contiene el contexto de la acción. En el caso de los activadores, esto incluye lo siguiente:

  • Creación del activador (event.workflow.triggerCreation): Se activa cuando se publica o habilita el flujo.

    • triggerId: Una cadena UUID única que identifica esta instancia de registro del activador

    • notifyUri: La URL única del endpoint de API de REST asociada con este registro del activador (por ejemplo, https://workspacestudio.googleapis.com/v1/triggers/YOUR_TRIGGER_ID:fire). Si se omite notifyUri de la carga útil del evento, crea la URL del endpoint directamente con el triggerId: https://workspacestudio.googleapis.com/v1/triggers/{triggerId}:fire.

    • inputs: Las entradas de variables que configuró el usuario desde la tarjeta

  • Borrado del activador (event.workflow.triggerDeletion): Se activa cuando se quita el activador del flujo o cuando se inhabilita o borra todo el flujo.

    • triggerId: La cadena UUID única de la instancia de suscripción que se limpiará

Ciclo de vida de la suscripción de tiempos de ejecución alternativos (API de HTTP)

En el caso de los complementos compilados con tiempos de ejecución alternativos, las notificaciones del ciclo de vida de la suscripción se entregan con solicitudes POST de HTTP a la URL del extremo HTTP configurada del complemento con el nombre de la acción especificado por la función de devolución de llamada onManageFunction. La carga útil coincide con la representación JSON del WorkflowEventObject.

Para obtener más información sobre los tiempos de ejecución alternativos, consulta Crea un complemento de Google Workspace con extremos HTTP .

Implementa devoluciones de llamada de ciclo de vida en Apps Script

En el siguiente ejemplo de Apps Script, se muestra cómo configurar la tarjeta de la interfaz de usuario, controlar los eventos del ciclo de vida de la suscripción con onManageTrigger y volver a activar la solicitud del activador a Google cuando se produce un evento.

Apps Script

/**
 * Generates and returns the user configuration card to collect inputs.
 */
function onConfigTrigger() {
  const projectInput = CardService.newTextInput()
    .setFieldName("projectId")
    .setTitle("Project ID")
    .setHint("Enter the project identifier to watch");

  const section = CardService.newCardSection()
    .setHeader("Configure Event Trigger")
    .addWidget(projectInput);

  const card = CardService.newCardBuilder()
    .addSection(section)
    .build();

  return card;
}

/**
 * Handles subscription lifecycle events sent from Google Workspace Studio.
 *
 * @param {Object} event The Workspace Studio event object.
 */
function onManageTrigger(event) {
  const triggerCreation = event.workflow.triggerCreation;
  const triggerDeletion = event.workflow.triggerDeletion;

  if (triggerCreation) {
    const triggerId = triggerCreation.triggerId;
    // Fall back to constructing the endpoint URL if notifyUri is omitted.
    const notifyUri = triggerCreation.notifyUri ||
        ("https://workspacestudio.googleapis.com/v1/triggers/" +
         triggerId + ":fire");
    const inputs = triggerCreation.inputs;

    // Extract input values configured by the user.
    const projectId = inputs["projectId"].stringValues[0];

    // Tip: In Apps Script, use PropertiesService to persist triggerId and notifyUri:
    // const props = PropertiesService.getUserProperties();
    // props.setProperty("notifyUri", notifyUri);
    // props.setProperty("triggerId", triggerId);
    //
    // TODO: Save triggerId, notifyUri, and projectId in your database/service.
    // Your backend service listens for events related to 'projectId'
    // and calls notifyUri when those events occur.
    console.log("Trigger subscription created: " + triggerId +
                ", Notify URI: " + notifyUri +
                ", Match Project: " + projectId);

  } else if (triggerDeletion) {
    const triggerId = triggerDeletion.triggerId;

    // In Apps Script, clean up stored properties:
    // PropertiesService.getUserProperties().deleteProperty("notifyUri");
    // PropertiesService.getUserProperties().deleteProperty("triggerId");
    //
    // TODO: Remove references to triggerId from your database and stop
    // sending future event notifications to the associated notifyUri.
    console.log("Trigger subscription deleted: " + triggerId);
  }
}

/**
 * Mock function showing how your backend service fires the trigger.
 * This logic runs on your service when a watched event occurs.
 *
 * @param {string} notifyUri The stored notifyUri associated with the trigger.
 * @param {string} triggerId The stored triggerId.
 * @param {string} [userAccessToken] The OAuth 2.0 access token for the user.
 *     In Apps Script, defaults to ScriptApp.getOAuthToken().
 */
function simulateEventFire(notifyUri, triggerId, userAccessToken) {
  // In Apps Script, obtain the OAuth token using ScriptApp.getOAuthToken().
  const token = userAccessToken || ScriptApp.getOAuthToken();
  // A unique UUID version 4 is recommended as the requestId for idempotency.
  const requestId = Utilities.getUuid();

  const payload = {
    "name": "triggers/" + triggerId,
    "outputs": {
      "eventName": { "stringValues": ["EventOccurred"] },
      "eventMessage": { "stringValues": ["Hello from the service!"] }
    },
    "requestId": requestId
  };

  const options = {
    "method": "POST",
    "contentType": "application/json",
    "headers": {
      "Authorization": "Bearer " + token
    },
    "payload": JSON.stringify(payload),
    "muteHttpExceptions": true
  };

  const response = UrlFetchApp.fetch(notifyUri, options);
  const responseCode = response.getResponseCode();

  if (responseCode === 200) {
    console.log("Trigger successfully fired!");
  } else if (responseCode === 404) {
    // 404 means the trigger registration is invalid or deleted.
    console.log("Trigger not found. Stop sending events for this trigger.");
    // TODO: Clean up the trigger from your backend database.
  } else if (responseCode === 429 || responseCode >= 500) {
    console.log("Temporary error (" + responseCode + "). Retry using exponential backoff.");
  } else {
    console.log("Failed to fire trigger. HTTP Code: " + responseCode + " - " + response.getContentText());
  }
}

Usa la API de Workspace Studio

Puedes usar la API de Workspace Studio (workspacestudio.googleapis.com) para notificar a Google de forma programática sobre los eventos del activador.

Los extremos se encuentran en la ruta base: https://workspacestudio.googleapis.com/v1.

Notifica un evento del activador

Activa un activador con el triggers.fire método para iniciar la ejecución de un flujo.

  • Método HTTP: POST
  • Ruta de acceso: /v1/triggers/{triggerId}:fire (donde {triggerId} es el identificador único que se recuperó durante la creación de la suscripción del activador)
  • Permiso de OAuth: https://www.googleapis.com/auth/workspace.studio.trigger

En la siguiente muestra de código, se muestra cómo activar un activador en la solicitud.

Solicitud

{
  "name": "triggers/TRIGGER_ID",
  "outputs": {
    "eventName": {
      "stringValues": [
        "EventOccurred"
      ]
    },
    "eventMessage": {
      "stringValues": [
        "Hello from the service!"
      ]
    }
  },
  "log": {
    "textFormatElements": [
      {
        "text": "An event occurred in the app."
      }
    ]
  },
  "requestId": "UNIQUE_REQUEST_ID"
}
  • name (string, obligatorio): El nombre del recurso del activador, con el formato triggers/{triggerId}
  • outputs (map, opcional): Un mapa de variables de salida del activador que representan los datos del evento Cada valor es un objeto VariableData que admite listas con tipo (como stringValues, booleanValues, integerValues).
  • log (objeto, opcional): Una representación de marcado TextFormat que se muestra en los registros de actividad de ejecución de Workspace Studio
  • requestId (string, opcional): Un identificador único (se recomienda UUID v4) de hasta 36 caracteres ASCII para garantizar la idempotencia de la API en los reintentos

Respuesta

La respuesta muestra un objeto JSON vacío {} si la operación se realiza correctamente.

Cuotas de la API de Workspace Studio

El tráfico enviado al servicio workspacestudio.googleapis.com está restringido para evitar la sobrecarga del sistema, fomentar el uso legítimo de los recursos y proteger el rendimiento general de Google Workspace.

Se aplican las siguientes cuotas:

Tipo de cuota Quota
Por minuto por proyecto 1,000 solicitudes de activadores
Por minuto por usuario 100 solicitudes de activadores

Los tipos de cuotas son los siguientes:

  • Por minuto por proyecto: Limita la cantidad acumulada de eventos de activadores activados desde el proyecto de Google Cloud de un solo desarrollador a 1,000 solicitudes por minuto en todos los usuarios que ejecutan sus activadores.
  • Por minuto por usuario: Limita las invocaciones acumuladas de activadores de un solo usuario final en un proyecto de Cloud determinado a 100 solicitudes por minuto.

Controla los errores de cuota basados en el tiempo

Si excedes estas cuotas, la API muestra un código de error HTTP 429 Too Many Requests (o 429 Resource Exhausted) que indica que se excedió la cuota de frecuencia.

Para resolver estos errores, tu código debe detectar la excepción y usar una estrategia de retirada exponencial truncada. La retirada exponencial reintenta las solicitudes con errores con retrasos cada vez más largos entre los intentos, incluido el jitter aleatorio (volver a calcular un retraso aleatorio en cada iteración) para evitar que varios clientes se sincronicen y vuelvan a intentar al mismo tiempo:

  1. Realiza una solicitud a la API de Workspace Studio.
  2. Si la solicitud falla con un 429 error, espera 1 second + random_number_milliseconds y vuelve a intentarlo.
  3. Si vuelve a fallar, espera 2 seconds + random_number_milliseconds y vuelve a intentarlo.
  4. Si vuelve a fallar, espera 4 seconds + random_number_milliseconds y vuelve a intentarlo.
  5. Continúa con este bucle, duplicando la demora hasta un umbral maximum_backoff (por lo general, 32 o 64 segundos).
  6. Una vez que alcances la duración máxima de retirada, vuelve a intentarlo con esa demora constante hasta que se alcance el límite máximo de reintentos. Luego, detén el proceso y registra el error.

Prácticas recomendadas

Cuando diseñes y implementes un activador, ten en cuenta las siguientes prácticas recomendadas:

Emite eventos únicos en lugar de listas por lotes

Diseña tu activador para que emita un evento individual para cada ocurrencia distinta (como un solo registro actualizado, un mensaje nuevo publicado o una tarea asignada) en lugar de emitir un solo evento que contenga un lote o una lista de elementos:

  • Coherencia con los activadores integrados: En Workspace Studio, los activadores integrados de Google Workspace (como recibir un correo electrónico en Gmail o que un usuario se una a un espacio en Google Chat) se activan en un solo evento. La emisión de eventos de un solo elemento se alinea con este comportamiento y proporciona una experiencia coherente y predecible para los usuarios en todos los activadores.
  • Configuración de flujo más simple: Los pasos posteriores de un flujo suelen procesar un elemento a la vez. La emisión de eventos de un solo elemento permite a los usuarios asignar variables directamente sin agregar pasos complejos para iterar sobre arrays o analizar listas.
  • Controla los cambios de sondeo y lotes de forma individual: Si tu servicio de backend sondea una API externa y detecta varios elementos modificados durante un solo intervalo de sondeo, activa un evento de activador individual para cada elemento en lugar de agruparlos en un evento de lote.
  • Administra la frecuencia de eventos y las cuotas: Debido a que la activación de eventos individuales para varios elementos modificados puede causar una ráfaga repentina de solicitudes, asegúrate de que tu servicio se mantenga dentro de las cuotas de la API de Workspace Studio (como el límite de 100 solicitudes por minuto por usuario). Si un ciclo de sondeo genera un gran volumen de elementos (por ejemplo, más de 100 registros modificados), regula o limita los envíos de eventos a lo largo del tiempo para evitar errores 429 Too Many Requests.

Comportamientos principales y situaciones limítrofes

Cuando integran activadores, los desarrolladores deben controlar comportamientos de error y funciones de tiempo de ejecución específicos:

  • No se admite la ejecución de pruebas: Workspace Studio no admite ejecuciones de pruebas para activadores.
  • Idempotencia y prevención de reproducción: Aunque no es estrictamente necesario, debes incluir un requestId único (como un UUID) en tu carga útil de HTTP o Apps Script. Proporcionar un requestId garantiza la idempotencia, ya que permite que la API detecte y omita las notificaciones duplicadas, lo que evita que el flujo se ejecute varias veces para un solo evento.
  • Flujos inhabilitados y habilitados nuevamente: Cuando se inhabilita un flujo que contiene tu activador en Workspace Studio, Google envía un evento de ciclo de vida triggerDeletion a tu devolución de llamada onManageFunction. Además, cualquier llamada al método FireTrigger asociado muestra un código de retorno de error 404 Not Found (Requested entity was not found.). Tu servicio debe reaccionar a los errores 404 deteniendo las entregas futuras de notificaciones de eventos para ese ID de instancia del activador.

    Si un usuario vuelve a habilitar el flujo más adelante, Google inicia un nuevo ciclo de vida de la suscripción invocando tu devolución de llamada onManageFunction con un nuevo evento triggerCreation que contiene un nuevo triggerId y notifyUri. El triggerId anterior se retira de forma permanente y no se reactiva, por lo que tu servicio no debe sondear ni verificar si se volvió a habilitar una instancia de activador anterior. Para obtener más información, consulta Administra el ciclo de vida de la suscripción del activador.

  • Borrado idempotente de la suscripción: Tu onManageFunction función de devolución de llamada debe controlar las solicitudes de borrado de activadores de Google de forma idempotente. Si Google llama al hook de borrado varias veces para el mismo triggerId (por ejemplo, durante los reintentos debido a pérdidas de conexión temporales), la función debe mostrarse correctamente.

  • Cuotas de flujo: Además de las cuotas de la API de Workspace Studio, los flujos de usuarios están sujetos a controles de cuota internos adicionales. Los bucles de alta frecuencia o el volumen excesivo de eventos pueden exceder los umbrales de seguridad, lo que provoca la inhabilitación automática del flujo.

  • Permiso denegado (403) en la activación del activador: Si las llamadas al extremo triggers.fire muestran 403 PERMISSION_DENIED con un estado de error SERVICE_DISABLED, verifica lo siguiente:

    • La API de Google Workspace Studio está habilitada en tu proyecto de Google Cloud.
    • Si usas Google Apps Script, tu proyecto está vinculado a un proyecto estándar de Cloud en lugar del proyecto predeterminado de Apps Script Cloud.
    • El token de acceso de OAuth incluye el permiso https://www.googleapis.com/auth/workspace.studio.trigger.