
Your AI Sales Agent Only Works in One Channel. That Is a Problem.
Most AI sales agents live inside a chat widget. A lead visits your site, has a great conversation, gets qualified, receives a confirmation email, and then... replies to that email. The reply goes to a human inbox. The AI agent never sees it. The conversation thread breaks. The lead waits hours or days for a response that the AI could have handled in seconds.
We had this exact problem with Vector, our 12-dimensional AI sales qualification agent. Vector was excellent at qualifying leads through the chat widget. But every confirmation email we sent had replyTo: lloyd@pixelmojo.io, meaning replies bypassed Vector entirely. We were leaving money on the table.
So we fixed it. In a single Thread-Based Engineering session, we extended Vector from a chat-only agent to a multi-channel system: chat, email replies, broadcasts, and full delivery tracking. Here is exactly how we did it, what architecture decisions we made, and how TBE made it possible in one session instead of a sprint.
The Architecture Before: One Channel, One Bottleneck
Vector's original architecture was a single API route handler at /api/chat. It did everything: session management, spam detection, conversation analysis, emotional intelligence, system prompt building, OpenAI API calls with function calling, lead qualification scoring, email notifications, analytics tracking, and operational pattern detection.
All of this lived in roughly 1,100 lines of a single file.
The system worked well for chat. But it was a monolith. Adding email as a second channel would mean either duplicating all 1,100 lines (with divergent maintenance) or refactoring the core intelligence into a shared module.
What we were missing
Before this session, our email infrastructure was fire-and-forget:
- Confirmation emails sent with no delivery tracking
- No idea if emails bounced, opened, or got marked as spam
- Lead replies went to a human inbox, breaking the AI conversation thread
- No broadcast capability (product updates required manual work)
- No contact management (leads existed in Supabase but not in our email platform)
The TBE Session: Thread Classification
Thread-Based Engineering classifies work into seven thread types based on complexity and required autonomy. Before writing any code, we mapped the session:
| Task | Thread Type | Autonomy Level | Why |
|---|---|---|---|
| Webhook delivery tracking | B-thread (Base) | In-the-loop | New infrastructure, needs human approval at each step |
| Contact sync utility | P-thread (Parallel) | On-the-loop | Follows existing patterns, monitor but don't block |
| AI core extraction | P-thread (Parallel) | On-the-loop | Refactor with clear boundaries, validate at end |
| Inbound email agent | C-thread (Creative) | Guided autonomy | Novel integration, periodic checkpoints |
| Broadcast dashboard | F-thread (Fast) | Guided autonomy | Follows established admin patterns |
This classification determined how much supervision each task needed. The B-thread (webhook setup) required approval at every step because it touched production infrastructure. The F-thread (broadcast dashboard) could move fast because it followed patterns already proven in the existing admin pages.
Phase 1: Visibility First (B-Thread)
The first thing we built was delivery tracking. You cannot improve what you cannot measure.
Webhook endpoint with signature verification
We created a POST endpoint that receives events from Resend's webhook system. Every email event (sent, delivered, opened, clicked, bounced, complained) gets verified using Svix HMAC signatures and stored in a new email_events table.
A key decision: we set up six separate webhooks (one per event type), each with its own signing secret. The endpoint tries each secret until one validates. This means a single RESEND_WEBHOOK_SECRETS environment variable holds all secrets, comma-separated.
Admin dashboard
We built an email tracking page at /admin/email-tracking showing:
- Delivery rates, open rates, click rates, bounce rates
- Real-time event timeline
- Per-recipient breakdown
- Bounce and complaint alerts at the top of the page
This gave us immediate visibility into every email Vector sends.
Contact auto-sync
Every new lead from the chat widget, contact form, or Radar beta signup now automatically syncs to Resend as a contact with custom properties: tier (high-value, qualified, early-stage), score, company, source, project_type, and industry. A backfill script (npm run sync:contacts) handles existing leads.
Phase 2: The Core Extraction (P-Thread)
This was the critical architectural move. Vector's AI intelligence was embedded inside the chat route handler. To add email as a channel, we needed to extract it.
What we extracted
We created src/lib/chat/ai-core.ts with a single function:
export async function generateAIResponse(
message: string,
history: Array<{ role: 'user' | 'assistant'; content: string }>,
options: AIResponseOptions
): Promise<AIResponseResult>
This function encapsulates:
- System prompt building with channel-specific additions (email gets a more formal tone)
- Emotional intelligence injection (detected emotions shape the AI's strategy)
- OpenAI API call with function calling for lead capture
- Tool call handling (when the AI decides to save lead data)
- Follow-up response generation after tool calls
What stayed in the chat route
Session management, spam detection, disqualification strikes, trivia mode, analytics tracking, and operational pattern logging. These are chat-specific concerns that the email channel does not need.
The result
The chat route went from 1,100 lines of monolithic logic to calling generateAIResponse() and handling the result. The duplicated save-and-analytics code (which existed for both the tool-call path and the non-tool-call path) was merged into a single shared block.
Both channels now use the same AI brain. When we improve Vector's negotiation patterns, both chat and email benefit automatically.
Phase 3: The Inbound Email Agent (C-Thread)
This is where it gets interesting. When a lead replies to a Vector confirmation email, the system:
- Receives the webhook from Resend's inbound email system
- Verifies the signature using Svix (same pattern as delivery webhooks)
- Fetches the full email content via
resend.emails.receiving.get(emailId) - Matches the sender to an existing lead in the database by email address
- Loads conversation history from the lead's original chat session
- Strips signatures and quoted text from the email body
- Calls
generateAIResponse()with the email body, full history, andchannel: 'email' - Sends a threaded reply with proper
In-Reply-ToandReferencesheaders - Stores both messages in the database with
channel: 'email'
If the sender is not a known lead, the email gets forwarded to founders@pixelmojo.io instead.
Email-specific behavior
When the channel is email, the AI gets additional instructions:
- Keep responses to 2-4 paragraphs (not chat-length)
- Use a professional email tone
- Include a clear call-to-action (book a call, reply with details)
- Sign off as "Lloyd & the Pixelmojo team"
- No markdown formatting
The same Vector brain, adapted for the medium.
Rate limiting
Inbound emails are rate-limited to 5 per sender per hour. This prevents abuse while allowing legitimate back-and-forth conversation.
Phase 4: Broadcast Dashboard (F-Thread)
The fastest phase. We built a broadcast admin page at /admin/broadcasts following the exact patterns from the existing outreach page:
- Segment selector populated from Resend's API
- Subject line input with variable helper buttons (
{{{FIRST_NAME|there}}},{{{RESEND_UNSUBSCRIBE_URL}}}) - HTML body editor with live preview toggle
- Schedule option (send now or pick a date/time)
- Confirmation dialog before sending (shows segment name)
- History table showing all past broadcasts with status
The Resend Broadcast API allows creating and sending in a single call:
await resend.broadcasts.create({
segmentId: selectedSegment,
from: 'Lloyd from Pixelmojo <lloyd@pixelmojo.io>',
subject: 'Your subject here',
html: '<p>Hi {{{FIRST_NAME|there}}}, your content...</p>',
send: true,
})
Combined with the contact sync from Phase 1, this means every qualified lead is automatically reachable via targeted broadcasts segmented by qualification tier.
The Thread Autonomy Progression
What makes this case study a TBE story (not just a feature list) is the autonomy progression:
| Phase | Thread Level | Supervision | What the Agent Does |
|---|---|---|---|
| Webhook setup | B-thread | Human approves every step | Creates tables, endpoints, env vars with human verification |
| AI core extraction | P-thread | Human validates at end | Refactors code, human checks type-check and lint pass |
| Inbound email agent | C-thread | Periodic checkpoints | Designs new system, human reviews architecture decisions |
| Broadcast dashboard | F-thread | Minimal oversight | Follows proven patterns, human reviews final output |
| Email auto-replies (production) | Z-thread | Fully autonomous | Vector handles replies without human involvement |
The progression from B-thread to Z-thread mirrors how trust is built in any agentic system. You start with full supervision, prove reliability at each level, and gradually grant more autonomy. By the end of this session, Vector operates as a Z-thread email agent: it receives replies, generates responses, and sends them without any human in the loop. The governance boundaries (sender verification, rate limiting, known-lead matching) are the quality gates that make autonomous operation safe.
This is the TBE + AXD framework in practice. Thread autonomy levels map directly to user supervision patterns.
Why This Matters for Vector and Hive Clients
For Vector clients
Vector is no longer limited to your website. Every confirmation email, follow-up, and outreach message becomes a potential AI conversation. A lead who engages through chat at 2 PM can reply to their confirmation email at 11 PM and get an intelligent, context-aware response in seconds. The 12-dimensional qualification continues across channels.
For Hive clients
This multi-channel architecture is a preview of what Hive delivers at scale. In this case study, we have four specialized agents working together:
- Chat agent (handles website conversations)
- Email reply agent (handles inbound email replies)
- Broadcast agent (handles targeted outreach)
- Tracking agent (monitors delivery and engagement)
All four share the same lead database, conversation history, and contact sync. They coordinate without stepping on each other. This is multi-agent orchestration: specialized agents with shared context, exactly what Hive provides for organizations with multiple customer touchpoints.
What We Shipped: The Numbers
| Metric | Value |
|---|---|
| Files changed | 26 across 2 commits |
| Lines added | 2,733 |
| New API routes | 6 (webhook, inbound, email-tracking, broadcasts, segments, broadcast history) |
| New admin pages | 2 (Email Tracking, Broadcasts) |
| Database migrations | 3 (email_events, inbound_emails, broadcast_history) |
| Channels supported | 3 (chat, email reply, broadcast) |
| Shared AI core | 1 module used by all channels |
Implementation Checklist: Build Your Own
If you want to replicate this multi-channel pattern for your own AI agent:
1. Extract your AI core
Separate the LLM call logic from channel-specific concerns. Your core function should accept a message, history, and options, then return a response and any extracted data. Both your existing channel and new channels call this function.
2. Set up delivery tracking first
You need visibility before you add channels. Webhook-based delivery tracking (sent, delivered, opened, bounced) gives you the data to evaluate performance.
3. Sync contacts to your email platform
Leads should automatically appear in your email platform with metadata (qualification tier, source, score). This enables segmented broadcasts without manual list management.
4. Build inbound email handling
The key components: webhook receiver, sender verification against known leads, conversation history loading, AI response generation via your shared core, and threaded reply sending with proper RFC headers.
5. Add a broadcast capability
With contacts synced and segmented, broadcasts become a single API call. Build an admin interface so non-technical team members can send targeted emails.
6. Use TBE thread classification
Classify each task before starting. Infrastructure tasks (B-thread) need careful supervision. Pattern-following tasks (F-thread) can move fast. Novel integrations (C-thread) need periodic checkpoints. This prevents both over-engineering simple tasks and under-supervising complex ones.
Multi-Channel AI Agents: Questions Teams Ask
Common questions about this topic, answered.
What Comes Next
The inbound email agent is deployed and ready. Once we activate Resend's inbound receiving (a configuration change, not a code change), Vector will start handling email replies autonomously. The broadcast dashboard is live. The delivery tracking is already capturing events.
The bigger picture: this is how we build every product at Pixelmojo. Thread-Based Engineering for governance. Agentic Experience Design for the user-facing layer. Shared intelligence cores instead of duplicated bots. Progressive autonomy instead of all-or-nothing automation.
If your AI agent only talks through one channel, you are leaving conversations (and revenue) on the table.
Ready to extend your AI agent across channels?
- Vector: 12-dimensional AI sales qualification that works across chat and email
- Hive: Multi-agent orchestration for organizations with multiple customer touchpoints
- Contact Us: Let's talk about your multi-channel AI strategy
