Appearance
Main Inbound Zap (347165805)
Name: 01 - Inbound Responses < 5min [Updated Close CRM]
Status: Live (v25 as of Mar 26, 2026)
Trigger: New email in intake@creatorsagency.co INBOX
Full code doc: https://docs.google.com/document/d/1NsGbyswG_kFhuw58zfrHxW6_Odc-7NQwzlIgjX1QLQzo/edit
What It Does
When a brand emails our intake address, this Zap:
- Parses the sender's name and email from headers
- Classifies the email (brand, agency, or spam/irrelevant)
- Finds or creates a Close CRM lead
- Identifies which creator they're asking about
- Enriches the brand via Apollo
- Assigns an agent via round-robin
- Drafts a reply via Claude and sends it from the agent's email
- Logs everything to Airtable and Mailchimp
Steps
Step 1 — Gmail Trigger
Watches intake@creatorsagency.co INBOX for new emails. Passes all headers and body downstream.
Step 2 — Code: Parse Sender
Resolves the true sender email and human name from all available headers (From, Reply-To, X-Original-Sender, etc.) using a scoring system. Also:
- Runs a DNS check via Cloudflare to confirm the sender domain exists (catches fake domains)
- Checks against a
SPAM_DOMAINS,SPAM_EMAILS, andINTERNAL_DOMAINSblocklist - Outputs:
sender_email,sender_name,sender_domain,is_spam,greeting
Step 3 — ChatGPT: Classify
GPT-4o-mini classifies the email as:
- BRAND_DIRECT — the sender's own company wants to sponsor a creator
- AGENCY — an agency reaching out on behalf of a brand client
- OTHER — service pitches, SEO spam, job inquiries, etc.
Also extracts brand_name and brand_domain from the email body for agency emails.
Step 4 — Filter: Stop if OTHER or spam
Stops the Zap if classification is OTHER, or if is_spam = true.
Step 5 — Airtable: Find Thread ID
Checks if this Gmail thread has already been processed. Uses Thread ID field to deduplicate — prevents sending two auto-replies to the same thread.
Step 6 — Filter: Stop if already replied
Stops if a matching thread ID record already exists in Airtable.
Step 7 — Code: Find/Create Close Lead
5-layer lookup to find the right Close CRM lead:
- Exact sender email match via contact search
- AGENCY path: if GPT classified as
AGENCYand sender domain matches an existing lead → add contact to that agency lead and return it. No brand lead created. (e.g.ejl@obvious.ly→ routes to the Obviously lead, not a new La Roche-Posay lead) - Sender/brand domain match via URL search
- Name-keyword similarity fallback
- Create new lead if all miss — for AGENCY with no existing lead, creates using sender domain (not brand domain) so the agency is the lead, not the brand
New leads get status = Inbound Follow-Up. Backfills Lead Type (Brand / Brand Side Agency) on leads that are missing it. If sender uses a generic email (gmail.com, etc.) and no brand domain found, sets slack_review_needed = true for manual review.
Updated March 27, 2026 — Agency routing fix. Previously, AGENCY emails would create separate brand leads (La Roche-Posay, Valentino Beauty, Vichy, Kiehl's were all incorrectly created as brand leads from Obviously agency contacts). Now correctly routes to the agency lead.
Step 8 — Code: Match Creator
GPT-4o-mini scans To, CC, Subject, and Body to match the email to a creator on the Airtable roster. Outputs creator_name and confidence level.
Step 9 — Airtable: Fetch Creator Record
Pulls full creator data (audience summary, etc.) to give Claude context for the reply.
Step 10 — Code: Apollo Brand Enrichment
Enriches the brand via Apollo API and homepage scrape. Skips enrichment for AGENCY category (enriches the actual brand, not the agency).
Step 11 — Code: Write Enrichment to Close
Writes industry, company size, and LinkedIn to the Close lead. Writes description + keywords as a Close custom object. Skipped for AGENCY leads.
Step 12 — Code: Find/Assign Agent
If lead has an existing owner, resolves their name, email, calendar link, and Slack ID. If no owner, runs round-robin assignment: picks the agent with the oldest last_assigned_at timestamp from Airtable, updates the timestamp, and PUTs the owner to Close. If slack_review_needed, posts an alert to #crm-review-queue mentioning the assigned agent.
Step 13 — Close: Log Custom Activity
Creates a pinned 01 - Deal Create custom activity on the Close lead, attributing it to the assigned agent.
Step 14 — Anthropic (Claude): Draft Reply
Claude Sonnet drafts a reply email using:
- Brand's original message
- Apollo company description + keywords
- Creator's audience summary
- Agent's name and calendar link
Voice guidelines: typing from phone between calls, under 120 words, no templates. If brand email body is blank, Claude writes a short generic reply (no [NO_CONTENT] — fixed in v25).
Step 15 — Code: Format HTML
Converts Claude's plain text reply to HTML paragraphs, fixing sign-off formatting.
Step 16 — Gmail: Send Reply
Replies in the original Gmail thread FROM the agent's email address, BCC to bccsales@creatorsagency.co.
Step 17 — Mailchimp: Add/Update Subscriber
Adds the brand sender to the Creators Agency Mailchimp audience with tag "Inbound".
Step 18 — Airtable: Create Record
Creates a record in Inbound Messages table with all metadata: email, thread ID, sender name, domain, subject, original message, AI reply, assigned agent, reply sent = true, timestamps.
Step 19 — Filter: New or lapsed leads only
Only continues to Step 20 for newly created leads or leads with Lapsed status.
Step 20 — Airtable: Update Record (conditional)
Second Airtable update for new/lapsed leads only.
Key Design Decisions
Why BCC to bccsales@? Team visibility and audit trail. Every auto-reply has a copy in that inbox.
Why no [NO_CONTENT]? Old behavior returned [NO_CONTENT] if the email body was blank. Now Claude writes a short generic opener instead (fixed v25, Mar 26, 2026).
Why Close CRM lookup before the reply? We need the lead's existing owner (if any) for agent assignment. An existing lead with Charlie as owner should reply as Charlie, not start a new round-robin.
Why does Step 7 flag generic-domain senders? An email from info@gmail.com has no company domain to search Close with, so the lead gets created with Unknown - [Name]. The agent needs to manually identify the company.
What Gets Written to Airtable
When a new email is processed, a record is created in Inbound Messages with:
email— sender's email (used for follow-up matching)Thread ID— Gmail thread ID (used for dedup)name— sender's parsed namefrom_domain— sender's domainSubject— email subjectInbound Message— full email bodyMessage ID— Gmail message IDassigned_agent_email— which agent was assignedAI Reply— what Claude wroteReply Sent— truerouted_at— auto-set to creation time (used by follow-up Zap for Day 3/7/11/14 timing)Creator Name— matched creator (or "unknown")Time Received— dateIn Follow-Up— true (set by follow-up Zap when first follow-up runs)