How to set up an AI agent to summarize long email threads in Google Chat
You know that feeling — you step away for a coffee, come back, and Google Chat has 43 new messages in the #project‑firefly room. Scrolling, searching for decisions, losing context. 😫
This guide shows you how to build a kind, quiet AI agent that lives in Google Chat (or watches from the side) and whispers a tidy summary of any long thread. No code degree required.
what you’ll need
Google Workspace (Chat enabled) Gemini API key or Claude API key Google Apps Script 15 minutes🧘 the blueprint: how the agent works
- Trigger: you type
/summarizein a Google Chat space (or react with 📝). - Fetch: a script collects the last N messages from the thread (or the whole thread).
- Summarize: messages are sent to Gemini/Claude with a prompt: “summarize decisions, action items, key points”.
- Post: the AI summary is posted back to the space as a neat card or message.
Go to console.cloud.google.com, create a new project (or select existing).
- Enable Google Chat API.
- Go to “APIs & Services” → “Credentials” → Create OAuth 2.0 Client ID (application type: “Desktop app” or “Web application” — for Apps Script we’ll use script’s built-in auth later).
- Enable Gemini API (or Vertex AI) if using Google AI. Otherwise grab Claude key separately.
Open script.google.com, start a new project. Name it “Chat summarizer bot”.
🔧 code overview (copy & customize)
// Google Chat AI summarizer — fetches thread, calls Gemini, posts summary
const GEMINI_API_KEY = "YOUR_GOOGLE_AI_STUDIO_KEY"; // from aistudio.google.com
function doGet(e) {
return ContentService.createTextOutput("Bot is alive.");
}
// this function will be called when the bot is mentioned or slash command
function onMessage(event) {
// event.space.name, event.message.text, event.message.thread
if (event.message.slashCommand) {
if (event.message.slashCommand.commandId === 1) { // /summarize
return summarizeThread(event);
}
}
return { text: "👋 use /summarize to get a summary of this thread." };
}
function summarizeThread(event) {
const spaceName = event.space.name;
const threadKey = event.message.thread.name; // unique thread id
// 1. fetch recent messages in the thread (last 50)
const messages = listMessages(spaceName, threadKey, 50);
if (!messages || messages.length === 0) return { text: "no messages found." };
// 2. format them into a prompt
const threadText = messages.map(m => m.text).join("\n");
const prompt = `Summarize the following Google Chat thread. Keep it friendly but concise.
- highlight key decisions ✅
- action items with owners (if mentioned) 📋
- any deadlines or dates 📅
- overall vibe / conclusion.
Thread messages:\n${threadText}\n\nSummary:`;
// 3. call Gemini (or Claude)
const summary = callGemini(prompt);
// 4. post summary back to thread
postMessage(spaceName, threadKey, `📋 *Thread summary:*\n${summary}`);
return { text: "summary posted above 👆" }; // fallback
}
// helper: list messages from a thread
function listMessages(spaceName, threadKey, max=50) {
const url = `https://chat.googleapis.com/v1/${spaceName}/messages?pageSize=${max}&threadKey=${encodeURIComponent(threadKey)}`;
const response = UrlFetchApp.fetch(url, {
headers: { Authorization: 'Bearer ' + ScriptApp.getOAuthToken() }
});
const data = JSON.parse(response);
return data.messages || [];
}
// helper: call Gemini 1.5 Flash
function callGemini(promptText) {
const url = `https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=${GEMINI_API_KEY}`;
const payload = {
contents: [{ parts: [{ text: promptText }] }],
generationConfig: { temperature: 0.3, maxOutputTokens: 400 }
};
const options = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
payload: JSON.stringify(payload)
};
const response = UrlFetchApp.fetch(url, options);
const json = JSON.parse(response);
return json.candidates[0].content.parts[0].text;
}
function postMessage(spaceName, threadKey, text) {
const url = `https://chat.googleapis.com/v1/${spaceName}/messages`;
const payload = {
text: text,
thread: { name: threadKey }
};
UrlFetchApp.fetch(url, {
method: 'POST',
headers: { Authorization: 'Bearer ' + ScriptApp.getOAuthToken() },
contentType: 'application/json',
payload: JSON.stringify(payload)
});
}
After pasting, replace GEMINI_API_KEY with your actual key (from aistudio.google.com → Get API key).
- In Apps Script editor, click Project Settings → check “Show ‘appsscript.json’ manifest file in editor”.
- Go back to editor, open
appsscript.jsonand add Chat scopes:
{
"timeZone": "America/New_York",
"dependencies": {},
"exceptionLogging": "STACKDRIVER",
"oauthScopes": [
"https://www.googleapis.com/auth/chat.messages",
"https://www.googleapis.com/auth/chat.spaces.readonly",
"https://www.googleapis.com/auth/script.external_request"
],
"chat": {
"name": "Thread Summarizer",
"description": "Summarizes long threads using AI",
"slashCommands": [{
"commandId": 1,
"name": "summarize",
"description": "Get a summary of this thread",
"commandType": "MESSAGE"
}]
}
}
Save. Then deploy: Deploy → New deployment → type “Google Chat app”. Copy the deployment ID.
Go back to Google Cloud Console → APIs & Services → Google Chat API → Configuration.
- App name: Thread Summarizer
- Avatar: optional
- Description: friendly AI that summarizes threads
- Functionality: Check “Bot works in direct messages, room mentions, and space mentions”.
- Connection settings: “Apps Script project” → paste your Deployment ID.
- Slash commands: add command “/summarize” with ID 1.
- Permissions: “Specific people and groups in your domain” (or make it public internally).
Save. Now add the bot to any Chat space by @mentioning it using its email (looks like @threadsummarizer).
Go to a Google Chat space with a long thread. Type /summarize (or @bot /summarize). Wait a few seconds — the bot will fetch recent messages and post a concise summary right in the thread.
“✅ Decision: use new logo on homepage. 📋 Action: @mia to export final files by Friday. 📅 Deadline: Friday EOD. Vibe: team excited about the rebrand.”
If something fails, check Apps Script Executions tab for logs.
🧠 pro humanizer prompts (better summaries)
| thread type | prompt add-on |
|---|---|
| brainstorm / ideas | “extract the top 3 creative ideas and any concerns.” |
| decision‑heavy | “list final decisions, who made them, and any unresolved points.” |
| daily standup | “summarize each person’s update, blockers, and what they’ll do next.” |
| support thread | “what’s the main issue, any solutions proposed, customer sentiment.” |
💬 you asked — we answer
callGemini function with a Claude API call (Anthropic). You’ll need to adjust auth.
That’s the sign of a true AI expert. But if your team needs a more robust solution — like a bot that also searches attachments, complies with EU AI Act, or integrates with your knowledge base — our team builds production‑grade agents for US and EU companies.
synoipiss · US efficiency & EU privacy
set up AI agents to automate your emails
The big‑picture guide — compare all methods (no‑code n8n, Make, CrewAI, LangGraph) and choose your path.
→ read the hub →connect Gemini to Gmail
Automatic labels, triage & summaries — using n8n, Apps Script, or Vertex AI.
→ Gemini guide →auto‑draft with Claude + Zapier
Drafts that sound like you — 15‑minute setup, brand voice prompts, saves 10+ hours/week.
→ Claude guide →categorize work vs. personal emails
Copy‑paste universal prompt (98% accuracy) — works with Gemini, ChatGPT, Claude, n8n, Zapier.
→ categorization guide →