mech.app

The mech.app newsletter

Agentic AI, minus the noise.

Get practical field notes on AI agents, automation, developer tools and security delivered to your inbox.

No spam. Unsubscribe anytime.

Automation

Loop's Warm Intro Tracker: CRM State Management and Follow-Up Notification Boundaries

How Loop's warm intro tracker exposes stateful follow-up automation challenges: polling vs webhooks, notification timing, and multi-system reconciliation.

Source: getlooped.cc
Loop's Warm Intro Tracker: CRM State Management and Follow-Up Notification Boundaries

Loop is a warm introduction tracker that watches email threads and follows up weeks later to ask what happened. You CC loop@getlooped.cc on an intro email, and the service checks back with both parties after a delay. The product pitch is simple, but the plumbing underneath exposes a cluster of stateful automation problems: how do you track multi-party workflows across systems you don’t control, when do you send notifications without spamming, and what happens when email state conflicts with CRM state?

This is not a CRM. Loop positions itself as a “quiet companion” with no signup, no inbox access, and no database you have to populate. That constraint forces interesting architectural choices about state inference, notification scheduling, and privacy boundaries.

State Model for Multi-Party Workflows

A warm intro has at least three actors: the introducer, the person being introduced, and the recipient. Each actor can respond (or not) at different times, creating a partial-update problem. Loop needs to track:

  • Intro sent: timestamp, participants, thread ID
  • Response from party A: detected or inferred
  • Response from party B: detected or inferred
  • Follow-up scheduled: when to check in
  • Follow-up sent: timestamp, delivery status
  • Outcome reported: meeting scheduled, deal closed, no response

The state machine is simple in theory but messy in practice because Loop has limited observability. It sees only the emails where it was CC’d. If the introducer forwards the thread without CC’ing Loop, or if the parties move to Slack or a calendar invite, Loop loses the thread.

Detection Strategies

Loop has three options for detecting progress:

  1. Email polling: parse replies in the thread where Loop was CC’d
  2. Calendar webhooks: watch for meeting invites between the parties
  3. CRM sync: pull status updates from Salesforce, HubSpot, or Attio
  4. Manual input: ask the introducer to report back

The Show HN post and landing page suggest Loop uses email-only detection. No signup means no OAuth flow for calendar or CRM access. That limits Loop to inferring state from email metadata: reply count, participant list changes, and thread activity timestamps.

Notification Timing and Throttling

Loop waits “a few weeks” before checking in. That delay is a design choice with trade-offs:

Timing StrategyProsCons
Fixed delay (e.g., 14 days)Simple to implement, predictableMisses fast-moving intros, annoys slow ones
Adaptive delay based on reply velocityMatches natural cadenceRequires more state, harder to explain
User-configurable delayFlexibleAdds UI complexity, breaks “no signup” model
Event-driven (trigger on thread silence)TimelyNeeds continuous email polling, higher cost

Loop appears to use a fixed delay. The landing page says “a few weeks later” without qualification. That keeps the state model simple: one scheduled task per intro, no dynamic rescheduling.

Throttling is the other half of the problem. If Loop checks in too often, it becomes spam. If it checks in too rarely, the introducer forgets the context. A reasonable heuristic:

  • First check-in at 14 days
  • Second check-in at 30 days if no response
  • Stop after two attempts

Loop’s privacy model (no persistent user account) makes it hard to implement per-user throttling rules. The service has to decide globally or infer preferences from reply behavior.

Privacy and Access Control

Loop’s “no signup, no inbox access” constraint is a privacy feature and an architectural constraint. Without OAuth, Loop cannot:

  • Read the full email thread (only messages where it was CC’d)
  • Access the introducer’s calendar
  • Write to the introducer’s CRM
  • Authenticate the introducer’s identity

That means Loop must treat every CC as an ephemeral permission grant. The email address loop@getlooped.cc becomes the access token. If someone CC’s Loop on a sensitive intro, Loop sees it. If they forget to CC Loop on a follow-up, Loop loses visibility.

