Part 1: It Seemed Simple Enough
Just Ask the Team to Build an App
In early 2026, we set out to build BeeChat — a macOS messaging app for our AI team. We already had the AI team in place: a coordinator (Bee), a researcher (Gav), a developer (Q), a designer (Mel), a strategic reviewer (Kieran), and an operations manager (Luna). The idea was straightforward: ask Q to build a Swift/SwiftUI app, have Mel design it, Kieran review the architecture, and Bee coordinate.
What could go wrong?
Quite a lot, as it turned out. But not because the AI agents weren't capable. Because we didn't know how to run an AI development project properly.
Part 2: The Naive Approach — and Its Consequences
Monolithic Code with No Backups
The first version of BeeChat was a single Swift codebase — everything in one Xcode project: the UI, the database layer, the API client, the encryption logic, the keychain integration. No modular separation. No independent packages. Change one thing, and you risked breaking everything else.
There was also no disciplined version control. Commits were irregular. The git repo drifted from the actual working code on disk. We didn't realise it at the time, but we were building a house of cards.
The Working Build That Wasn't in the Repo
In March 2026, we finally got a working build. BeeChat launched. Messages sent and received. The database persisted across restarts. SQLCipher encryption was in place. Keychain integration worked. It did what it was supposed to do.
The problem? The working build existed on disk — but the git repo had been accidentally reverted to an older commit from the day before. All the source changes that made the app work — the fixes, the wiring, the careful integration — were not committed. They lived only in the build artifacts and uncommitted files.
"We had a working app at 17:14 and a broken repository by 21:00. The source code that made it work was gone from version control. Everything after that point was trying to reconstruct what we'd already built."
The Crash Cascade
When we tried to fix minor layout issues — moving message bubbles, adjusting widths — the build system broke. Package dependencies failed. Xcode couldn't resolve GRDB, KeychainSwift, MarkdownUI, SQLCipher. Emergency fixes created new problems. Compile errors multiplied. The database corrupted during an encryption migration. The app wouldn't launch.
By the time we'd finished trying to fix a cosmetic issue, we couldn't even open the app.
The pattern we kept repeating:
Ask AI to build something → It works → Make a change without understanding the dependencies → Everything breaks → Try to fix the fixes → The original working state is lost → Start again.
Part 3: The Hard Lessons
Lesson One: AI Needs Process, Not Just Capability
The AI team could write Swift code. Q could architect, Mel could design, Kieran could review. But without a disciplined development process — regular commits, clean builds, independent testing of each component — the code accumulated technical debt faster than we could pay it down.
We learned that asking AI to build software is like asking a brilliant developer to build software without a code review process. The talent is there. The structure isn't. And without structure, even brilliant code becomes unmaintainable.
Lesson Two: Modularity Is Non-Negotiable
With everything in one codebase, every change was high-risk. Change the database schema, and the UI layer breaks. Update the API client, and the persistence layer fails. There was no isolation — no way to change one thing without risking everything.
We needed independent packages. If the UI broke, the database should still work. If the database changed, the API client shouldn't care. That's Software Development 101. But when AI is writing the code, it's surprisingly easy to skip it.
Lesson Three: Agents Need Roles and Boundaries
Early on, we let the coordinator (Bee) start implementing code. Not just coordinating — actually writing. The result: the person who should be orchestrating the work was also creating work. Changes were being made without review. The architecture was drifting.
We established a rule that we still follow: Bee orchestrates, Bee never implements. Each agent has a defined role. The coordinator coordinates. The developer develops. The reviewer reviews. The designer designs. Without boundaries, the team starts stepping on itself.
"The biggest lesson wasn't about AI capability. It was about human process. AI can write code, but it can't decide that code needs modular architecture. That's your job. AI can follow a process, but it won't create one for you. That's your job too."
Part 4: Starting Over — Properly This Time
BeeChat v5 — Modular from Day One
By May 2026, we'd learned enough to start properly. BeeChat-v5 wasn't a rewrite of the old codebase — it was a clean build from scratch, designed around three shared Swift packages:
- BeeChatPersistence — GRDB/SQLite data layer, topic management, message storage. Independent, testable, with 7+ passing tests.
- BeeChatGateway — WebSocket communication with the OpenClaw gateway. Resilient handshake, auto-reconnect. 26 passing tests.
- BeeChatSyncBridge — Event routing, message persistence, streaming response handling. 48 passing tests.
On top of these shared packages sit two apps — the macOS app and, later, BeeChat-Mobile for iOS. Both depend on the same shared packages. Change the persistence layer once, both apps get the fix. Run the tests once, both apps are verified.
"The difference between BeeChat v1 and BeeChat v5 isn't that v5 has better code. It's that v5 has a better structure. The code in v1 was probably fine — we just couldn't maintain it. v5 was designed to be maintained."
Gate-Based Development
We also introduced a gate-based development process. Before any feature goes live, it passes through defined gates:
- Gate 2A: Architecture specification — what are we building and why?
- Gate 2B: Implementation plan — which components change, what tests are needed?
- Gate 2F: Integration testing — does it work end-to-end across both platforms?
Each gate requires passing tests, code review, and a clean build. No exceptions. This is the process that should have existed from day one.
Part 5: Still Learning
The Journey Isn't Over
BeeChat v5 works. The macOS app sends messages, receives AI responses, persists data, and displays streaming output. The iOS app is in development, sharing the same packages. Cross-device topic sync runs over Tailscale — a networking solution we only discovered because we needed it for testing on a real iPhone.
But we're still learning. Every integration brings new challenges: protocol versioning, database migration safety, WebSocket reconnection edge cases, cross-platform UI differences. The difference now is that when we hit a wall, we have a process for climbing over it — not a process that creates more walls.