← Systems

AI Automation

Scout

Turn useful public GTM signals into a visible queue without automating the human relationship.

My role
Owned the signal-to-review operating model, its human-action boundary, and the decision to withdraw it
Maturity
Withdrawn 2026-09-16. Live verification 2026-08-28, invalidated by a source-policy change 2026-09-14.
Decision
When the source said no, withdraw the system rather than re-engineer around the control.
Boundary
Scout could not post, comment, connect, or message. A person decided what happened next, and that boundary held until the end.

6

Reusable Workflows

Withdrawn

Status

2026-09-14

Source Blocked

2026-08-28

Live Verification

On 2026-09-14 Scout's only automated source began refusing it. Every request to the three public HubSpot Community RSS feeds returned 403, and the site's robots.txt carried Disallow: /c/*.rss, which is the exact path shape Scout fetched.

Two independent signals, pointing the same way: automated access was not wanted.

Scout had worked. It was verified working on 2026-08-28 with live requests against those feeds, and the record of that run is still in the repository. Seventeen days later the same requests were refused.

I withdrew it. The repository carries a dated withdrawal notice, the releases are retitled, the template published to a public workflow library has been removed at my request, and no fix is pending. This page is kept at its original URL because the README and the postmortem both point here.

The alternative was available and I want to name it plainly, because the whole value of this record is that the alternative was available. Rotating user agents, routing through a residential proxy, scraping the HTML instead of the feed, or simply ignoring a file that has no legal force would each have restored the data. Any of them would also have been a decision to treat a clear signal as an obstacle. The system's entire premise was respecting a boundary between automated preparation and human action. A system built on that premise cannot route around a boundary the moment one costs it something.

How the failure was actually found

The discovery is the useful part, and it took three steps. None of them was the step I expected.

The error named the wrong component. Scout's daily run had been failing, and the thrown error came from the Parse XML node. Parse XML was fine. Fetch RSS had been returning 403 for every feed for at least ten days, and because that node was configured with onError: continueRegularOutput, it forwarded the error items downstream, where the XML node rejected them for lacking a data property. The node that threw was three steps from the cause.

That error handler was a deliberate choice, made so one dead feed would not take down the run. What it actually did was convert a total outage into a misleading error about a different component, and it hid the outage for at least ten days. Error handling that degrades instead of failing loudly moves the blame. It does not reduce the damage.

The 403 was not a bot-detection problem. My first reading was that this was a challenge to work around with headers. The response carried cf-mitigated: challenge, which supports that reading. Then I read robots.txt, which nobody had checked during the original build, and found the path shape disallowed explicitly.

That is the finding that settled it. One signal is a configuration you might be on the wrong side of by accident. Two aligned signals are an answer.

The verification had an expiry nobody had written down. Scout's live verification was real. Dated 2026-08-28, live requests, real feeds, recorded check by check. Nothing was fabricated and nothing was skipped. It was also a dated observation about a third party that was free to change its mind, and it was being presented as a property of the system.

A test count implies a permanent property. What Scout had was a measurement with a shelf life. That is the single most portable lesson here, and it is why every maturity line on this site now carries a date and names what would invalidate it.

The question the original review never asked

The build process asked whether the request succeeded. It never asked whether the request was permitted.

Those are different questions and only one of them was in the process. A 200 response tells you a server answered. It tells you nothing about whether the operator of that server wants to be fetched on a schedule by a system they have never heard of.

Scout's own documentation half-knew this. The source policy said the availability of an RSS feed is not permission for every downstream use, and the release rejected adding a different feed URL without a separate access-policy review. The principle was written down and the check that would have enforced it was not run.

What Scout was

Six n8n workflows forming one operating loop. This describes the system as it ran until 2026-09-14; step 1's automated source is blocked and the loop no longer runs end to end. Manual intake was always a supported path and is unaffected.

  1. Capture: Read three public HubSpot Community RSS feeds, or accept a signal entered manually. The RSS path has returned 403 since 2026-09-14.
  2. Reduce: Remove old posts and posts without a RevOps keyword before sending anything to a model.
  3. Qualify: Ask Claude to classify the remaining signal by warmth, persona, track, pain area, and response angle.
  4. Map: Store qualified signals in a Notion database with a next action and a draft response.
  5. Maintain: Fill missing drafts and move a signal forward when an engagement notification is recognized.
  6. Report: Prepare stale-work nudges and a weekly scorecard for the operator.

Scout architecture showing HubSpot Community RSS and manual intake feeding validation and Claude qualification, with qualified signals stored in Notion and a human review boundary before any action.

Every workflow imported inactive and without credentials. The dashed line in the diagram is the product boundary: everything above it prepared work, everything below it required a person.

The deterministic reduction layer mattered more than the model call. Filtering by age and keyword before qualification meant the model saw a fraction of the volume, which is the same principle every other system on this site is built on: the model goes where judgment is required, and a rule decides everything a rule can decide.

The human boundary held for the life of the project. Scout could not post, comment, connect, or message. It prepared work in Notion and stopped. That was true in the first version and it was true on the day it was withdrawn, and it is the reason the withdrawal was a decision about data access rather than about damage already done.

The failure before the failure

Two weeks before the source closed, a different failure changed how the project verified anything.

The first real n8n sandbox run failed before making an external request. Scout used JavaScript's URL constructor to validate and clean links. The offline test harness supplied that global, so 322 tests passed. The target n8n 2.36.8 Code sandbox did not supply it. Workflow 01 could not start, Workflow 02 rejected valid URLs, and Workflows 03 and 06 silently removed every link from their digest output.

The tests were not false. They were faithful to the wrong runtime.

The fix replaced the unavailable global with a dependency-free HTTP URL parser inside each affected Code node. The more important half was that the harness stopped injecting capabilities the target sandbox does not have, and regression checks then ran inside a real n8n Code node.

That failure produced the release standard: static structure, clean import, offline behavior, target-sandbox behavior, and live external-service behavior recorded as separate dimensions, because one passing result cannot stand in for another.

It is worth noticing that this lesson and the one that ended the project are the same lesson at two different scales. A test that passes in the wrong runtime, and a verification that passes on the wrong date, are both a measurement being read as a property.

Verification, separated by dimension

The release recorded ten checks on 2026-08-28. Eight passed and two were never performed. One of the eight, live RSS retrieval, has failed since 2026-09-14. The original results are left in place rather than restated: they were real on the date they were taken, and that is the point this page is making.

CheckStatus
Static validationPassing
Clean import into n8n 2.36.8Passing
Offline Code node executionPassing
Target-sandbox URL regressionPassing
Live HubSpot Community RSS retrievalPassed 2026-08-28. Failing since 2026-09-14 (403, and robots.txt disallows the path)
Live Anthropic classification and draftingPassing
Live Notion creation and updatesPassing
Computed digest contentPassing, nothing sent
Email deliveryNot done
Gmail notification triggerNot done

Read the complete verification record.

The release boundary

The public repository contains inactive, credential-free templates. Instance and workflow identifiers, credential references, active-state metadata, environment-specific values, and recipient addresses were removed before a workflow could become a reusable artifact.

Private operational exports stayed outside Git. Sanitized derivatives were rebuilt with deterministic template identifiers and passed through structure validation, a public-export scanner, tests, and current-tree and history scans. The released repository began as a clean public snapshot rather than carrying private development history forward.

That was less convenient than uploading the original JSON. It was also the only release boundary that matched the claim being made, and it is the reason the withdrawal was straightforward: there was a clean public artifact to annotate, and nothing private to retract.

What was never verified

Scout never delivered an email to a real inbox. Workflow 04 never reacted to a real Gmail notification. Workflows 02 through 06 were never imported separately through the Editor UI. Nothing ran on a schedule or in production. Cost per run and setup duration were never measured.

Those were accepted limits of the release, and they are stated here as limits rather than as things the ending excused.

What this record demonstrates

The engineering is ordinary enough: six workflows, a deterministic reduction layer, a schema, a review boundary, and a release process that kept private operations out of a public repository.

The part worth showing is what happened when the system's premise was tested against its own convenience. Scout's premise was that automation prepares and a person decides. When the source withdrew permission, the cheapest reading was that a 403 is a technical problem with technical answers. Taking that reading would have kept the system running and quietly converted it into the thing it was built not to be.

There is a version of this project where the feeds still work, nobody asks how, and the case study is about throughput. This is the other version. For the kind of work I want to do, it is the more useful one to be able to show, because the judgment it records is the part that does not transfer from a tutorial.

Repository and technical artifacts

The repository is MIT licensed and remains public as an engineering record. It includes all six workflows, setup documentation, the Notion schema, synthetic fixtures, validation tooling, and the decision log behind the release and the withdrawal.