Last Wednesday at 7:30am, before anyone was at a desk, a scheduled job on our Mac woke up, pulled 90 days of Search Console data for a client, cross-referenced it against GA4, read the project changelog, and wrote a report.
It found three things worth doing. It found twenty-two things that looked worth doing, and killed them.
That second number is the point. An SEO agent is a program that runs on a schedule, reads your own search and analytics data, works out what changed and why, and proposes specific fixes for a human to approve — and its value is set almost entirely by what it declines to recommend. This post covers how ours is built, the guardrails that keep it away from production, and the unedited numbers from one real run on a client site.
We're not writing it as theory. This agent has been running against a live client for three weeks, and we've included the week where it was partly wrong.
Every SEO agent has the same failure mode: it can't say no
Point an agent at Search Console and ask for recommendations and you will get recommendations. That is the problem.
The data is full of pages sitting at position 8 with thousands of impressions and almost no clicks. To a language model — or a junior strategist, or most SEO dashboards — that pattern reads as money on the table. Page one, high visibility, nobody clicking: obviously the title and meta description need a rewrite. That's a "quick win," and you can generate forty of them in a minute.
Here are two from this client's data. The query "how often do appraisals come in low": 3,121 impressions at an average position of 8.6, zero clicks. And "sell my house fast": 2,081 impressions, position 9.9, zero clicks.
Any tool would flag both as opportunities. Our agent killed both, and it was right to.
Why those impressions weren't real
Two checks explain it.
The first is a correlation. Over 90 days, this site's daily clicks and daily impressions move together at r = 0.34. Healthy sites run above 0.6. When clicks and impressions stop tracking each other, impressions have stopped describing human beings.
The second is the device split. On the Queens city page: 2,287 desktop impressions against 23 mobile. On Albany: 3,127 desktop, 91 mobile. Real people searching "we buy houses queens" are on a phone, in a kitchen, looking at a house they need to get rid of. A 99-to-1 desktop skew on a local-intent query isn't an audience. It's rank-tracking software and bots, logged by Google as impressions.
So the agent is sitting on a pile of quick wins that are statistical ghosts. If it reports them, two things happen and both are expensive.
You spend a week rewriting titles for traffic that was never going to arrive. Then, when the rewrites move nothing, you stop trusting the report. That second cost is the real one. An agent that cries wolf every week gets ignored, and then you're paying a subscription and still flying blind.
Which is why "how many recommendations did it find" is a terrible way to evaluate an agent for SEO. The number you want is precision, not recall.
How we built the SEO agent: four layers
The design principle is that the language model does judgment and nothing else. It never does arithmetic, and it never touches a website.
- A scheduler. A macOS
launchdjob fires every Wednesday at 7:30am and reports on the previous Monday–Sunday. It holds the machine awake while it runs and sends a desktop notification when it finishes, pass or fail. - Python scripts that own all the math. One pulls Search Console across three windows (7 days vs prior 7, 28 vs prior 28, 3 months vs prior 3). One pulls GA4 organic sessions, key events and converting landing pages. One draws the charts. They write JSON. The reporting step that runs afterward is explicitly forbidden from recomputing a single delta — if a number is in the report, a script produced it.
- A skill holding the judgment rules. This is the actual intellectual property: a few hundred lines specifying how to classify a mover (ranking change vs CTR change vs demand change), what disqualifies a finding, and the hard cap on how many items it may propose.
- Notion as the approval queue. Every finding becomes a work item with status
Proposed. Nothing is implemented by the thing that found it.
The split between layers 2 and 3 matters more than it sounds. Language models are unreliable at percentage change and genuinely good at "these three queries all sat at position 8, vanished in the same week, and the page was last updated a year ago." Give each part the job it's actually good at.
The validation gate that runs before any comparison
This is the part most tools skip, and it's the cheapest thing you can add.
Before the agent compares a single number week over week, it reads the correlation figure and sets a flag: Healthy or Weak impression signal. On this client it's weak, so the report leads with clicks, labels every impression, CTR and position change as low confidence, and says so once, in plain language, at the top.
From there, four exclusion rules fire before it may propose anything:
- Inflated impressions are not a CTR problem. When the signal is weak, a page with 1,000+ impressions at position 10 or better and CTR under 0.2% is noise, not opportunity.
- Desktop-heavy impressions are not demand. If a finding rests on impressions, check the device split. Over 80% desktop with near-zero clicks means trackers.
- A URL plus a tracking parameter is not cannibalization.
/long-island/and/long-island/?utm_campaign=gmbare one page — the second is just the Google Business Profile link. Strip tracking parameters before comparing. - A CTR win needs real clicks. The "500 impressions at position 8–15" trigger only counts if the page already earns at least five clicks in 28 days.
Everything the rules kill gets written into the report under a heading called Killed theories, each with the rule that killed it. We read that section first. It's where we find out whether the agent is thinking or pattern-matching, and it's the section we'd hand a skeptical client.
An agent you can't audit is a consultant you can't fire.
What one real week of the agent looked like
Leave the Key Homebuyers buys houses in Long Island, Queens and Brooklyn. Their organic traffic is a mix of high-intent local landing pages and a large informational blog. Here's the week of September 28 to October 4, unedited.
The surface read was good: 113 clicks against 83 the week before, up 36%. First up week since August. A dashboard would have shown green and stopped there.
The agent led with the part that wasn't green. Over 28 days, clicks were down 20% (371 vs 466). Over three months, down 32% (1,499 vs 2,188). The weekly line since mid-August reads 140, 91, 83, 88, 87, 83, 113 — one good week inside a sustained decline.
Then it localized the damage to two pages and classified each by cause rather than lumping them together.
A senior-housing guide: 73 clicks → 24 over 28 days. Position held steady at about 11. Impressions fell from roughly 1,100 a week to 550, and the main query's CTR fell from 3.6% to 1.1%. Steady rank with collapsed CTR and impressions means the results page changed around the post, not that the post lost rank. The agent said exactly that, and flagged its own explanation as a guess rather than a finding.
A rent-to-own guide: 24 clicks → 2. This is the catch we care about. The page's average position barely moved, 10.48 to 10.56, so a page-level report shows nothing wrong at all. Underneath, three separate queries that had been sitting around position 8 dropped out of results entirely. Those were mobile clicks, so they were real people. The post was last updated in October 2025.
And the honest footnote, which it surfaced without being asked: organic leads were flat. Eight key events over 28 days against eight the period before, 26 against 27 over three months. Several hundred lost clicks had cost this client zero leads, because the losses were in informational blog traffic rather than on the pages that convert.
That last fact is the difference between a report and a dashboard. It moves the recommendation from "emergency" to "fix the content decay, and stop worrying."
Three items went to Notion. One was a title and meta-description fix on a post holding position 9.85 with 2,457 impressions and a 0.49% CTR against the roughly 1.8% expected at that position — and no meta description on the live page at all, so Google was auto-generating the snippet. Real position, real clicks already, genuine gap. That one passed every rule.
It also noticed a post that had jumped to 8 clicks by ranking first for "flushing meadows corona park bag policy," and logged it as off-topic traffic with no lead value instead of celebrating a win.
Across the three weeks it has been running, 27 approved items have shipped. Six queries on money pages — the city landing pages that actually produce leads, not the blog — have moved into the top three results. That's a small sample over a short window, and we'd treat any causal claim about three weeks of SEO with suspicion. But it's the right direction, and it came from a handful of deliberate changes rather than forty speculative ones.
Why this SEO agent lives in a GitHub repo
There's a reason to build a GitHub SEO agent rather than buy a dashboard, and it isn't ideology.
Every part of this is a text file under version control. The judgment rules are a skill in a repo. Each client is a single JSON config: thresholds, which GA4 events count as leads, the canonical URL, and a content_rules block of client-specific facts the agent must respect.
That block is load-bearing. For this client it encodes that call tracking masks the phone number, so differing numbers across pages are expected and must never be flagged as an error. It also encodes that the brand never states a number of days to close, so any page copy promising "as little as 7 days" is an accuracy defect to fix rather than a conversion opportunity to copy.
Encode a client's reality once and every future run inherits it. That compounds, and it's the thing no generic tool can do for you.
Because it's in git, we can diff what the agent believed in August against what it believes now, roll back a rule that made it noisy, and show a client the exact reason a recommendation appeared. Try getting that out of a dashboard.
The guardrails, because it runs unattended
An agent with write access to a production website while you're asleep isn't an asset. It's a liability with a cron schedule. This is also the objection every client raises first, so it's worth being specific.
- The reporting agent cannot write to the site at all. It runs with an explicit allowlist — read Search Console, read GA4, read two WordPress endpoints, write files, write Notion — and a blocklist that denies every edit, create, publish and plugin call by name, even where a broader rule would have allowed it.
- Implementation is a separate, human-triggered job. We approve items in Notion first. Only then does a different skill run, and before it saves anything it confirms it's pointed at the environment named in the client config rather than whatever happened to be configured last.
- Every change is reversible. Pre-edit values go to a backups folder, the change goes in a changelog, and the Notion item records what shipped and when.
- It cannot nag. Anything already proposed — including items we rejected — is blocked from reappearing. A page changed in the last 42 days is off-limits because it's too early to measure. A rejected item can't return for 180 days, and only then if the numbers have clearly gotten worse.
- It has a hard cap. Five critical items per week, maximum. Zero is an acceptable answer, and some weeks it's the right one. Everything else goes on a watch list with no work item attached.
This is the same structure we use whenever an automated system touches something that matters: narrow permissions, a human gate on anything irreversible, and a log that lets you prove what happened. It's less about AI than about building a revenue engine that survives due diligence.
What the agent can't do
Three things, so you can judge it fairly.
It can't see competitors right now. Semrush is disconnected for this client, so the report says exactly that in one line instead of guessing.
It can't explain brand demand. This client's branded query is down from 83 clicks to 63 over three months while holding position 1.1. That isn't an SEO problem — something changed in offline marketing or the Google Business Profile. The agent identifies it as outside its scope and hands it to a human, which is the correct answer.
And it can't beat small samples. One landing page went from 4 leads to 0 on one to three sessions. It put that on the watch list and refused to recommend anything, which is right and deeply unsatisfying.
None of that makes it less useful. It makes the things it does say worth reading, which is the only metric that matters for something you have to trust at 7:30 on a Wednesday morning.
If you're considering an agent for SEO
The build isn't the hard part. Scheduling a job, calling two APIs and writing markdown is a weekend's work. The hard part is the judgment layer: knowing that a 99-to-1 desktop skew means bots, that a stable average position can hide three queries falling off a cliff, and that an agent proposing thirty fixes is worth less than one proposing three.
That knowledge doesn't come from the model. It comes from having been wrong about search data before and encoding what you learned somewhere it can't be forgotten.
Which is the same job we do for revenue systems generally: take the judgment that currently lives in one person's head, write it down as a system, and hand over something that runs without them. An agent is just a particularly literal version of that.
If you'd rather not build one, this is what our done-for-you SEO agent does on a client site every week — the same architecture described above, with the audit, the fix and the approval queue included. If you'd sooner see the numbers first, the engagement pricing is published.
And if your growth still depends on remembering to check things, the agent isn't the constraint. That is.
FAQ
What is an SEO agent?+
An SEO agent is a program that runs on a schedule, pulls your own search and analytics data, decides what changed and why, and proposes specific fixes for a human to approve. It differs from an SEO tool in that it reaches a conclusion instead of handing you a dashboard, and from an AI writing tool in that its output is a diagnosis, not content.
Can an AI agent do SEO without a human?+
Parts of it, safely. Pulling data, classifying what moved, and drafting the exact change are a good fit for an agent. Deciding whether a change is worth making, and publishing it, should stay with a person. In our build the reporting agent has no write access to the website at all; implementation is a separate job we trigger after approving the item.
Is it safe to give an SEO agent access to my website?+
Only with an explicit permission model. Ours runs with an allowlist of read-only data sources plus file and Notion writes, and a blocklist that denies every edit, create, publish and plugin call by name. Implementation is a separate job we trigger after approving the item, and it checks it is pointed at the environment named in the client config before it saves anything.
How is an SEO agent different from a tool like Semrush or Ahrefs?+
Those tools are the data layer and are very good at it. They tell you a page has 2,400 impressions at position 10. An agent adds the judgment layer: whether those impressions are real users or rank-tracking bots, whether the drop is a ranking loss or a change in the results page, and whether it is worth your week. In practice you want both.
How long does it take to build an SEO agent?+
The plumbing is a weekend: a scheduled job, two API clients, and a reporting step. The judgment rules are the real work and they are never finished. Most of ours were written after the agent confidently recommended something wrong and we had to encode why it was wrong.