Exponential Operator is a 100% human-written newsletter by Sawyer Middeleer, founder of Revi Systems. If you were forwarded this email, join some of the sharpest AI operators by subscribing here:

Hi all,

Everyone starting a business confronts the question of “how do I get more customers?”

You have two options, really. Either they come to you or you go to them.

The former requires an audience of people receptive to the value you provide (what I’m trying to cultivate here to some extent). The latter is all about reaching the right people with the right message, at the right time.

Reaching the people you want to do business with sounds simple, but is actually really hard to do well.

Low-quality automation has flooded inboxes with spam, making it nearly impossible to get someone’s attention. Even if you cut through the noise, more likely than not your offer isn’t compelling enough or the timing is wrong.

This all means that for better or worse, sales outreach is a numbers game, best fought with data and automation. Sounds easy, but unfortunately the best sales tech is way beyond the budget of my little solo operation.

So I did what any good AI operator would do and decided to build my own growth operating system with Claude Code. It was surprisingly hard to make and I’m quite happy with where it’s at one week in.

In the spirit of building in public, I’ll walk through exactly what I built, how and why.

As I described in a prior post, I like starting any AI project with a specific problem to solve. In this case, there were 3:

  • I want AI to automate the process of finding and emailing prospects who are the best fit for my services, right at this moment

  • Each piece of this workflow needs to be orchestrated by an AI agent autonomously, only involving me to review messages before they’re sent

  • The automation needs to be reliable - no accidental CRM overwrites, no messy or duplicated data, and no major action taken without my approval

After about 20 minutes of planning with Claude I landed on an architecture that looks like this:

There’s a lot going on so I’ll break it down:

The AI agent on the left - Claude Code or OpenClaw etc - serves as the intermediary between me and the system. I want to be able to tell my agent what to do and it’ll do it, and have the agent report to me when something needs my attention.

The GTM system on the right is built around 3 main pieces

Declarations

These are files that describe the target state and other configuration details of each node within my GTM system. Basically they tell the agent: whenever you touch this tool, you need to make sure you use these exact settings, otherwise you’ll break something.

This is great because it gives the AI free reign over the system within well prescribed guardrails. Take this declaration for a person object in my CRM, for example:

object: person
name: Person

fields:
  - name: email
    type: string
    required: true
    unique: true
    attio: { slug: email_addresses, type: email-address, multiselect: true }

  - name: first_name
    type: string
    required: true
    attio: { slug: name, type: personal-name }

  - name: last_name
    type: string
    required: true
    attio: { slug: name, type: personal-name }

  - name: description
    type: text
    attio: { slug: description, type: text }
    
...

It tells my AI what a “person” is supposed to look like in my CRM - what data is available, and what data is not. If the AI tries pushing data that doesn’t look exactly like this, it will throw an error and tell it to stop. The AI can still update my CRM structure, but it will always have to preview the before-after result before any real change goes through to minimize risk of error.

Providers

A provider is just an integration with an external tool - a CRM like HubSpot, a sequencer like Instantly, or a data source like Apollo. They live separately from the main automation engine and can be easily added or removed without changing anything else about how the system works.

While it was more work to build out a separate provider layer, it was worth it because now I can experiment freely. Every time I want to add a new tool or data source, all I need to do is have Claude write a new provider - that’s it. The more complex and hard to modify logic within the automation engine itself can remain unchanged.

Automation Engine

This is the meat of the system, where most of the business logic lives. It has modules that orchestrate every step in the sales process, from prospect discovery to data enrichment and outreach sequencing.

It’s decoupled from both the declarations and the providers, which means it’s totally indifferent to what tools I use or what specific campaigns I’m running. For example, the engine knows I have something called a CRM, but it doesn’t know or care whether I’m using Salesforce or HubSpot or something else.

And because all the complex logic lives here, separate from the declarations interface, the AI agent running my campaigns doesn’t have to know how it works at all. The major benefit here is in context management.

It’s super inefficient for Claude to have to read through my codebase every time it wants to do something simple like enrich a list and start a sequence. All Claude has to do with my system is learn what settings it should put in the declaration and that’s it.

Finally, an interesting discovery I made along the way:

Turns out hiring signals are pretty much free because all the major ATS's expose public API endpoints. As long as you know the company's url slug you can plug into their job board like an RSS feed

It took me like 3 minutes and $0 to build a daily alert that tracks postings from ~800 companies

That’s all for today. Thanks for reading!

江湖再见🫡

-Sawyer

Keep Reading