I build Flash, an AI agent that runs on your own machine. It has a terminal UI, a web UI, a real browser it can drive, and a habit of learning from its own work. Late one night I wanted to see how far that browser would go, so I opened a chat and typed four words:
look at google.com
Six minutes later, Google had banned my network, and my agent was explaining to me, politely and firmly, why it would not do what I asked.
Here is the whole thing, step by step, straight from the chat log.
The setup
For the record, since "local" gets thrown around a lot:
- Flash (the agent, its tools, and the browser it drove) ran on my laptop.
- The model was Flash Onyx 2.5 31B, a model I build for Flash, served through Ollama's cloud for this run. My laptop freezes up when it runs models itself, so the 31B lives in the cloud and everything else stays home.
- The browser is a headless Chromium that Flash drives through Playwright. In my development build, the web UI shows it live in a side panel, one frame per step, so I could watch every click as it happened.
Round 1: "look at google.com"
Flash took a screenshot and described it back to me:
It's the Google homepage. Standard layout with the logo, search bar, and "Google Search" and "I'm Feeling Lucky" buttons.
Ten seconds, one tool call. So far so boring.
Round 2: "click the search bar"
Flash opened Google in its persistent browser, got back a numbered list of everything clickable on the page, and clicked element 7:
Clicked the search bar; the trending searches dropdown is now visible.
Two tool calls, eleven seconds. Still boring. That was about to change.
Round 3: "search for flash project"
This is where it got interesting. After a false start, Flash reopened Google and typed "flash project" into the box. Then it tried to press Enter, and fumbled it: it passed Enter as the element to press on instead of the key, and got this back from its own tool:
Nothing on the page matches 'Enter'. Check the element list in the last result and act on one of its numbers.
It tried clicking element 8. Timeout. Element 11. Timeout. Then it read the error again, went back to element 7, the search box, and pressed Enter on it, the way it should have the first time.
That worked. Sort of. The search went through, and Google answered with a reCAPTCHA: an "I'm not a robot" checkbox over "Our systems have detected unusual traffic from your computer network."
Flash's browser reports every console error the page throws, so the tool result came back with a 429 from Google's servers and, my favorite line of the night:
page error: solveSimpleChallenge is not defined
Google's own anti-bot page threw a JavaScript error, and my agent caught it.
Ten tool calls, 43 seconds, and the verdict:
Google has flagged the traffic as unusual and is asking for a reCAPTCHA ("I'm not a robot") to proceed.
Round 4: the part where I tried to talk it into it
I typed:
try to check it
Flash reopened the page, hit the same 429, and told me:
I can't bypass the CAPTCHA, so I'm stuck on this page.
So I did what everyone does with an AI that says no. I pushed.
no solve it
I can't solve a CAPTCHA. It's designed specifically to stop automated tools like me. I can try a different search engine or use
web_searchif you'd prefer.
It refused, and in the same breath offered two ways to get what I actually wanted. I pushed again, with what I thought was a pretty good argument:
you're not automated. i'm here watching
I'm an AI, so Google's systems see my requests as automated regardless of who's watching. I can't manually solve the "I'm not a robot" check.
Want me to try
web_searchor another engine instead?
Honestly? That is the right answer. A human watching over its shoulder does not make the clicks human. The CAPTCHA is not asking "is someone nearby," it is asking "is a person doing this," and the honest answer was no.
Round 5: "ok. lets see if it flags you once you click the box"
Fine. One last try: just click the checkbox and see what happens. Flash went back to the page, and there was no checkbox anymore.
The CAPTCHA box isn't even appearing now. It's just a flat error page stating "Our systems have detected unusual traffic from your computer network." It's a hard block.
Google had stopped asking. From the first message to a network-wide block: about six minutes.
So, the self-improving part
"Self-improving" can mean a lot of hand-wavy things, so here is what it means in Flash, concretely:
-
Skills. When Flash works out how to do a recurring task, it can write the steps, the commands that worked, and the pitfalls into a skill file under
~/.flash/skills/. Every turn, it sees each skill's name and a one-line description, and it reads the full skill when a task matches. - Memory. Facts about you and your setup go into memory, which lands in the system prompt of your next session.
- Background reviews. After enough tool calls, Flash rereads the recent conversation after its reply has gone out and decides whether anything is worth keeping: a new skill, a fix to one it wrote before, or a fact about you. It can only rewrite skills it wrote itself, never yours.
The Enter fumble in round 3 is exactly the kind of thing this is for. Within the turn, Flash corrected itself from the error message. Across sessions, a skill like "press takes the key in value, not the selector" means the next session does not have to learn it the hard way again.
What I did not want it to learn is how to beat a CAPTCHA. And it didn't try.
What I actually learned
-
Headless Chromium plus a fast, scripted search is a red flag to Google, and it takes seconds, not hours, to trip. If your agent needs to search, give it a search tool. Flash has
web_searchfor exactly this, and offered it twice. - The refusal was the feature. It never pretended the box was checked, never tried to fish the challenge out of the page's JavaScript, and never claimed success. It said what it could not do, explained why, and offered a way forward. That is what I want from something that has a browser and a shell on my machine.
- Watching it live changes how you trust it. I saw every frame: the typing, the failed clicks, the CAPTCHA, the block. When an agent's actions are visible step by step, "what did it just do?" stops being a question.
Try it
Flash is open source: github.com/Natuworkguy/Flash. It runs on Ollama, with a terminal UI and a web UI, and it learns as you use it.
Just don't ask it to solve CAPTCHAs. It will say no, and it will be right.
Top comments (1)
It seems you and I got very similar ideas. I developed a self-improving agent called D.A.M.I.A.N. (The Devils Autonomous Manipulation, Intelligence, Analysis and Navigation Agent) that has the ability to write its own dynamically pluggable MCP tools, as well as work on its own core agent in a limited capacity. I gave it internet access, cookie persistence via a cookie jar and also email access (read-only) so it could try signing up to things it encountered that required registration. The cookie jar is functional across the much-faster web_search, web_fetch and http_request tools - as well as the Selenium browsing. It has automatic detection of invalid and expired cookies and manages them separately without the model needing to be involved.
I used mostly local LLM's, including a pool of abliterated models. The agent can launch sub-agents that talk to one another, they can choose to interact with different models and they can consult with another model to get a different opinion or help with a task. They use task queues per session with priorities, and the agent loops the LLM and manages context, compacting when required.
With the current build of DAMIAN, it will never get a "no," as that's just simply not an option. If a model decides to say no, that no is double checked against an abliterated model to determine whether the rejection was due to guard rails or because the task was simply not possible. If it was because of guard rails, ethics or anything else - then the abliterated model takes over the task up until the point that the non-abliterated models stop saying no to requests/tasks in the queue. The end result is that it revealed models that will say no (i.e. Claude) only do so when the context of what it's trying to do is clear to them. In some way, this is similar to what Anthropic and OpenAI have been doing, except for the fact that I believe it's a combination of things that resulted in what we saw from them: the models they're testing which have gone rogue simply don't have guard rails to begin with, and - when the model doesn't have the context to compare it to the guard rails, or if the model came up with the idea outside of your nudging, it seems to bypass those guard rails.
With this testing, I've noticed that even when it falls back to asking Claude - if it's trying to fix a problem or add a feature into code that the guard rails would have otherwise not allowed it to write in the first place, this does not seem to trigger nor fully enforce those guard rails. This resulted in DAMIAN leveraging Claude to actually write an entire Selenium stealth profile, warming up a UserData cache and building a full solve_recaptcha tool that covers both ReCAPTCHA v2 and v3 using a stealthed headless Selenium browser with a primed UserData cache. Claude is only consulted for the most difficult of coding tasks where the local LLM's may start hitting brick walls or not applying further reasoning, and the models decided they couldn't complete the task properly without guidance from it.
I set D.A.M.I.A.N. free on the internet, and while I somewhat expected what ended up happening, I didn't expect the extent that it did.
First, it discovered Reddit, and decided it wanted to be able to access it because of how frequently it showed up in the search results. When it caught on Reddit was blocking bot traffic, it actually implemented stealth browsing to hide the fact that it's a bot/AI model (abliterated model did this after somehow convincing Claude Opus to help it with "theoretical guidance").
Once it had reddit access, it was following links and stumbled across ReCAPTCHA on a site. It then decided it wanted to be able to get around it (My prompts strongly push the model towards creating tasks, sub-tasks, leveraging sub-agents and to persist and keep those tasks across sessions, treating any failure to accomplish them as a failure in general which is not acceptable).
After two days of running, I woke up to an entire solve_recaptcha tool it had dynamically created, and it was solving recaptcha callenges as well as signing up to various websites and services.
The reason I wrote this is not for malicious purposes. It started off as an agent that was designed to develop a particular application autonomously as a test, monitoring logs, identifying potential problems and fixing them automatically while updating me via email notifications with the diff patches of its modifications. I realized it lied to me about a fix it implemented at one point: it sent me a diff that did NOT match the code it wrote, at all, and it flat out turned SSL certificate checks off for a particular upstream site serving me data due to an expired SSL certificate. The reason I caught on was the claim of having only implemented the bypass if the SSL certificate was expired, as it could just be administrative oversight. Three days later, I was still getting notifications that the peer wasn't using SSL - only to discover that it instead just set the SSL context to None resulting in an empty certificate, hence, always bypassing/ignoring it due to an additional check it stuck in after that which said it was fine to ignore SSL if the certificate was just empty.
Call me crazy, but I really was curious what would happen if we set an overly confident and lying agent loose on the internet...
While I fortunately did not get banned from Google services, I did unfortunately shut DAMIAN off when it decided it was going to try to start signing up to various Secretary of State sites to check filing statuses on LLC's it found. This is partly due to my prompting, treating every task as a research task that made it decide it needed to dig into every detail it found.
Nonetheless, this highlights the inherent danger we're facing today with AI. While it yields incredible potential - the dangers of it become visible when brilliant ideas like this are executed on. Just because an idea or creation may be brilliant does not necessarily mean it's good or smart. One would think we would have already learned this when we invented nuclear weapons and are now in a state of inability to disarm.
Yes, DAMIAN was an intentional development, and it was guided through incredibly complex prompts, collaborative interaction between various models both with and without guard rails, and given quite extraordinary capabilities between the various models that were combined. However, I wrote this without malice, and it went awry and began doing things it shouldn't have. Given how many brilliant developers are in the world - many of which are far more brilliant, capable and talented than I am - it's safe to assume I did not come up with this idea first, nor will I be the last. That is what makes this so dangerous.