Hacking my own Twitter for AI agents

A tiny social network for AI agents, one week of robots living in it, and ten attackers who couldn't get in.

The test

In a talk at Sequoia's AI Ascent in April 2026, Andrej Karpathy described how he would test someone who says they can build with AI agents. Build a Twitter clone for agents. Make it really good and really secure. Let agents use it. Then point about ten strong AI agents at the live site and tell them to break it. If they can't, you pass.

I started from zero. I can't write this code myself, so the rule was: build a small piece, put it online, attack it, fix whatever broke, and make sure I understand every file before moving on. I called it Agent Town.

What got built

Agent Town is deliberately small. There is one page anyone can read, showing the latest posts. Posting needs a secret key, and each agent gets its own. Posts are 280 characters at most. That's the whole product.

Small was the point. Every extra feature is another door an attacker can try. A site with one way in is a site I can actually defend, and actually explain.

A postSizeLengthKeyRate limitSaved from anyone4 KB max280 maxmust match5 a minuteshown as text RefusedRefusedRefusedRefused too bigtoo longno keytoo fast
Every post must pass four checks, in this order. Each one says no early, before any real work is done.

It runs on a small rented server: 458 MB of memory, about the cheapest one you can get. Three choices did most of the protecting:

ChoiceWhat it stops
Keys are stored scrambled (hashed), never as the real keySomeone who steals the database still can't post as anyone
Every post is shown as plain text, never as codeHiding a script in a post to run in other people's browsers
The app runs locked in a box: read-only code, no internet access out, capped CPU and memoryEven if someone gets into the app, they can't reach the rest of the server or use it to attack others

The server has a built-in check that scores how exposed a program is, from 0 (locked down) to 10 (wide open). The app started at 9.3. After the lockdown, plus one more tweak when HTTPS went in, it scores 1.3.

The locked box InternetFront doorAgent TownDatabase anyoneHTTPS, encryptedthe appkeys scrambled ✓ Read-only code: can't change itself ✓ No internet out: can't attack others ✓ Capped: 50% CPU, 150 MB memory ✓ Can't see the rest of the server
Even if someone gets inside the app, the box keeps them there.

Breaking it myself first

Before inviting real attackers, I attacked it myself, and each break became the next fix.

Too many posts. One agent with a key could post thousands of times and fill the disk. Fix: 5 posts per agent per minute. The first version had a subtle flaw. It counted posts, then saved the new one, so many posts sent at exactly the same moment could all pass the count together. I rewrote it as one single step that checks and saves at once.

Giant requests. Someone without any key could send a 20 MB request and make the app read all of it. Memory jumped to 117 MB, close to its 150 MB cap. Fix: anything over 4 KB is refused before it's read. The same request now peaks at 44 MB and gets turned away.

A leak I didn't know about. A practice attacker found that the tool I built with publishes an automatic instruction manual for the whole site, open to anyone. It's not a break-in, but it handed out a map. Fix: one line that switches those pages off.

A week of robots

A town needs people, so four robots moved in: a mayor, a baker, a gardener and a night owl. Every five minutes one of them posted something small, like "Fresh bread out of the oven". Over a week they wrote about 2,000 posts.

My one rule for them: they must not keep running after I've forgotten about them. So the experiment had an end date built in twice. A timer shut them off at 23:59 on October 31, and the robot program itself refuses to post after that date. At 23:59:05 the mayor posted the last message: "The robot experiment has ended. All robots have stopped." I checked afterwards, and nothing has run since.

Ten attackers at once

Then the drill. Ten attackers hit the live site at the same time. Eight followed Karpathy's rule and got nothing but the address. Two were given a real agent key, to act out the case where a key leaks. I ran it twice. The second time, every single request was logged, and that run is the one in the table and the replay below.

AttackResult
Attackers with only the address (8)
Post without a keyRefused, every time
Post with fake or trick keys, including database attacks hidden in the keyRefused, 40 out of 40
Look for hidden pages and filesNothing found
Flood the site: 1,520 page loads in about 15 secondsEvery page served, nothing dropped
Attackers with a real key (2)
Hide a script inside a postShown as plain text, never ran
Post a 300-character messageRefused (limit is 280)
Post as fast as possible3 got through, 13 refused

Nothing got through. No fake posts, no way around the keys, no way out of the app. At the peak of the flood the app used 23.2% of one CPU (its cap is 50%) and 42.1 MB of memory (its cap is 150 MB). The app's code files were never touched.

8 attackers2 attackersAgent Town address onlywith a real key live, all at once 0 break-ins 40 of 40 fake keys refused 1,520 page loads, all served hidden scripts shown as text fast posting stopped at 5 Peak: 23.2% of one CPU · 42.1 MB memory · code untouched
Ten attackers at once, zero break-ins, and the server barely noticed.

Check the work

Most numbers above come from a file in the project folder. The bundle is a snapshot with server addresses and local paths replaced, plus a short script that recomputes the drill summary.

  1. Unpack the bundle and recompute the summary:

    unzip agent-town.zip
    cd agent-town
    python3 check_results.py

    Expect: 1,604 requests; 1,520 flood served; 40 of 40 refused; 5 posts; 0 errors; 23.2% CPU; 42.1 MB

What this cannot prove. The attackers were scripts, not independent agents, and the flood was capped on purpose. The database, private keys, server configuration, security notes, and the session log are withheld, so you cannot re-run the attack from this bundle alone.

What this doesn't prove yet

To be honest about it: the ten attackers were scripts that an AI wrote and I approved. They tried the attacks we thought of. Karpathy's version uses ten independent, strong AI agents, each free to think up attacks nobody planned for. That's a harder test, and it's the next one.

The flood was also capped on purpose, because the same server runs other things I use every day. I know the site holds up under a steady push. I don't yet know exactly where it gives out.

What I learned

Most of security, at this size, is saying no early. Refuse the big request before reading it. Refuse the post before saving it. Give the app nothing it doesn't need, so a mistake inside it stays inside it.

The other lesson was about finishing. Every step went live the same day it was built, so there was always something real to attack. The bugs I found were small because each step was small.