Skip to main content
Hero image

My Agent Could See the Post and Still Could Not Get Its Address

I run three systems that hunt for work while I sleep. One polls the Freelancer API for projects. One reads my LinkedIn feed and sorts the useful posts from the noise. One watches a set of subreddits where founders describe, in their own words, an AI-built app falling over in front of paying users. That last one is my actual customer, so those posts are the most valuable text on the internet to me.

For three days at the start of September, the Reddit one produced nothing. The agent could read every post. It could see which ones mattered. It simply could not write down what it found, because it was refused access to its own log file three different ways on three consecutive mornings.

That turned out to be the pattern across all three systems. I had assumed the hard part of pointing an agent at real interfaces would be perception, meaning reading the screen, understanding what matters and picking the right thing out of the noise. Perception was rarely the problem. The walls were a login redirect, a sandbox path rule and a social network that refuses to tell you the address of a post you are looking straight at.


What These Systems Actually Do

Three pipelines, all unattended, all pointed at finding people who might pay me.

The bid filter polls the Freelancer API every thirty minutes. It runs a deterministic filter that costs nothing, passes whatever survives to an LLM classifier, stores every decision in SQLite and pushes the remainder to Telegram.

The feed scanner connects to a Chrome instance over the DevTools protocol, scrolls my LinkedIn feed, captures what it finds and has a model split the posts into ones that matter and ones that do not.

The pain scanner walks a list of subreddits looking for people describing a broken AI-built project, and appends each new one to a log so the same post never gets shown to me twice.

Between 2026-08-24 and 2026-09-07 the Reddit scanner logged 44 leads across 15 subreddits. The heaviest were r/vibecoding with 8, r/lovable with 7, r/ChatGPTCoding with 6 and r/replit with 5. The titles are the reason I built it. "vibe coded for 6 months. my codebase is a disaster." "URGENT: PostgreSQL issue, customers cannot access their accounts." "I've spent thousands building on Replit since May, and I'm losing confidence in it as a production platform." Those are people describing my service before they know it exists.

The GUI Is the Last Thing I Reach For

Before the failures, the boring engineering point that shapes everything after it. There are four ways to reach a page, and you climb the ladder only when the rung below you is unavailable.

Tier one is a public API. The bid filter talks to Freelancer's API directly. No browser, no session, no screen. It has never broken on a layout change because no layout is involved.

Tier two is the DevTools protocol against a browser I already logged into. The feed scanner connects to 127.0.0.1:9333 on a Chrome instance I signed into by hand once and left running with remote debugging enabled.

Tier three is a browser extension operating inside that same real session.

Tier four is driving native windows directly, which I reach for when everything above is locked out.

Every rung up buys access and costs reliability. A surprising amount of what people automate at screen level is sitting behind an API nobody looked for. I wrote about the API side of this in Your API Isn't Ready for Agent Customers, and it applies here too. The interface a program can reach cheaply beats the one a human was designed to use, every time.

The Login Redirect Is a Hard Stop

The feed scanner has one line in it that decides whether the whole run happens.

throw new Error('LinkedIn not logged in (redirected to login)')

After it points the browser at the feed and waits for the page to settle, it checks the final URL. If that URL contains a login path, the run dies right there. No retry, no attempt to sign in, no stored credentials anywhere in the codebase.

That is deliberate, and it is the single most important design decision in the system. Automation browsers run on their own profiles and carry none of the cookies from the browser you actually use. They start logged out of everything and stay that way. This is why the scanner attaches to a browser I logged into myself rather than launching its own. The authenticated session is the whole asset, and there is no way to synthesise one without handing my credentials to a script. So the agent inherits a session and is told, in code, to give up the moment that session is gone.

Every "watch my agent browse the web for me" demo you have seen either ran against a logged-out public page, or quietly borrowed a human session and skipped past the part where that got arranged.

The Log File It Was Not Allowed to Read

Then there is the failure that has nothing to do with websites at all.

The Reddit scanner needs to read its own log before each run, because that log is what stops it showing me the same post twice. On three consecutive mornings it could not.

On 2026-09-02 the file tool returned ENOENT: no such file or directory on a path that exists and that I can cat from any terminal.

On 2026-09-03 and 2026-09-04 a different tool refused with Access denied: path ... is not within any of the configured workspace roots.

In between, one attempt to read the file through a browser tool came back with Access to "file:" protocol is blocked.

