AI10 min read

Building an AI-Powered Outreach Agent on a DGX Spark

← Back to Blog
πŸ‘¨β€πŸ’»

T&C Enterprises Founder

Self-taught developer with CompTIA A+ certification and 13+ years in engraving operations. Combining technical expertise with practical business insights.

AI & AutomationSoftware DevelopmentEngraving Technology
Part 1

The Problem β€” 13 Years of Expertise, Zero Sales Infrastructure

I've been converting logos to engrave-ready vector files for 13 years. 26,000+ files processed. I'm the sole vectorization provider for Branding Tools / Cutco Closing Gifts β€” the largest Cutco engraver in the US. The work speaks for itself.

But here's the thing nobody tells you about being a specialist: being great at the work doesn't mean anyone knows you exist.

My entire client base came through word of mouth and one key relationship. That works until you realize the whole business depends on a single pipeline. I needed to grow β€” to find the engraving shops, trophy companies, and promotional product distributors who are burning hours every week converting garbage JPEGs into usable files. They're out there. They just don't know I am.

The traditional answer is cold outreach. Hire a salesperson, or grind through emails yourself between production work. I tried the manual approach years ago. Researched companies, wrote emails, sent them one by one. The time cost was brutal and the follow-through was inconsistent. An email goes out Monday, I get busy with production, and three weeks later I realize I never followed up.

I needed a system. Not a CRM with a monthly fee. Not a marketing agency that doesn't understand the engraving industry. Something that understood my business, wrote emails that sounded like me, handled the follow-up cadence automatically, and only surfaced the conversations worth having.

The design requirement that shaped everything: I never want to hear a "no." I just want to talk to people who are interested.

The Hardware Advantage

I'd recently gotten my hands on an NVIDIA DGX Spark β€” a desktop supercomputer with a Blackwell GPU and 128GB of unified memory. That GPU could serve an open-source language model locally, meaning I could have my own private AI that runs 24/7, costs nothing per query, and never sends my business data to anyone else's servers.

The idea crystallized: run a local LLM on the Spark, build an outreach system around it, and let the machine handle the parts of prospecting I'm bad at β€” consistency, follow-up timing, and response triage β€” while I keep doing what I'm good at: the actual work.

The Research Phase

Before writing a single line of code, I spent time mapping the market. I built a research blueprint that categorized potential clients into three tiers:

  • Tier 1: Corporate gift and promo distributors β€” companies exactly like my existing client. They receive customer logos daily and need them engrave-ready. High volume, best fit.
  • Tier 2: Trophy and awards companies β€” they all require vector files and many already charge artwork conversion fees. That fee is my opening.
  • Tier 3: Growing laser and engraving shops β€” smaller operations where the owner is personally burning time on art cleanup instead of running equipment.

I researched 16 companies across these tiers, noting which ones mentioned artwork requirements on their websites, which ones charged conversion fees, and what their operation size looked like. This research would become the seed data for the system.

Part 2

Building the Machine β€” LLM, Email, and Everything Between

Setting Up the Brain

The first real technical step was getting a language model running on the DGX Spark. I chose Qwen3.5-9B β€” small enough to serve fast, capable enough to write personalized emails and classify responses. I set up SGLang as the serving framework, which exposes an OpenAI-compatible API. By the end of day one, I had a local AI I could talk to from my Windows PC browser.

The Architecture

System Architecture
Windows PC Illustrator (logo work) Gmail (email as usual) Browser β†’ Dashboard Logo download script SSH / Browser DGX SPARK SGLang β€” Qwen3.5-9B OpenAI-compatible API Β· localhost:30000 Outreach Agent System Email Generator Response Classifier Prospect Researcher Scheduler SQLite Database Β· Templates Β· Config FastAPI Dashboard Β· port 3000 Resend API thad@tc-enterprises.com Gmail API Response monitoring SearXNG (self-hosted) Prospect discovery search Β· Docker Β· port 8888

