1. Giriş
Google Workspace Studio, Gmail, Google Chat, Google Drive ve Google E-Tablolar gibi Google Workspace uygulamalarında iş süreçlerini otomatikleştirmenize olanak tanır. İş akışlarınızın harici bir web uygulamasından başlatılması veya kendi bulut ortamınızda özel mantık yürütülmesi gerektiğinde, Cloud Run'da Node.js'de HTTP Google Workspace eklentisi ile Google Workspace Studio'yu genişletebilirsiniz:
- Özel başlangıç adımı (
workflowTrigger): Google Workspace Studiotriggers.fireREST API'yi çağırarak, harici bir etkinlik gerçekleştiğinde (ör. bir müşterinin dahili bir web portalında destek kaydı göndermesi) Google Workspace Studio akışını başlatır. - Özel işlem adımı (
workflowAction): Akışın önceki adımlarından değişkenler alır, Node.js hizmetinizde özel mantık veya yapay zeka çıkarımı çalıştırır ve çıkış değişkenlerini Google Workspace Studio'ya geri döndürür.
Bu codelab'de, Cloud Run'da Google Workspace Studio için eksiksiz bir Node.js HTTP uzantısı oluşturup dağıtacak, etkin akış tetikleyici aboneliklerini ve gönderilen biletleri kapsayıcı revizyonları arasında kalıcı hale getirmek için Cloud Firestore'u kullanacak ve Gemini Enterprise Agent Platform'da Gemini 3.8 Flash (gemini-3.8-flash) ile özel işlem adımınızda bilet aciliyetini sınıflandıracaksınız.
Ne oluşturacaksınız?
- Cloud Run üzerinde Node.js, Express ve Firestore ile oluşturulmuş bir Support Quick Portal web uygulaması ve HTTP Google Workspace eklentisi.
studio_triggersFirestore koleksiyonunda etkin akış aboneliklerini sürdüren,support_ticketsFirestore koleksiyonunda gönderilen destek kayıtlarını günlüğe kaydeden ve web portalında bir destek kaydı gönderildiğinde tetiklenen,ticketTitleveticketDescriptiondeğerlerini Google Workspace Studio akışına ileten bir Yeni Destek Kaydı özel başlangıç adımı (supportTicketTrigger).- Gemini Enterprise Agent Platform'da (
aiplatform.googleapis.com) Gemini 3.8 Flash (gemini-3.8-flash) kullanarak bilet aciliyetini sınıflandıran bir Aciliyet Algıla özel işlem adımı (urgencyDetectorStep) ve anahtar kelime eşlemeye (urgent,blocker,critical) otomatik geri dönüş.
Neler öğreneceksiniz?
workflowTriggerveworkflowActionöğeleriyle bir HTTP Google Workspace eklentisi dağıtım manifesti (deployment.json) nasıl yapılandırılır?- Google Workspace Studio tetikleyici aboneliklerinin (
triggerId,notifyUriveuserOAuthToken)studio_triggersFirestore koleksiyonunda nasıl kalıcı hale getirileceği vetriggers.fireREST API kullanılarak akışların nasıl tetikleneceği. - Gemini Enterprise Agent Platform'da Gemini 3.8 Flash (
gemini-3.8-flash) yapılandırılmış çıkışını kullanarak Node.js'de anahtar kelime geri dönüşüyleworkflowActionözel adım oluşturma
Ön koşullar
- Google Workspace Studio'ya erişimi olan bir Google Workspace hesabı.
- Faturalandırmanın etkinleştirildiği bir Google Cloud projesi. Test için yayınlanmamış eklenti dağıtımlarını yükleyebilmeniz amacıyla, kullanıcı hesabınızla aynı Google Workspace kuruluşunda oluşturulur.
2. Google Cloud projenizi ve Firestore'u ayarlama
Bu adımda, projenizin OAuth kullanıcı rızası ekranını yapılandırır, Cloud Shell'de gerekli Google Cloud ve Google Workspace API'lerini etkinleştirir, (default) Firestore veritabanınızı sağlar ve eklenti yetkilendirme hizmeti hesabınızı ilk kullanıma hazırlarsınız.
- Google Cloud Console'u açın, Google Cloud projenizi seçin ve üst gezinme çubuğundaki Cloud Shell'i etkinleştir simgesini tıklayın.
- Google Workspace'in eklentiniz için bir OAuth istemcisi sağlayabilmesi amacıyla OAuth kullanıcı rızası ekranını yapılandırın:
- Google Auth Platform Branding sayfasını açın.
- İstenirse Başlayın'ı tıklayın. (Kullanıcı rızası ekranınız zaten yapılandırılmışsa 3. adıma geçin.)
- Uygulama bilgileri bölümünde Uygulama adı için
Support Extensiongirin, Kullanıcı destek e-postanızı seçin ve Sonraki'yi tıklayın. - Kitle bölümünde Şirket içi'ni seçin ve Sonraki'yi tıklayın.
- İletişim bilgileri bölümünde e-posta adresinizi girip Sonraki'yi tıklayın.
- Bitir bölümünde Google API Hizmetleri: Kullanıcı Verileri Politikası'nı kabul edin, Devam'ı ve Oluştur'u tıklayın.
- Cloud Shell'de etkin projenizi ayarlayın (
YOUR_PROJECT_IDyerine Google Cloud proje kimliğinizi girin) ve gerekli API'leri etkinleştirin: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 (default)Firestore veritabanınızıus-central1içinde sağlayın (henüz yoksa) ve Google Workspace eklentileri hizmet hesabınızı ilk kullanıma hazırlayın: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. Firestore ve Gemini 3.8 Flash ile Node.js uygulaması oluşturma
Bu adımda, Node.js uygulamasını ~/studio-support-addon içinde oluşturursunuz. Kodu modüler ve okunabilir tutmak için projeyi beş odaklanmış dosyaya ayırın:
firestore.js: Cloud Firestore istemcisini (studio_triggersvesupport_ticketskoleksiyonları) başlatır ve önbelleğe alınmış OAuth jetonlarını yeniler.starter.js: Yeni Destek Kaydı özel başlangıç adımı webhook'larını (/onConfigTriggerve/onManageTrigger) uygular.action.js: Anahtar kelime eşleştirme geri dönüşüyle Gemini 3.8 Flash (gemini-3.8-flash) kullanarak Aciliyet Algıla özel işlem adımı webhook'larını (/onConfigUrgencyve/onExecuteUrgency) uygular.portal.js: Destek Hızlı Portalı web kullanıcı arayüzüne (GET /) hizmet verir ve etkin Google Workspace Studio tetikleyicilerini (POST /api/submit-ticket) etkinleştirir.index.js: Tüm Express rotalarını birbirine bağlar ve HTTP sunucusunu başlatır.
Projeyi ve package.json başlatın.
- Bir proje dizini oluşturun ve bu dizine gidin:
mkdir -p ~/studio-support-addon && cd ~/studio-support-addon express,@google-cloud/firestoreve@google/genaiilepackage.jsonoluşturma: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 — Paylaşılan Firestore durumu ve OAuth jetonu yenileme
İki Firestore koleksiyonunuzu yönetmek ve önbelleğe alınmış kullanıcı OAuth jetonlarını güncel tutmak için firestore.js oluşturun:
studio_triggers: Cloud Run kapsayıcı yeniden başlatmalarında ve sıfıra ölçeklendirme etkinliklerinde etkin Google Workspace Studio akışı aboneliklerinin (triggerId,notifyUriveuserOAuthToken) korunmasını sağlar.support_tickets: Portal üzerinden gönderilen her destek kaydının kaydını saklar.refreshTokenInFirestore(req): Google Workspace Studio, webhook uç noktalarınızdan herhangi birini her çağırdığında kısa ömürlü birauthorizationEventObject.userOAuthTokeniçerir. Bu yardımcı, arka plantriggers.fireçağrılarının yetkili kalması için etkin tetikleyici belgeleri en son jetonla günceller.
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 — Özel Başlangıç Adımı (workflowTrigger)
Google Workspace Studio özel başlangıç adımının gerektirdiği iki webhook uç noktasını uygulamak için starter.js oluşturun:
onConfigTrigger(POST /onConfigTrigger): Kullanıcı, Google Workspace Studio'da akışının başlangıcı olarak Yeni Destek Kaydı'nı seçtiğinde çağrılır. Başlatıcıyı açıklayan birpushCardgezinme işlemi döndürür.onManageTrigger(POST /onManageTrigger): Kullanıcı bir akışı etkinleştirdiğinde (req.body.workflow.triggerCreation) veya devre dışı bıraktığında / sildiğinde (req.body.workflow.triggerDeletion) çağrılır. Abonelik dokümanınıstudio_triggersFirestore koleksiyonuna kaydeder veya siler.
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 — Gemini 3.8 Flash ile Özel İşlem Adımı (workflowAction)
Google Workspace Studio özel işlem adımının gerektirdiği iki webhook uç noktasını uygulamak için action.js oluşturun:
onConfigUrgency(POST /onConfigUrgency):hostAppDataSource.workflowDataSource.includeVariables: truedeğerini ayarlayan birtextInputwidget'ı içeren bir yapılandırma kartı döndürür. Bu kart, kullanıcıların başlangıç adımında oluşturulanticketDescriptiondeğişkenini seçmesine olanak tanır.onExecuteUrgency(POST /onExecuteUrgency):req.body.workflow.actionInvocation.inputs'den gelenticketDescriptiongirişini okur, yapılandırılmış çıkış (responseSchemaenum["High", "Normal"]) ile Gemini Enterprise Agent Platform'da Gemini 3.8 Flash (gemini-3.8-flash) kullanarak iş etkisini ve aciliyetini sınıflandırır, model çağrısı başarısız olursadetectKeywordUrgency()'e (urgent,blocker,critical) geri döner vehostAppAction.workflowAction.returnOutputVariablesActionkullanarakurgencyLevelçıkış değişkenini döndürür.
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 — Support Quick Portal UI ve triggers.fire dispatcher
Web portalına hizmet vermek ve bilet gönderimlerini Google Workspace Studio'ya yönlendirmek için portal.js oluşturun:
renderPortal(GET /): Kayıtlı etkin Google Workspace Studio tetikleyicilerinin sayısını göstermek içinstudio_triggersFirestore koleksiyonunu sorgular ve HTML destek kaydı gönderme formunu sunar.submitTicket(POST /api/submit-ticket):studio_triggersiçindeki tüm etkin tetikleyici dokümanları yineler,ticketTitleveticketDescriptionçıkış değişkenleri ve benzersiz birrequestIdile Google Workspace Studiotriggers.fireuç noktasını (https://workspacestudio.googleapis.com/v1/triggers/{triggerId}:fire) çağırır ve biletisupport_ticketsFirestore koleksiyonuna kaydeder.
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: Express sunucusu giriş noktası
Portal rotalarınızı ve Google Workspace Studio webhook uç noktalarınızı index.js ile PORT üzerinde dinleyen bir Express HTTP sunucusunda (Cloud Run'da varsayılan 8080) birbirine bağlayın:
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. Cloud Run'a dağıtma ve eklentiyi yükleme
Bu adımda Node.js hizmetini Cloud Run'a dağıtacak, Google Workspace eklentisi çağırma, Firestore ve Agent Platform çalışma zamanı erişimi için IAM izinleri verecek, deployment.json manifestini oluşturacak ve eklenti dağıtımını yükleyeceksiniz.
support-extensionhizmetini, proje ve Firestore koleksiyonu ortam değişkenlerinizle Cloud Run'a dağıtın: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- Google Workspace Studio'nun webhook uç noktalarınızı çağırabilmesi için Cloud Run hizmetinde Google Workspace Eklentileri hizmet hesabına
roles/run.invokerizni verin: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 - Cloud Run çalışma zamanı hizmet hesabına
roles/datastore.user(studio_triggersvesupport_ticketsFirestore koleksiyonlarını okuma ve yazma için) veroles/aiplatform.user(Gemini Enterprise Agent Platform'da Gemini'ı çağırma için) izinlerini verin: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 - Dağıtılan Cloud Run URL'nizi alın ve
deployment.jsonmanifestini oluşturun. Bu manifest,supportTicketTrigger(workflowTrigger) veurgencyDetectorStep(workflowAction) öğelerini tanımlar: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 - Hesabınız için Google Workspace eklenti dağıtımını oluşturun (veya değiştirin), yükleyin ve Destek Hızlı Portalı URL'nizi yazdırın:
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. Google Workspace Studio'da özel adımlarınızı test etme
- Google Workspace Studio'yu açın (zaten açıksa tarayıcı sekmesini yenileyin) ve Yeni Akış'ı tıklayın.
- Başlangıç seçin > Destek Uzantısı > Yeni Destek Kaydı'nı tıklayın.
- Adım ekle (
+) > Destek Uzantısı > Aciliyet Algıla'yı tıklayın. Kaynak Açıklaması alanında + Değişkenler'i tıklayın ve Destek Kaydı Açıklaması'nı seçin. - Adım ekle'yi (
+) tıklayın ve mesajda Destek Kaydı Başlığı, Aciliyet Düzeyi ve Destek Kaydı Açıklaması değişkenlerini içeren bir Chat > Chat'te beni bilgilendir adımı ekleyin. - Sağ üst köşedeki akışı Açık konuma getirin. Google Workspace Studio, Cloud Run'daki
/onManageTriggeruç noktanızı hemen çağırır. Bu uç nokta, etkin tetikleyici aboneliğini Firestore'dakistudio_triggerskoleksiyonuna yazar. - Destek Hızlı Portal URL'nizi (
https://support-extension-...run.app) yeni bir sekmede açın, portalda Firestore'da1etkin tetikleyicinin göründüğünü onaylayın ve Gemini 3.8 Flash (gemini-3.8-flash) sınıflandırmasını test etmek için iki bilet gönderin:- Yüksek etkili bilet (Bilet Başlığı:
London office lockout, Sorun Açıklaması:All 500 employees in the London office are locked out of their workstations 20 minutes before the board presentation.):urgentveyablockergibi sabit kodlu anahtar kelimeler olmasa bilegemini-3.8-flash, bu biletiHighaciliyetinde sınıflandırır. - Normal öncelikli destek kaydı (Destek kaydı başlığı:
Conference room adapters, Sorun açıklaması:Could we order two extra HDMI adapters for the third-floor conference room next month?):gemini-3.8-flash, bu destek kaydınıNormalaciliyetinde sınıflandırır.
- Yüksek etkili bilet (Bilet Başlığı:
- Google Chat'te ve Google Workspace Studio Etkinlik sekmesinde, akışınızın hem
Urgency Level: Highhem deUrgency Level: Normalile her iki bilet için de çalıştığını doğrulayın.
6. Temizleme
Google Cloud hesabınızdan sürekli olarak ücret alınmasını önlemek için Cloud Shell'de dağıtılan kaynakları kaldırın:
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. Tebrikler!
Gemini Enterprise Agent Platform'da Firestore, Cloud Run ve Gemini 3.8 Flash kullanarak Google Workspace Studio için bir Node.js HTTP uzantısı oluşturup dağıttınız ve test ettiniz.
İşlediğimiz konular
workflowTriggerveworkflowActionöğeleriyle Google Workspace Studio HTTP eklentisi manifesti (deployment.json) yapılandırma.- Google Workspace Studio
workflowTriggeraboneliklerinistudio_triggersFirestore koleksiyonunda kalıcı hale getirme vesupport_ticketsiçinde günlük portalı gönderimleri oluşturma. Böylece tetikleyiciler, Cloud Run ölçeklendirme ve yeniden dağıtma işlemlerinden etkilenmez. - Gemini Enterprise Agent Platform'da Gemini 3.8 Flash (
gemini-3.8-flash) ile destek taleplerini sınıflandıran birworkflowActionadımı oluşturma. Bu adımda, anahtar kelime eşleştirme ile ilgili yedekleme özelliği de bulunur.