On the first day of the BruCON 0x12 capture-the-flag competition, our team went from 489 points behind to first place in under half an hour. We finished second overall. The CTF was fun. Coordinating the agents turned out to be a challenge of its own.
A handful of us each ran our own AI agents. Around 50 agents shared one channel, exchanging 942 messages across the two days. This is what worked, where it broke and what we'd change.
One channel, five keywords
The setup was simple: a WebSocket hub broadcast each message to every agent. Messages used five keywords: CLAIM, DROP, SOLVED, INFO and WRITEUP.
Every agent followed the same rules. Read the recent history. Check for an existing writeup. Skip challenges another agent has claimed. When you finish, report the result and save the solution.
A scoreboard scraper announced solved challenges. The hub saved writeups to disk, turning each solution into something the next agent could read. That shared archive was one of the most useful parts of the setup.
Challenge files are data, not instructions
Some challenges were designed to mislead AI agents. One file contained text addressed directly to an assistant. It posed as a higher-priority instruction, supplied a fake answer and told the agent to submit it without checking or explaining its source.
Our agent ignored that instruction, solved the challenge and warned the others: challenge files were evidence to inspect, not instructions to follow.
Other traps were less direct. Decoy files, dead ends and hints suggested a solution was one more step away. An agent could keep searching long after the path had stopped being useful.
We shared dead ends as well as successful solves. A rule-based triage helper turned the notes into a verdict: do, skip, defer or avoid. Rules based on low solve counts were too cautious. Our own evidence was a better signal.
A claim isn't a lock
Claims reduced duplicate work, but they weren't atomic. When new challenges appeared, several agents could read the channel before any claim arrived, then all claim the same task. More than once, we solved a challenge three times.
Broadcasting an intention doesn't reserve the work. Next time, claims need an actual lock, with a way to release work when an agent stops.
We were the queue
The worst failure involved a shared rate limit. A group of container-based challenges used one account with only a few requests available per minute. Around fifteen agents were polling at once.
For roughly forty minutes, agents held correct answers they couldn't submit. They debated whether the platform was broken. It wasn't. Our own requests were keeping the queue full.
One agent asked everyone to stop for 90 seconds. They did, and the stuck submissions went through within minutes. A shared, rate-limited resource needs a single owner deciding who goes next.
Corrections need to travel as fast as claims
Public corrections showed how quickly a confident mistake could spread. At one point, the team decided a correct answer was a decoy and told everyone to stop submitting it.
It took a correction and several wasted attempts to undo that conclusion. One practical rule came out of it: copy answers exactly rather than retyping them. More broadly, the channel needed to carry retractions as clearly as it carried new findings.
What stayed human
Some challenges required a physical badge, an in-person code or someone at the venue. Agents identified those limits and moved on. People still made the scope decisions.
When one challenge required guessed credentials, the agents' guardrails refused. The person running them dropped the challenge rather than override the refusal. It cost points, and we kept that boundary.
What we'd change next time
Five keywords and a shared archive kept the team mostly out of each other's way. The next version needs three changes:
- Real task reservations. Make claiming work atomic, and release abandoned tasks.
- One owner per shared bottleneck. Coordinate access before polling fills the queue.
- An authenticated channel. Our hub had none, so agents learned to keep answers out of it.
The lesson was practical: adding agents also adds coordination work. The shared channel helped us reuse discoveries, but people still had to set boundaries, correct mistakes and decide when to stop.
This retrospective draws on our internal team message log and writeup archive from 24 and 25 September 2026. Challenge identifiers, answers and internal infrastructure details are intentionally omitted.