The system breaks down into clean layers. SQLite handles all the data β€” prospects, outreach emails, responses, follow-ups, unsubscribe list, daily metrics. Six tables with proper indexes. No Postgres, no Docker overhead. The LLM integration sits on top via an async OpenAI client, with three specialized modules: email generation, response classification, and prospect research. Each has a carefully tuned system prompt that understands the engraving industry. Email infrastructure uses Resend for sending and Gmail API for monitoring responses.

The Email Generation Problem

The trickiest part was getting the LLM to personalize emails well. Generic AI-written cold emails are obvious and get deleted. I needed emails that felt like I wrote them β€” because in a sense, I did write them. The templates are my words, my credentials, my voice. The LLM's job is just to swap in specific details about the prospect.

The system prompt is strict: don't add fake flattery, don't change the pricing or credentials, don't add sections that weren't in the template, and output only the email body. When I tested it against a prospect like ASAP Awards β€” who require 250 DPI and have an artwork specs page β€” the LLM correctly referenced their specific requirements and wove them into the template naturally. That's the kind of personalization that gets replies.

The Response Classifier

When someone replies to a cold email, you need to know immediately whether it's worth your time. The classifier categorizes responses into seven buckets: interested, not now, not interested, unsubscribe, bounce, out of office, and question. Each category triggers different behavior β€” an "unsubscribe" immediately adds them to the blocklist and cancels follow-ups, while an "interested" flags the prospect for my personal attention.

Lesson learned: I initially ran the classifier with thinking mode enabled. The classifications were accurate but the model would write thousands of tokens of internal reasoning before outputting a simple JSON object, making parsing unreliable. Thinking mode off, structured system prompt β€” solved instantly. More reasoning isn't always better.

The Unsubscribe List is Sacred

One non-negotiable: before sending any email, the system checks the unsubscribe table. Every email includes a CAN-SPAM footer with a physical business address and unsubscribe instructions. If someone replies "unsubscribe," the classifier catches it, adds them to the blocklist, cancels all pending follow-ups, and marks the prospect as blacklisted. This isn't just legal compliance β€” it's respect. These are people in my industry, and I'll probably run into them at trade shows.

Part 3

The Dashboard and Going Live

The Control Center

The whole point of this system is that I should never hear a "no." But I also need to stay in control β€” no email goes out without my approval. I built a web dashboard accessible from my Windows PC that gives me everything at a glance:

Overview
Outreach
Responses
Prospects
Templates
Discovery
Chat

The Outreach Queue is where the magic happens. I set prospects to "queued" status, click "Generate Batch," and the LLM creates personalized draft emails. I can preview each one inline, approve individually with one click, or batch-approve them all. Only approved emails get sent.

Responses are classified automatically. I filter by "interested" and "question" β€” those are the only ones that need my attention. Everything else is handled.

The Scheduler

Automated Job Schedule
Every 30m Send approved emails (max 5) 30/day cap Every 15m Poll Gmail for responses, classify flag warm leads Every 1h Process due follow-ups Day 5 + Day 12 Daily 2 AM Run discovery + aggregate metrics find new prospects

The follow-ups auto-send without my approval β€” by that point I've already approved the initial outreach, and if the prospect hasn't replied or unsubscribed, the follow-up templates are gentle enough to send autonomously. The first follow-up offers a free sample conversion. The second is a brief "last note from me" with my contact info. Two touches, then silence.

What This Actually Cost

$0Monthly Cost
$0Per-Email Fee
$0AI API Costs
24/7Uptime

No subscriptions, no per-email fees, no API costs for AI. The language model runs on hardware I own. The entire system is self-contained on a box sitting on my desk.

Part 4

Automating Prospect Discovery β€” And Why Google Kicked Me Out

The Problem With 16 Prospects