The privacy boundary is the CC line. Loop can only act on data explicitly shared with it. That’s cleaner than asking for inbox access, but it creates gaps. If the introducer wants to revoke access, they stop CC’ing Loop. There’s no admin panel to delete data because there’s no account to log into.

Conflict Resolution Across Systems

When email state conflicts with calendar state or CRM state, someone has to decide which source is authoritative. Loop sidesteps this by only using email. But if you wanted to build a more robust version, you’d face:

  • Email says no reply, calendar shows a meeting: trust the calendar
  • CRM says deal closed, email thread is silent: trust the CRM
  • Calendar invite was sent but declined: ambiguous, needs human input

A full-featured intro tracker would need a reconciliation layer that merges signals from multiple sources and flags conflicts for manual review. Loop avoids this complexity by staying email-only, but that limits its ability to detect outcomes.

Implementation Sketch

A minimal Loop-style service needs:

# Simplified state machine for intro tracking

from dataclasses import dataclass
from datetime import datetime, timedelta
from enum import Enum

class IntroState(Enum):
    PENDING = "pending"
    RESPONDED = "responded"
    FOLLOWED_UP = "followed_up"
    CLOSED = "closed"

@dataclass
class Intro:
    thread_id: str
    introducer: str
    party_a: str
    party_b: str
    created_at: datetime
    state: IntroState
    last_activity: datetime
    follow_up_scheduled: datetime | None

def should_follow_up(intro: Intro, now: datetime) -> bool:
    """Decide if it's time to check in."""
    if intro.state != IntroState.PENDING:
        return False
    if intro.follow_up_scheduled and now >= intro.follow_up_scheduled:
        return True
    # Default: follow up 14 days after last activity
    return (now - intro.last_activity) >= timedelta(days=14)

def update_from_email(intro: Intro, email_metadata: dict) -> Intro:
    """Infer state changes from email replies."""
    if email_metadata["reply_count"] > 0:
        intro.state = IntroState.RESPONDED
        intro.last_activity = email_metadata["last_reply_at"]
    return intro

The real implementation needs:

  • Email ingestion: SMTP server or Gmail API webhook
  • Thread parsing: extract participants, timestamps, reply count
  • Scheduled tasks: cron job or queue (Celery, Temporal, Inngest)
  • Notification delivery: send follow-up emails via SMTP or SendGrid
  • Deduplication: avoid double-sending if the introducer CC’s Loop twice

Observability Gaps

Loop has no way to know:

  • If the intro led to a meeting (unless someone replies to tell it)
  • If the parties moved to Slack or text
  • If the introducer manually followed up without CC’ing Loop
  • If the email was marked as spam

These gaps are inherent in the “no signup” model. You can’t instrument what you can’t see. The trade-off is simplicity and privacy at the cost of completeness.

A more invasive version would ask for:

  • Calendar read access: detect meetings between intro parties
  • CRM write access: log intro attempts and outcomes
  • Inbox read access: parse the full thread, not just CC’d messages

Each permission expands observability but increases friction and privacy risk.

Technical Verdict

Use Loop’s architecture when:

  • You want minimal user friction (no signup, no OAuth)
  • Your workflow is email-native and users already CC stakeholders
  • You can tolerate incomplete state (some intros will fall through the cracks)
  • Privacy and simplicity matter more than comprehensive tracking

Avoid this pattern when:

  • You need authoritative state across email, calendar, and CRM
  • Users expect real-time notifications or adaptive timing
  • The workflow involves more than three parties or complex branching
  • You need audit logs or compliance-grade data retention

Loop’s design is a good example of constraint-driven architecture. By refusing to ask for inbox access, it forces a simpler state model and clearer privacy boundaries. The cost is observability. You can’t track what you can’t see, and you can’t see what users don’t explicitly share.

For warm intro tracking, that trade-off works. For more complex workflows (deal pipelines, multi-stage approvals, compliance tracking), you’d need richer integration and a more sophisticated state reconciliation layer.