Support Email Workflow
activeListens for new support emails, searches brain/code for answers, drafts responses, sends to admin via Telegram for approval, then sends email on accept.
Detailed Steps
· 20Received new_support_email event from IMAP trigger. Extract from, subject, body, messageId.
Search workspace brain using keywords from subject and body to find relevant knowledge about the AI Telegram Copier.
Call POST /lookup-by-email on Firebase User Lookup with { email: from } where from is the sender's email from step 1. If 200 (user found), save uid and displayName into context — these identify the user account and can be used to correlate logs, Firestore data, and searches. If 404 (not found), note the email does not correspond to a Firebase user and continue without UID context.
If uid is available from step 3, optionally explore the user's Firestore document for additional context using Firestore Navigator (https://11ec33ab-9dd6-45b0-b385-ab434e894e65.op.munashesydney.com). Call POST /get-document with { path: Users/{uid} } to read the user's profile fields (name, email, subscriptionPlan, freeCredits, subscriptionEndDate, stripeCustomerId, etc.). Call POST /list-collections with { path: Users/{uid} } to discover subcollections (activity, rooms, telegramAccounts, metaApiKeys). If relevant to the support issue, explore further into subcollections like rooms or activity for deeper context. Use all discovered info to enrich your understanding of the user's account state. If uid is not available, skip this step.
Call GET /search on Coolify Logs Watcher with q=[keywords from subject+body] to find relevant error logs from free-copier services. If uid is available from step 3, also search logs that may relate to this user's accounts. Pass results (especially any error patterns, stack traces, or recent failures) into context for drafting the support response.
If brain, Firestore, and log search results are insufficient, call GET /repo/search on Git Code Controller with query composed from subject + body keywords scoped to org:munashesydney. Read relevant files via GET /repo/file to gather context from the codebase.
Compose a helpful draft response addressing the user's support issue. Be specific — reference actual code/config/features from the brain, Firestore data, or log errors found. Keep responses short and conversational. NO markdown (no **bold**, no *italic*, no backticks). NO divider lines like -- or ---. Use human-like natural language — avoid AI-sounding phrases like 'I hope this helps', "Please don't hesitate", 'Rest assured'. Write like a real person would.
Generate a unique emailId (UUID v4).
If you have any extra context, observations, or information you want the admin to know when reviewing the draft (e.g., 'User is on the Free plan, 3 active rooms', 'Found related error logs from yesterday', 'User has no active subscription — may need to check billing'), compile it into a concise aiNotes string. If there's nothing noteworthy, set aiNotes to null/omit it. Call POST /send-draft on Telegram Support Handler with { emailFrom, emailSubject, emailBody: body, draftResponse, emailId, includeButtons: true, aiNotes }. Do NOT pass chatId — the service reads ADMIN_CHAT_ID (8050367545) from its own env vars. Do NOT pass workflowId. When aiNotes is provided, it will appear in the Telegram message as a '📝 AI Notes' section before the draft response, giving the admin valuable context at a glance.
Pending response is stored in Telegram Support Handler's in-memory store at this point (send-draft endpoint persists it).
--- On callback (op.telegram.admin_decision event) ---
Received op.telegram.admin_decision event. Extract eventPayload from the event. The eventPayload contains: action (accept/reject/edit), emailId, chatId, messageId, originalEmail (with from, subject, body, messageId), and optionally aiNotes (any extra context the AI included with the draft). For edit actions, eventPayload also contains adminEditText and originalDraft. Note: edit actions are handled directly by the Telegram Support Handler and NEVER reach this pipeline — only 'accept' and 'reject' actions will appear here.
Call GET /pending-response/:emailId on Telegram Support Handler to retrieve { draft, originalEmail, status, aiNotes }. The response includes emailBody — the original customer email text.
If action is accept: Call POST /send on Email Sender with { to: originalEmail.from.email, subject: 'Re: ' + originalEmail.subject, body: draft, inReplyTo: originalEmail.messageId }. Follow the same tone rules: short, no markdown, no dividers, human-like. Then send confirmation to admin via POST /send-draft on Telegram Support Handler with { emailFrom: originalEmail.from.email, emailSubject: '✅ Email sent', draftResponse: '✅ Email sent successfully!', emailId, includeButtons: false }. Note: no aiNotes needed on confirmation messages.
If action is reject: Send admin a Telegram message via POST /send-draft on Telegram Support Handler with { emailFrom: '', emailSubject: '❌ Rejected', draftResponse: '❌ Response rejected — no email sent.', emailId, includeButtons: false }.
If action is edit: This action never reaches the Events pipeline. The Telegram Support Handler sends the 'Please enter your edit suggestion' prompt directly and registers the chat for edit mode. The admin's revision will arrive as an op.telegram.admin_decision event with action: 'edit'.
--- On edit suggestion (op.telegram.admin_decision with action: 'edit') ---
The admin submitted an edit suggestion via the Telegram Support Handler. You have the following context from the eventPayload: adminEditText (what the admin typed), emailId, chatId, originalDraft (the previous draft), originalEmail (with from, subject, body, messageId), and optionally aiNotes (the extra context from the original draft).
Compose an improved draft response that incorporates the admin's edit suggestion ({adminEditText}) into the response. Use the full context: the original customer email ({originalEmail.body} from {originalEmail.from} with subject {originalEmail.subject}), the previous draft ({originalDraft}), the admin's suggestion, and any aiNotes context. Follow the same tone rules: short, conversational, NO markdown, no dividers, human-like, avoid AI-sounding phrases. If you have updated or additional context to pass along to the admin, compile fresh aiNotes.
Call POST /send-draft on Telegram Support Handler with { emailFrom: originalEmail.from, emailSubject: originalEmail.subject, emailBody: originalEmail.body, draftResponse: the NEW polished draft, emailId, includeButtons: true, aiNotes: newAiNotes if you have fresh context }. This sends the refined draft back to the admin for approval with Accept/Edit/Reject buttons, allowing the cycle to repeat.
Pieces
· 6Event Subscriptions
· 1op.telegram.admin_decision
Emitted when an admin accepts, edits, or rejects a support email draft via Telegram. Payload includes action (accept/reject/edit), emailId, chatId, and context.
Similar Workflows
Weekly Coupon → Friday Email
Runs every Thursday 9am PT. Creates a Stripe coupon with a smart, time-of-year-aware code and discount (1-50%). Then schedules a promotional email via Mautic for Friday at 12:00 UTC using the branded email template.
Post-Purchase Automation
sends post purchase surveys for a company relevant reasons that led to the purchase and can lead to upgrading packages