LAB / 01 — PIPELINE TEARDOWN

Nine agents.
One irreversible action.

The B2B outreach pipeline behind Track 01, taken apart agent by agent. Most of it runs unattended. Exactly one step does not, and that choice is the most important design decision in the system.

Python · GPT-4o-mini and GPT-4o · IMAP/SMTP · CRM REST API · ran live Jun–Jul 2026

AGENT 01 / 09 · DATA & ENRICHMENT

Contact Enricher

verify_contact.py · v7–v8.1

Validates and enriches CRM contacts with employment status, tenure dates, and relocation gating. Filters out former employees and irrelevant leads before any outreach begins.

In
CRM contact list (REST API) · company name + job title
Out
Enriched record · employment status flag · outreach-eligible boolean
Model
GPT-4o-mini — date parsing and classification

Eight iterations to get here. Most of that was date parsing: "since 2019", "3 yrs", and an empty field all have to resolve to the same answer.

AGENT 02 / 09 · DATA & ENRICHMENT

Lead Generator

lead_generator.py

Identifies new qualified contacts from maritime and offshore industry sources. Applies domain filters and scores leads against target ICP criteria.

In
Industry domain list · ICP criteria config
Out
Scored lead list · CRM import payload
Model
GPT-4o-mini — ICP scoring

AGENT 03 / 09 · CONTEXT LAYER

Company News Enricher

news_enricher.py

Pulls recent company news from multi-source RSS feeds so outreach can reference something real. Includes a no-news sentinel and a cooldown so stale items are never reused.

In
Contact company domains · RSS feed configs
Out
Recent news digest per company · no-news sentinel flag
Model
None — deterministic

The sentinel matters more than the digest. Without an explicit "no news" value, a personalisation step will happily invent one.

AGENT 04 / 09 · OUTREACH EXECUTION

Cold Email Drafter

email_drafter.py

Writes personalised cold emails and the follow-up sequence — F1, F2, F3 at 3, 7, and 14 days. Applies anti-AI writing rules to keep the tone human, and handles out-of-office detection.

In
Enriched contact · news context · cadence position
Out
Draft email · subject line variants · OOO-aware scheduling
Model
GPT-4o-mini — drafting under anti-AI instructions

AGENT 05 / 09 · THE GATE

Email Dispatcher

email_dispatcher.py

Outbound email is the one action in this pipeline that cannot be undone.

Everything upstream can be re-run. A bad enrichment is a wasted API call; a bad draft is a discarded string. A sent email is a sent email — it is in someone's inbox, attached to a company name, and there is no retraction.

So this is the only step that does not run unattended. Dispatch is orchestrated around a 19:00–22:00 SGT review window: three hours in which a human reads what the model wrote and approves it. Automation handles the other eight agents. It does not handle this one.

In
Human-approved drafts · send schedule · sender identity config
Out
Sent email log · retry queue for failures
Model
None — SMTP with retry, rate limiting, sender rotation

This is the decision I would defend in an interview. Full autonomy was available and technically easy. It was the wrong call, because the cost of a bad send is borne by the recipient and the brand, not by the pipeline.

AGENT 06 / 09 · RESPONSE HANDLING

Inbound Email Logger

inbound_logger.py

Monitors the IMAP inbox for replies and logs every inbound message to the CRM. Normalises email metadata and creates activity records linked back to the originating contact.

In
IMAP mailbox · CRM contact index
Out
CRM activity records · reply thread metadata
Model
None — deterministic

AGENT 07 / 09 · RESPONSE HANDLING

Reply Classifier

reply_classifier.py

Sorts inbound replies into four categories: positive (interested), negative (opt-out), out-of-office, and HITL — meaning the model is not confident and a human decides. Routes each accordingly.

In
Inbound email text · thread context
Out
Sentiment category · HITL flag · routing decision
Model
GPT-4o — the one place the full model is used

A misread opt-out is a compliance problem, not an inconvenience. That is why this single step gets GPT-4o while everything else runs on mini, and why "I am not sure" is a valid output.

AGENT 08 / 09 · RESPONSE HANDLING

Reply Drafter

reply_drafter.py

Drafts follow-ups to positive replies, keeping conversation context and tone guidelines. Anything flagged HITL goes to a human queue instead of being sent.

In
Original thread · sentiment classification · contact context
Out
Draft reply · HITL queue if flagged
Model
GPT-4o-mini — reply drafting

AGENT 09 / 09 · REPORTING & CRM SYNC

Report Builder

crm_report_builder.py

Produces multi-sheet Excel reports with pipeline metrics and AI-written contact summaries, then PATCHes the CRM to update records. Scheduled weekly for management review.

In
CRM data export · pipeline logs
Out
Multi-sheet Excel report · CRM PATCH payload
Model
GPT-4o-mini — contact summaries

Eight of nine agents run on the cheap model. One does not. The split is not about capability, it is about what a wrong answer costs.

DEFAULT · 8 OF 9 AGENTS

GPT-4o-mini

Drafting, enrichment, ICP scoring, date parsing, contact summaries. High volume, and a wrong answer costs one retry.

RESERVED · 1 OF 9 AGENTS

GPT-4o

Reply classification only — the single place where output quality decides routing, and where misreading an opt-out is a compliance problem rather than a wasted call.

Structured outputs enforced with JSON Schema throughout · DuckDuckGo Search and RSS for enrichment · all nine agents in Python.

A motion demo that had to earn its place. The pipeline is a sequence, so a scroll-driven walk is the honest way to show it — and every word here is readable with JavaScript switched off, because a portfolio that hides its content when a script fails is not a portfolio.

← Back to the portfolio

— END OF TRANSMISSION · © 2026 NUR FAJAR —