The problem this solves
Every customer you close is still in the prospecting audience until somebody removes them, and somebody rarely does. The warehouse knows who converted yesterday; the ad accounts find out weeks later, after the account has seen a month of acquisition ads and the account manager has heard about it.
The fix is a nightly loop from the warehouse to the audiences: new customers land on a suppression list, the audiences built from list <name> are rebuilt as the list minus the suppression, and the result is refreshed on LinkedIn and Meta. Each step is a CLI call, so it runs from cron, from your scheduler or from the warehouse's own job runner, and the audience refresh is approval-gated the way every push to an ad account is.
Done this way, suppression stops being a quarterly cleanup and becomes a property of the audience: whoever the warehouse calls a customer at 03:00 is excluded by the time the ads spend at 09:00.
How the mission runs
- Read the warehouse export. The job starts from the CSV your warehouse writes nightly, with a column for the customer's domain or email and a date column. The Audience Agent's recipe reads only rows dated since the last run, so the file can be a full export and the job still processes only what is new.
- Add new customers to suppression list <name>. The new rows go into suppression list <name> through the CLI call that adds rows to a list from a file. Domains are normalized and deduplicated first, so the same customer arriving as an email one night and a domain the next is one row. The list lives in your workspace, so this write lands immediately and shows up in the audit trail.
- Rebuild the audience source. The audience source is list <name> minus the suppression list, matched by domain and by email. The job recomputes the difference every night rather than editing the audience in place, so a customer added to suppression is gone from the source the same night, and a company that churns later can be re-added by removing it from suppression.
- Refresh the LinkedIn and Meta audiences. The audiences command refreshes the matched audiences built from that source on the connected LinkedIn Ads and Meta Ads accounts, hashed and shaped the way each platform expects. Because this writes to an ad account, the refresh is staged for approval: the command returns an approval id, and the audience updates once someone approves it in the console or in Slack.
- Report the result. After approval the platform reports each audience's size as the ad platform matched it, and the job prints the count of customers suppressed tonight, the audience sizes and the credits metered, so a one-line summary can go to a channel or a log.
- Schedule it. The cron line runs the job after the warehouse export lands, with the key read from an environment variable and minted for this job alone. Exit code 0 means every step ran, 1 means an API or run failure and 2 a usage error, so a missing export or a revoked key alerts rather than quietly leaving the audiences stale.
The prompt
This is the exact objective the agent receives. Swap the obvious placeholders for your own domain, segment or channel and run it as-is from the console, Slack, or the API.
What comes back
The CLI commands for each step, the cron line, and a wrapper that reads the warehouse CSV, pushes new customers into suppression list <name>, rebuilds list <name> minus suppression and refreshes the LinkedIn and Meta audiences from it with an approval id on each refresh. Every morning the audiences exclude everyone the warehouse called a customer the night before, the sizes are reported as the platforms matched them, and the audit trail shows what changed and what it cost.
Make it yours
- Add Reddit to the refresh, or write Google, TikTok, X and Pinterest export files to a folder for the platforms you upload to by hand.
- Suppress open opportunities and current partners from a second warehouse export, so the same job keeps three exclusion sets current.
- Run it as a platform schedule instead of cron when you would rather not keep a machine of yours awake for it; the approval step is the same.
- Post the nightly summary to #paid-media with the approval link, so whoever runs the accounts approves from the same message.
Frequently asked questions
Why is the audience refresh gated when the suppression push is not?
The suppression list is data inside your workspace, so writing to it is an internal change recorded in the audit trail. The refresh changes an audience inside your ad accounts, and every write to a connected CRM, outreach tool or ad account waits for a person, by design.
How are customers matched to the audience?
By domain where the platform matches companies and by hashed email where it matches people. A customer row with only an email is resolved to its domain through the enrichment waterfall, so the person and their company are both excluded.
What if the warehouse export is late?
The job reads rows by date since the last run, so a late file is picked up the next night without gaps, and the run that found no file exits non-zero so you know it happened. Nothing is refreshed from a missing file.
Does the audience shrink over time?
It shrinks by the customers you win and grows by whatever refreshes list <name> adds. Because the source is recomputed each night rather than edited in place, the audience always equals the current list minus the current suppression, with no drift to reconcile.