1. Introdução
Com o Google Workspace Studio, você automatiza processos de negócios em aplicativos do Google Workspace, como Gmail, Google Chat, Google Drive e Google Planilhas. Quando seus fluxos de trabalho precisam começar em um aplicativo da Web externo ou executar uma lógica personalizada no seu próprio ambiente de nuvem, é possível estender o Google Workspace Studio com um complemento do Google Workspace HTTP em Node.js no Cloud Run:
- Etapa inicial personalizada (
workflowTrigger): inicia um fluxo do Google Workspace Studio quando ocorre um evento externo, como um cliente enviando um tíquete em um portal da Web interno, chamando a API RESTtriggers.firedo Google Workspace Studio. - Etapa de ação personalizada (
workflowAction): recebe variáveis de etapas anteriores no fluxo, executa lógica personalizada ou inferência de IA no seu serviço Node.js e retorna variáveis de saída para o Google Workspace Studio.
Neste codelab, você vai criar e implantar uma extensão HTTP Node.js completa para o Google Workspace Studio no Cloud Run, usar o Cloud Firestore para manter as assinaturas de gatilho de fluxo ativas e os tíquetes enviados em todas as revisões de contêineres e classificar a urgência dos tíquetes na etapa de ação personalizada usando o Gemini 3.8 Flash (gemini-3.8-flash) na Gemini Enterprise Agent Platform com um fallback resiliente de correspondência de palavras-chave.
O que você vai criar
- Um web app Support Quick Portal e um complemento HTTP do Google Workspace criados com Node.js, Express e Firestore no Cloud Run.
- Uma etapa inicial personalizada Novo tíquete de suporte (
supportTicketTrigger) que mantém as assinaturas de fluxo ativas em uma coleção do Firestorestudio_triggers, registra os tíquetes enviados em uma coleção do Firestoresupport_ticketse é acionada sempre que um tíquete é enviado no portal da Web, transmitindoticketTitleeticketDescriptionpara um fluxo do Google Workspace Studio. - Uma etapa de ação personalizada Detect Urgency (
urgencyDetectorStep) que classifica a urgência do tíquete usando o Gemini 3.8 Flash (gemini-3.8-flash) na Gemini Enterprise Agent Platform (aiplatform.googleapis.com), com um fallback automático para correspondência de palavras-chave (urgent,blocker,critical).
O que você vai aprender
- Como configurar um manifesto de implantação de complemento do Google Workspace HTTP (
deployment.json) com elementosworkflowTriggereworkflowAction. - Como persistir assinaturas de gatilhos do Google Workspace Studio (
triggerId,notifyUrieuserOAuthToken) em uma coleçãostudio_triggersdo Firestore e disparar fluxos usando a API RESTtriggers.fire. - Como criar uma etapa personalizada
workflowActionem Node.js usando a saída estruturada do Gemini 3.8 Flash (gemini-3.8-flash) na Gemini Enterprise Agent Platform com um fallback de palavra-chave.
Pré-requisitos
- Uma conta do Google Workspace com acesso ao Google Workspace Studio.
- Um projeto do Google Cloud com o faturamento ativado, criado na mesma organização do Google Workspace que sua conta de usuário para que você possa instalar implantações de complementos não publicadas para teste.
2. Configurar seu projeto na nuvem do Google Cloud e o Firestore
Nesta etapa, você vai configurar a tela de permissão do OAuth do projeto, ativar as APIs necessárias do Google Cloud e do Google Workspace no Cloud Shell, provisionar o banco de dados do Firestore (default) e inicializar a conta de serviço de autorização do complemento.
- Abra o console do Google Cloud, selecione seu projeto na nuvem e clique no ícone Ativar o Cloud Shell na barra de navegação superior.
- Configure a tela de permissão OAuth para que o Google Workspace possa provisionar um cliente OAuth para seu complemento:
- Abra a página de branding da Google Auth Platform.
- Se for solicitado, clique em Começar. Se a tela de permissão já estiver configurada, pule para a etapa 3.
- Em Informações do app, insira
Support Extensionno Nome do app, selecione seu E-mail de suporte ao usuário e clique em Próxima. - Em Público-alvo, selecione Interno e clique em Próxima.
- Em Informações de contato, insira seu endereço de e-mail e clique em Próxima.
- Em Concluir, aceite a Política de dados do usuário dos serviços de API do Google, clique em Continuar e em Criar.
- No Cloud Shell, defina seu projeto ativo (substitua
YOUR_PROJECT_IDpelo ID do projeto do Google Cloud) e ative as APIs necessárias:gcloud config set project YOUR_PROJECT_ID gcloud services enable \ aiplatform.googleapis.com \ firestore.googleapis.com \ run.googleapis.com \ cloudbuild.googleapis.com \ artifactregistry.googleapis.com \ appsmarket-component.googleapis.com \ gsuiteaddons.googleapis.com \ workspacestudio.googleapis.com - Provisione seu banco de dados Firestore
(default)emus-central1(se ele ainda não existir) e inicialize sua conta de serviço de complementos do Google Workspace:gcloud firestore databases describe --database="(default)" >/dev/null 2>&1 || \ gcloud firestore databases create \ --database="(default)" \ --location=us-central1 \ --type=firestore-native \ --quiet gcloud workspace-add-ons get-authorization
3. Criar o app Node.js com o Firestore e o Gemini 3.8 Flash
Nesta etapa, você vai criar o aplicativo Node.js em ~/studio-support-addon. Para manter o código modular e legível, organize o projeto em cinco arquivos focados:
firestore.js: inicializa o cliente do Cloud Firestore (coleçõesstudio_triggersesupport_tickets) e atualiza os tokens OAuth em cache.starter.js: implementa os webhooks da etapa inicial personalizada Novo tíquete de suporte (/onConfigTriggere/onManageTrigger).action.js: implementa os webhooks da etapa de ação personalizada Detect Urgency (/onConfigUrgencye/onExecuteUrgency) usando o Gemini 3.8 Flash (gemini-3.8-flash) com um fallback de correspondência de palavras-chave.portal.js: veicula a interface da Web do Portal rápido de suporte (GET /) e aciona gatilhos ativos do Google Workspace Studio (POST /api/submit-ticket).index.js: conecta todas as rotas do Express e inicia o servidor HTTP.
Inicializar o projeto e package.json
- Crie um diretório de projeto e navegue até ele:
mkdir -p ~/studio-support-addon && cd ~/studio-support-addon - Crie
package.jsoncomexpress,@google-cloud/firestoree@google/genai:cat << 'EOF' > package.json { "name": "studio-support-addon", "version": "1.0.0", "type": "module", "main": "index.js", "scripts": { "start": "node index.js" }, "dependencies": { "@google-cloud/firestore": "^7.11.0", "@google/genai": "^1.0.0", "express": "^4.21.2" } } EOF
firestore.js — Estado compartilhado do Firestore e atualização do token OAuth
Crie firestore.js para gerenciar as duas coleções do Firestore e manter atualizados os tokens OAuth do usuário em cache:
studio_triggers: armazena as assinaturas ativas do fluxo do Google Workspace Studio (triggerId,notifyUrieuserOAuthToken) para que elas sobrevivam a reinicializações de contêineres do Cloud Run e eventos de redução da escala a zero.support_tickets: armazena um registro de cada tíquete de suporte enviado pelo portal.refreshTokenInFirestore(req): sempre que o Google Workspace Studio chama um dos seus endpoints de webhook, ele inclui umauthorizationEventObject.userOAuthTokende curta duração. Esse auxiliar atualiza os documentos de acionamento ativos com o token mais recente para que as chamadastriggers.fireem segundo plano permaneçam autorizadas.
cat << 'EOF' > firestore.js
import { Firestore } from '@google-cloud/firestore';
export const db = new Firestore({
projectId: process.env.GOOGLE_CLOUD_PROJECT || undefined,
databaseId: '(default)',
ignoreUndefinedProperties: true,
});
export const triggersCollection = db.collection(
process.env.FIRESTORE_TRIGGERS_COLLECTION || 'studio_triggers'
);
export const ticketsCollection = db.collection(
process.env.FIRESTORE_TICKETS_COLLECTION || 'support_tickets'
);
// Keep cached userOAuthToken fresh across active trigger documents
export async function refreshTokenInFirestore(req) {
const freshToken = req.body?.authorizationEventObject?.userOAuthToken;
if (!freshToken) return;
try {
const snapshot = await triggersCollection.get();
if (snapshot.empty) return;
const batch = db.batch();
snapshot.docs.forEach((doc) => {
batch.set(
doc.ref,
{ userOAuthToken: freshToken, updatedAt: new Date().toISOString() },
{ merge: true }
);
});
await batch.commit();
} catch (err) {
console.error('Error refreshing OAuth token in Firestore:', err.message);
}
}
EOF
starter.js: etapa de ativação personalizada (workflowTrigger)
Crie starter.js para implementar os dois endpoints de webhook necessários para uma etapa inicial personalizada do Google Workspace Studio:
onConfigTrigger(POST /onConfigTrigger): chamado quando um usuário seleciona Novo tíquete de suporte como o iniciador do fluxo no Google Workspace Studio. Retorna uma ação de navegaçãopushCardque descreve o iniciador.onManageTrigger(POST /onManageTrigger): é chamado quando um usuário ativa (req.body.workflow.triggerCreation) ou desativa / exclui (req.body.workflow.triggerDeletion) um fluxo. Salva ou exclui o documento de assinatura na coleçãostudio_triggersdo Firestore.
cat << 'EOF' > starter.js
import { triggersCollection, refreshTokenInFirestore } from './firestore.js';
// Custom Starter Configuration Card
export async function onConfigTrigger(req, res) {
await refreshTokenInFirestore(req);
res.status(200).json({
action: {
navigations: [
{
pushCard: {
sections: [
{
header: 'Support Ticket Listener',
widgets: [
{
textParagraph: {
text: 'This starter listens for new tickets submitted through the Support Quick Portal and stores subscriptions in Firestore.',
},
},
],
},
],
},
},
],
},
});
}
// Custom Starter Subscription Lifecycle (Firestore studio_triggers collection)
export async function onManageTrigger(req, res) {
try {
const triggerCreation = req.body?.workflow?.triggerCreation;
const triggerDeletion = req.body?.workflow?.triggerDeletion;
const userOAuthToken =
req.body?.authorizationEventObject?.userOAuthToken || null;
if (triggerCreation?.triggerId) {
const triggerId = String(triggerCreation.triggerId);
const docId = encodeURIComponent(triggerId);
await triggersCollection.doc(docId).set(
{
triggerId,
notifyUri: triggerCreation.notifyUri || null,
...(userOAuthToken ? { userOAuthToken } : {}),
updatedAt: new Date().toISOString(),
},
{ merge: true }
);
}
if (triggerDeletion?.triggerId) {
const triggerId = String(triggerDeletion.triggerId);
const docId = encodeURIComponent(triggerId);
await triggersCollection.doc(docId).delete();
}
if (!triggerCreation && !triggerDeletion && userOAuthToken) {
await refreshTokenInFirestore(req);
}
} catch (err) {
console.error('Error in /onManageTrigger:', err.message);
}
res.status(200).json({});
}
EOF
action.js: etapa de ação personalizada (workflowAction) com o Gemini 3.8 Flash
Crie action.js para implementar os dois endpoints de webhook necessários em uma etapa de ação personalizada do Google Workspace Studio:
onConfigUrgency(POST /onConfigUrgency): retorna um card de configuração com um widgettextInputque definehostAppDataSource.workflowDataSource.includeVariables: true, permitindo que os usuários selecionem a variávelticketDescriptiongerada pela etapa inicial.onExecuteUrgency(POST /onExecuteUrgency): lê a entradaticketDescriptiondereq.body.workflow.actionInvocation.inputs, classifica o impacto e a urgência nos negócios usando o Gemini 3.8 Flash (gemini-3.8-flash) na Gemini Enterprise Agent Platform com saída estruturada (tipo enumeradoresponseSchema["High", "Normal"]), volta paradetectKeywordUrgency()(urgent,blocker,critical) se a chamada do modelo falhar e retorna a variável de saídaurgencyLevelusandohostAppAction.workflowAction.returnOutputVariablesAction.
cat << 'EOF' > action.js
import { GoogleGenAI, Type } from '@google/genai';
import { refreshTokenInFirestore } from './firestore.js';
// Initialize Google GenAI SDK for the Gemini Enterprise Agent Platform
const ai = new GoogleGenAI({
vertexai: true,
project: process.env.GOOGLE_CLOUD_PROJECT,
location: 'global',
});
// Fallback keyword classifier if the Gemini API call is unavailable
export function detectKeywordUrgency(description) {
const lower = (description || '').toLowerCase();
return lower.includes('urgent') ||
lower.includes('blocker') ||
lower.includes('critical')
? 'High'
: 'Normal';
}
// Custom Action Step Configuration Card
export async function onConfigUrgency(req, res) {
await refreshTokenInFirestore(req);
res.status(200).json({
action: {
navigations: [
{
pushCard: {
sections: [
{
header: 'Urgency Detector Step',
widgets: [
{
textInput: {
name: 'ticketDescription',
label: 'Source Description',
hintText:
'Select the description variable outputted by the starter',
hostAppDataSource: {
workflowDataSource: {
includeVariables: true,
},
},
},
},
],
},
],
},
},
],
},
});
}
// Custom Action Step Execution: Gemini 3.8 Flash with keyword fallback
export async function onExecuteUrgency(req, res) {
await refreshTokenInFirestore(req);
const inputs = req.body?.workflow?.actionInvocation?.inputs || {};
const description = inputs.ticketDescription?.stringValues?.[0] || '';
let urgencyLevel = detectKeywordUrgency(description);
try {
const response = await ai.models.generateContent({
model: 'gemini-3.8-flash',
contents: `Evaluate the business impact and time sensitivity of this support ticket description and classify its urgency:\n\n${description}`,
config: {
responseMimeType: 'text/x.enum',
responseSchema: {
type: Type.STRING,
enum: ['High', 'Normal'],
},
},
});
const candidate = (response.text || '').trim();
if (candidate === 'High' || candidate === 'Normal') {
urgencyLevel = candidate;
}
} catch (err) {
console.error('Gemini fallback to keyword matching:', err.message);
}
res.status(200).json({
hostAppAction: {
workflowAction: {
returnOutputVariablesAction: {
variables: {
urgencyLevel: {
stringValues: [urgencyLevel],
},
},
},
},
},
});
}
EOF
portal.js: compatibilidade com a interface do usuário do Quick Portal e o dispatcher triggers.fire
Crie portal.js para veicular o portal da Web e enviar solicitações de tíquetes ao Google Workspace Studio:
renderPortal(GET /): consulta a coleçãostudio_triggersdo Firestore para mostrar quantos gatilhos ativos do Google Workspace Studio estão registrados e veicula o formulário HTML de envio de tíquetes.submitTicket(POST /api/submit-ticket): itera todos os documentos de acionamento ativos emstudio_triggers, invoca o endpointtriggers.firedo Google Workspace Studio (https://workspacestudio.googleapis.com/v1/triggers/{triggerId}:fire) com as variáveis de saídaticketTitleeticketDescriptione umrequestIdexclusivo, e salva o tíquete na coleçãosupport_ticketsdo Firestore.
cat << 'EOF' > portal.js
import { triggersCollection, ticketsCollection } from './firestore.js';
// Support Quick Portal UI
export async function renderPortal(req, res) {
let activeCount = 0;
try {
const snapshot = await triggersCollection.get();
activeCount = snapshot.size;
} catch (err) {
console.error('Error reading studio_triggers collection:', err.message);
}
res.status(200).send(`<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Support Quick Portal</title>
<style>
body { font-family: Arial, sans-serif; padding: 24px; max-width: 540px; margin: auto; color: #202124; }
.badge { background: #e8f0fe; color: #1967d2; padding: 8px 12px; border-radius: 6px; font-size: 14px; margin-bottom: 16px; }
label { font-weight: bold; display: block; margin-top: 16px; }
input, textarea { width: 100%; margin-top: 6px; padding: 10px; box-sizing: border-box; border: 1px solid #dadce0; border-radius: 4px; }
button { background-color: #1a73e8; color: white; border: none; padding: 10px 18px; margin-top: 16px; font-weight: bold; cursor: pointer; border-radius: 4px; }
button:hover { background-color: #1557b0; }
#status { margin-top: 16px; font-weight: bold; }
</style>
</head>
<body>
<h2>Support Quick Portal</h2>
<div class="badge">
Active Google Workspace Studio triggers in Firestore (<code>studio_triggers</code>):
<strong id="trigger-count">${activeCount}</strong>
</div>
<p>Submit a support ticket below to fire your Google Workspace Studio flow.</p>
<label for="title">Ticket Title</label>
<input type="text" id="title" placeholder="e.g. Database failure">
<label for="description">Issue Description</label>
<textarea id="description" rows="4" placeholder="Describe the issue..."></textarea>
<button onclick="submitTicket()">Submit Ticket</button>
<div id="status"></div>
<script>
async function submitTicket() {
const title = document.getElementById('title').value.trim();
const description = document.getElementById('description').value.trim();
const statusEl = document.getElementById('status');
if (!title || !description) {
statusEl.style.color = '#d93025';
statusEl.textContent = 'Please fill out both fields.';
return;
}
statusEl.style.color = '#188038';
statusEl.textContent = 'Submitting ticket...';
try {
const res = await fetch('/api/submit-ticket', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ title, description }),
});
const data = await res.json();
if (data.ok) {
statusEl.textContent =
'Ticket saved to Firestore! Fired ' + data.triggersFired + ' Google Workspace Studio trigger(s).';
} else {
statusEl.style.color = '#d93025';
statusEl.textContent = 'Error: ' + (data.error || 'Unknown error');
}
} catch (err) {
statusEl.style.color = '#d93025';
statusEl.textContent = 'Request failed: ' + err.message;
}
}
</script>
</body>
</html>`);
}
// Portal Form Submission -> Fire Active Google Workspace Studio Triggers
export async function submitTicket(req, res) {
const title = req.body?.title || 'Untitled Ticket';
const description = req.body?.description || '';
const results = [];
try {
const snapshot = await triggersCollection.get();
for (const doc of snapshot.docs) {
const trigger = doc.data();
if (!trigger.triggerId || !trigger.userOAuthToken) continue;
const response = await fetch(
`https://workspacestudio.googleapis.com/v1/triggers/${encodeURIComponent(trigger.triggerId)}:fire`,
{
method: 'POST',
headers: {
Authorization: `Bearer ${trigger.userOAuthToken}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: 'triggers/' + trigger.triggerId,
outputs: {
ticketTitle: { stringValues: [title] },
ticketDescription: { stringValues: [description] },
},
requestId:
'req_' + Date.now() + '_' + Math.floor(Math.random() * 1000),
}),
}
);
results.push({ triggerId: trigger.triggerId, status: response.status });
}
await ticketsCollection.add({
title,
description,
triggersFired: results.length,
createdAt: new Date().toISOString(),
});
res.status(200).json({ ok: true, triggersFired: results.length, results });
} catch (err) {
console.error('Error in /api/submit-ticket:', err.message);
res.status(500).json({ ok: false, error: err.message });
}
}
EOF
index.js: ponto de entrada do servidor Express
Crie index.js para conectar as rotas do portal e os endpoints de webhook do Google Workspace Studio em um servidor HTTP do Express que detecta PORT (o padrão é 8080 no Cloud Run):
cat << 'EOF' > index.js
import express from 'express';
import { onConfigTrigger, onManageTrigger } from './starter.js';
import { onConfigUrgency, onExecuteUrgency } from './action.js';
import { renderPortal, submitTicket } from './portal.js';
const app = express();
app.use(express.json());
// Support Quick Portal routes
app.get('/', renderPortal);
app.post('/api/submit-ticket', submitTicket);
// Google Workspace Studio Custom Starter Step webhooks
app.post('/onConfigTrigger', onConfigTrigger);
app.post('/onManageTrigger', onManageTrigger);
// Google Workspace Studio Custom Action Step webhooks
app.post('/onConfigUrgency', onConfigUrgency);
app.post('/onExecuteUrgency', onExecuteUrgency);
const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {
console.log(`Support Extension listening on port ${PORT}`);
});
EOF
4. Implantar no Cloud Run e instalar o complemento
Nesta etapa, você vai implantar o serviço Node.js no Cloud Run, conceder permissões do IAM para o invocador de complementos do Google Workspace e o acesso ao tempo de execução do Firestore e da Agent Platform, gerar o manifesto deployment.json e instalar a implantação do complemento.
- Implante o serviço
support-extensionno Cloud Run com as variáveis de ambiente do projeto e da coleção do Firestore:gcloud run deploy support-extension \ --source . \ --region us-central1 \ --allow-unauthenticated \ --set-env-vars="GOOGLE_CLOUD_PROJECT=$(gcloud config get-value project),FIRESTORE_TRIGGERS_COLLECTION=studio_triggers,FIRESTORE_TICKETS_COLLECTION=support_tickets" \ --quiet - Conceda
roles/run.invokerno serviço do Cloud Run à conta de serviço dos complementos do Google Workspace para que o Google Workspace Studio possa chamar seus endpoints de webhook:ADDON_SA=$(gcloud workspace-add-ons get-authorization --format="value(serviceAccountEmail)") gcloud run services add-iam-policy-binding support-extension \ --region=us-central1 \ --member="serviceAccount:${ADDON_SA}" \ --role="roles/run.invoker" \ --quiet - Conceda
roles/datastore.user(para leitura e gravação das coleçõesstudio_triggersesupport_ticketsdo Firestore) eroles/aiplatform.user(para chamar o Gemini na Gemini Enterprise Agent Platform) à conta de serviço do ambiente de execução do Cloud Run:PROJECT_ID=$(gcloud config get-value project) PROJECT_NUMBER=$(gcloud projects describe "${PROJECT_ID}" --format="value(projectNumber)") RUNTIME_SA=$(gcloud run services describe support-extension --region=us-central1 --format="value(spec.template.spec.serviceAccountName)") RUNTIME_SA=${RUNTIME_SA:-"${PROJECT_NUMBER}-compute@developer.gserviceaccount.com"} gcloud projects add-iam-policy-binding "${PROJECT_ID}" \ --member="serviceAccount:${RUNTIME_SA}" \ --role="roles/datastore.user" \ --condition=None \ --quiet gcloud projects add-iam-policy-binding "${PROJECT_ID}" \ --member="serviceAccount:${RUNTIME_SA}" \ --role="roles/aiplatform.user" \ --condition=None \ --quiet - Recupere o URL implantado do Cloud Run e gere o manifesto
deployment.jsondefinindo os elementossupportTicketTrigger(workflowTrigger) eurgencyDetectorStep(workflowAction):SERVICE_URL=$(gcloud run services describe support-extension --region=us-central1 --format="value(status.url)") cat << EOF > deployment.json { "oauthScopes": [ "https://www.googleapis.com/auth/workspace.studio.trigger", "https://www.googleapis.com/auth/userinfo.email" ], "addOns": { "common": { "name": "Support Extension", "logoUrl": "https://www.gstatic.com/images/branding/productlogos/buganizer/v1/192px.svg" }, "studio": { "flows": { "workflowElements": [ { "id": "supportTicketTrigger", "state": "ACTIVE", "name": "New Support Ticket", "description": "Fires when someone submits a ticket in the Support Quick Portal.", "workflowTrigger": { "inputs": [], "outputs": [ { "id": "ticketTitle", "description": "Ticket Title", "cardinality": "SINGLE", "dataType": { "basicType": "STRING" } }, { "id": "ticketDescription", "description": "Ticket Description", "cardinality": "SINGLE", "dataType": { "basicType": "STRING" } } ], "onConfigFunction": "${SERVICE_URL}/onConfigTrigger", "onManageFunction": "${SERVICE_URL}/onManageTrigger" } }, { "id": "urgencyDetectorStep", "state": "ACTIVE", "name": "Detect Urgency", "description": "Evaluates the ticket description to detect High or Normal urgency.", "workflowAction": { "inputs": [ { "id": "ticketDescription", "description": "Description to scan", "cardinality": "SINGLE", "dataType": { "basicType": "STRING" } } ], "outputs": [ { "id": "urgencyLevel", "description": "Detected Urgency (High / Normal)", "cardinality": "SINGLE", "dataType": { "basicType": "STRING" } } ], "onConfigFunction": "${SERVICE_URL}/onConfigUrgency", "onExecuteFunction": "${SERVICE_URL}/onExecuteUrgency" } } ] } }, "httpOptions": { "authorizationHeader": "SYSTEM_ID_TOKEN" } } } EOF - Crie (ou substitua) e instale a implantação do complemento do Google Workspace na sua conta e imprima o URL do Portal rápido de suporte:
gcloud workspace-add-ons deployments create support-extension --deployment-file=deployment.json || \ gcloud workspace-add-ons deployments replace support-extension --deployment-file=deployment.json gcloud workspace-add-ons deployments install support-extension echo "Support Quick Portal URL: ${SERVICE_URL}"
5. Testar etapas personalizadas no Google Workspace Studio
- Abra o Google Workspace Studio (atualize a guia do navegador se ela já estiver aberta) e clique em Novo fluxo.
- Clique em Selecionar uma etapa inicial > Extensão de suporte > Novo tíquete de suporte.
- Clique em Adicionar etapa (
+) > Extensão de suporte > Detectar urgência. No campo Descrição da origem, clique em + Variáveis e selecione Descrição do tíquete. - Clique em Adicionar etapa (
+) e adicione uma etapa Chat > Me notificar pelo Chat que inclua as variáveis Título do tíquete, Nível de urgência e Descrição do tíquete na mensagem. - Ative o fluxo Ativado no canto superior direito. O Google Workspace Studio chama imediatamente o endpoint
/onManageTriggerno Cloud Run, que grava a assinatura de gatilho ativa na coleçãostudio_triggersdo Firestore. - Abra o URL do portal rápido de suporte (
https://support-extension-...run.app) em uma nova guia, confirme se o portal mostra o gatilho ativo1no Firestore e envie dois tíquetes para testar a classificação do Gemini 3.8 Flash (gemini-3.8-flash):- Ticket de alto impacto (Título do ticket:
London office lockout, Descrição do problema:All 500 employees in the London office are locked out of their workstations 20 minutes before the board presentation.): mesmo sem palavras-chave codificadas, comourgentoublocker,gemini-3.8-flashclassifica esse ticket como de urgênciaHigh. - Tíquete de rotina (Título do tíquete:
Conference room adapters, Descrição do problema:Could we order two extra HDMI adapters for the third-floor conference room next month?):gemini-3.8-flashclassifica esse tíquete como de urgênciaNormal.
- Ticket de alto impacto (Título do ticket:
- Verifique no Google Chat e na guia Atividade do Google Workspace Studio se o fluxo foi executado para os dois tíquetes com
Urgency Level: HigheUrgency Level: Normal.
6. Limpar
Para evitar cobranças contínuas na sua conta do Google Cloud, remova os recursos implantados no Cloud Shell:
gcloud workspace-add-ons deployments uninstall support-extension
gcloud workspace-add-ons deployments delete support-extension --quiet
gcloud run services delete support-extension --region=us-central1 --quiet
gcloud firestore databases delete --database="(default)" --quiet
7. Parabéns!
Você criou, implantou e testou uma extensão HTTP do Node.js para o Google Workspace Studio usando o Firestore, o Cloud Run e o Gemini 3.8 Flash na Gemini Enterprise Agent Platform.
O que aprendemos
- Configuração de um manifesto de complemento HTTP do Google Workspace Studio (
deployment.json) com elementosworkflowTriggereworkflowAction. - Persistência das assinaturas do Google Workspace Studio
workflowTriggerna coleçãostudio_triggersFirestore e envios do portal de geração de registros emsupport_ticketspara que os gatilhos sobrevivam ao escalonamento e às novas implantações do Cloud Run. - Criar uma etapa
workflowActionque classifica tíquetes de suporte com saída estruturada Gemini 3.8 Flash (gemini-3.8-flash) na Gemini Enterprise Agent Platform, com um fallback resiliente de correspondência de palavras-chave.