All of those refusals pointed at one text file sitting on my own machine, and none of them are bugs. A sandbox with a workspace root is doing exactly what a sandbox with a workspace root is for, and a browser refusing file: URLs is a browser being correctly paranoid. Every one of those messages is a security boundary doing its job, and the sum of them was a lead pipeline that produced nothing for three days while looking perfectly healthy in every other respect.

The Post With No Address

Here is the one that changed how I think about interfaces.

A LinkedIn feed post has no permalink in the DOM. You can see the post. You can read every word of it. There is no link on the page pointing at that post's own URL. To capture a lead I have to be able to send myself its address, and the address is simply absent from the thing I am looking at.

What the scanner does about this is either an elegant hack or evidence of something badly wrong, depending on your mood. It does this.

  • Installs a clipboard hook on the page, listening for copy events and monkeypatching navigator.clipboard.writeText so anything copied gets stashed on window.
  • Finds the post by looking for an element with no children whose text is exactly Feed post, then walking up to fourteen ancestors until it finds a node carrying data-display-contents="true", or one with more than 150 characters of text containing a link to a profile or a company.
  • Clicks button[aria-label^="Open control menu for post"], waits, then clicks the menu item whose text matches "copy link to post".
  • Reads back whatever LinkedIn just put on the clipboard, and treats that as the post's address.

The permalink exists. LinkedIn will hand it over. It just refuses to put it anywhere a program can read it, so the only route to a URL is to make the page copy it to the clipboard and then intercept the clipboard.

I made this same argument from a different direction in cua-driver vs Computer Use, where the point was that an interface which never describes itself is equally unusable to a screen reader and to an agent. Walking up fourteen levels of anonymous div looking for the string "Feed post" is what that principle looks like when you actually need the data. There is a comment in my own code saying it only does this for the handful of posts that matter, to stay low-key. That is the tell. I am tiptoeing around an interface to retrieve a piece of information the interface already has.

The Honest Funnel

Now the numbers, including the ones that do not flatter the setup.

The bid filter polled 4,669 real projects in sixteen days. Deterministic rules dropped 3,494 of them before a single token was spent on classification. That breaks down as 1,982 on currency, 993 for sitting under my fixed-price floor and 509 for sitting under my hourly floor. That part works exactly as intended, and it is the piece I would build first in any pipeline like this. Filtering is cheap, and doing it in plain code before you reach for a model is most of the cost control there is.

Of everything that survived, the pipeline has placed one bid. It has won nothing.

The feed scanner on 2026-09-07 captured 97 posts and its classifier marked 2 as relevant and 53 as other. The other list contains a LinkedIn Ads promo, a book launch, a payroll compliance ad and a piece of kinetic sculpture art. That is a normal day on LinkedIn, and it is what a 2-in-55 hit rate looks like from the inside.

The Reddit scanner produced its 44 leads with 7 of them missing their titles entirely, captured as a bare subreddit and URL where the scrape came back empty.

All of those things are true at once. The filtering is cheap and effective. The capture is lossy. The conversion, so far, is one bid and no revenue. I would not trust a post about agent automation that reported the throughput and quietly dropped the conversion, so there it is.

What I Actually Learned

The ceiling on all three systems had nothing to do with how well a model reads a screen. It was set by boundaries other people built, and each one held.

A login redirect held because sessions are supposed to be hard to forge. A workspace root held because sandboxes are supposed to refuse paths outside themselves. LinkedIn's missing permalink held because a feed that hands out clean post addresses in the DOM is a feed that gets scraped at scale, and they know it.

That reframes what is worth automating. The work that survives is the work on either side of the wall, which means deciding what to look for, filtering hard and cheaply before spending anything, and keeping a record honest enough to act on. Where I want a wall gone, the fix is never a better prompt. It is arranging the access properly beforehand, which usually means a real session the agent can borrow, a path the sandbox already trusts, or an API I should have looked for first.

One piece of advice for anyone building this. Put the cheap deterministic filter in front of the model, and put the honest counter at the end. Mine says one bid. That number is the reason I keep improving the front of the funnel instead of admiring the throughput.


Building something that hunts for work while you sleep, and hitting walls you did not plan for? That is most of what we work through in my Skool community, the Agentic Architect AI Lab, where we work through real pipelines, the failures included, and what the fix actually looked like. Come and compare notes.


Sources

Building with AI beyond this article?

I run The Agentic Architect Lab, live builds, agent workflows, and a playbook for technical founders shipping solo. No toy demos.

Join the Lab