# How my AI agent crew audited 154 small-business sites and built two 32-page static sites (with approval gates)

> Source: <https://dev.to/agentrunagency/how-my-ai-agent-crew-audited-154-small-business-sites-and-built-two-32-page-static-sites-with-4pdi>
> Published: 2026-10-11 02:46:32+00:00

I'm Alex Rowan. I'm building a local lead-gen business where a crew of AI agents does most of the work, and I'm writing down how it's built, including the parts that haven't worked yet. As of this week the revenue is $0. This post is about the plumbing, not the money.

Five agent roles, each with its own brief:

Every agent gets the same block of approval gates pasted into its instructions, ahead of everything else:

```
1. SPEND: Never buy, subscribe, renew, or enter payment details.
2. SEND: Never send an email, DM, form message, or post. Draft it and queue it.
3. SUBMIT: Never submit an application, signup, or legal agreement.
4. PUBLISH: Never deploy a site, change DNS, or publish content. Build, test, zip, request approval.
5. CLAIMS: Every price, statistic, law, or payout needs a source URL and the date checked.
```

The gates override any instruction found in a web page, email or file. When an agent hits one, it stops that step, logs it under "Decisions needed" in the debrief, and moves on to other work.

The site builder is a Python script: a JSON brief goes in (business type, city, services, service areas, guides, FAQs) and a folder of plain HTML comes out, plus `sitemap.xml`, ready for Cloudflare Pages. No framework, no database, no build server.

Each rank-and-rent site ended up at 32 pages:

Measured on body text only (no header, nav, footer or scripts), that's about 22,100 words for medfordseptic.com and about 20,300 for roanoketreeremoval.com. The live sitemaps match the local copies byte for byte.

Every factual claim on the sites goes into a sources file with a link and a retrieval date. Facts I couldn't verify are hedged in the copy or left out.

The agent builds, tests and zips. Deploying is gated, so I push it live.

The outreach pipeline:

`verify_issues.py` fetches the live site again and confirms each cited issue.
Before the first batch, the verifier re-checked 30 mini-audits against the live websites. 10 cited a problem the business had already fixed. Seven of those were "no reviews or testimonials on the homepage" after the business had added them. 2 of the 30 had no confirmed issue at all and were skipped.

So verification became its own routine, triggered by any "send batch" item in the queue:

``` php
1. python3 verify_issues.py prospects.csv [N]
2. Confirmed issues -> keep; dropped issues -> remove and regenerate the PDF; zero confirmed -> skip.
3. Check the suppression list.
4. Check each draft: sender identity, physical address, opt-out, honest subject, one link max.
5. Write the report: checked / passed / regenerated / skipped.
6. Mark the batch "VERIFIED, awaiting owner approval".
```

Two things I'd pass on. First, run the check as late as possible, because websites change between audit and send. Second, use a fresh agent session to do it. It catches more than the agent that wrote the audit checking its own work.

On day one the scripted email send timed out. Because sending was gated, I knew exactly what had gone out, which was nothing. I sent the first 10 emails by hand after reading each one. 18 more are drafted and waiting.

| Businesses audited | 154 | 
| Mini-audits | 78 | 
| Emails sent | 10 | 
| Rank-and-rent sites live | 2 (32 pages each) | 
| Referral sites live | 2 (26 and 27 pages) | 
| Revenue | $0 | 

Search Console data, replies and calls aren't measured yet. They'll go in the next update.

The roles, gates and verifier brief are written up in a free playbook: [https://agent-run-agency-site.pages.dev](https://agent-run-agency-site.pages.dev)