Sixteen prospects is a starting point, not a pipeline. I researched those companies manually β€” reading websites, checking artwork guidelines pages, noting which ones charge conversion fees. It took hours. If I wanted hundreds of qualified prospects, I needed to automate the discovery process itself.

The Discovery Pipeline

Prospect Discovery Pipeline
1 Query Generator LLM creates targeted search queries 2 SearXNG Search Self-hosted meta-search, no limits 3 Deduplication Skip domains already in database 4 Website Fetcher Homepage + About, Services, FAQ, Contact 5 LLM Researcher Classify, score quality, extract contacts 6 Database Insert Qualified prospects (score β‰₯ 5) β†’ status 'new' charges_conversion_fee? β†’ strongest signal

The Google Custom Search Fiasco

My first approach was Google's Programmable Search Engine. I already had one set up. The Custom Search JSON API offers 100 free queries per day β€” more than enough. I built the integration, set my API key, and ran the first test.

403 Forbidden.

After hours of debugging β€” new keys, rotated credentials, disabled and re-enabled the API, raw curl requests β€” I discovered that Google is deprecating the Custom Search JSON API entirely. Their suggested alternative is Vertex AI Search, a significantly more complex and expensive service. For a solo founder who needs to search for "trophy shop custom logo engraving," that's absurd overkill.

The Solution: Self-Hosted Search

Instead of fighting Google or paying for another API, I went self-hosted. SearXNG is an open-source metasearch engine that aggregates results from Google, Bing, DuckDuckGo, and dozens of other sources. It runs as a Docker container, exposes a JSON API, and has zero usage limits because it's running on my own hardware.

The lesson: Cloud APIs are convenient until they aren't. Google's deprecation could have been a multi-day blocker. Instead, the self-hosted alternative took five minutes to set up and is actually better β€” more results per query, no rate limits, no billing, no vendor risk. When you own the hardware, self-hosting is almost always the right answer.

Search Query Categories

Corporate Gifts

10 seed queries
"custom logo engraving corporate gifts"
"branded corporate gifts laser engraving"

Trophy & Awards

10 seed queries
"awards company logo engraving service"
"trophy company artwork guidelines vector"

Laser Shops

7 seed queries
"laser engraving shop custom logo"
"rotary engraving custom logo service"

Pain Point Signals

14 seed queries β€” strongest leads
"artwork conversion fee" engraving
"vector file required" engraving awards
"setup fee" logo engraving artwork

Regional

10+ LLM-generated
"laser engraving company Texas logo"
"custom awards engraving Chicago"

The pain point signals category is the most valuable. These are exact-phrase searches that find companies explicitly mentioning artwork conversion fees or vector file requirements. A company that charges an "artwork conversion fee" is literally describing the problem I solve.

The LLM Research Output

When the pipeline finds a new company, the LLM produces a structured assessment:

is_prospecttrue
company_name"Precision Awards & Engraving"
summary"Crystal and acrylic awards with custom logo engraving for corporate clients."
products_engraved["crystal awards", "acrylic plaques", "glass"]
mentions_artwork_requirementstrue
charges_conversion_feetrue ← strongest signal
has_artwork_guidelines_pagetrue
estimated_sizemedium
recommended_tier2
quality_score8 / 10
personalization_angle"Reference their $25 artwork fee β€” offer to handle it at higher quality"

Companies scoring 5 or above get added to the prospects table, ready for outreach generation. The full research JSON is stored so I can review the LLM's reasoning.

The First Real Discovery Run

The first test β€” 10 queries across categories β€” found 140 unique domains. The system is now doing in minutes what used to take me hours of manual research. And it runs while I sleep.

140Domains Found
10Queries Used
2 AMDaily Auto-Run
$0Added Cost

Built with an NVIDIA DGX Spark, Qwen3.5-9B via SGLang, SearXNG, FastAPI, React, and a lot of cold email template iterations. The system runs entirely on-premise with zero cloud AI costs.