I was in the middle of a vibe-coding session, building something completely different, as I do very often these days, and the AI kept asking follow-up questions. One question led to the next, then to the next, round after round of clarification before we even got to the actual answer. Each single question made sense on its own, but taken together, a pattern showed up where I spent more time answering questions than working on the actual task. At some point I thought, almost annoyed: come on, doesn't this ever stop? This should be clear by now. I wasn't really discussing a tradeoff with the AI anymore, I was just being asked the same kind of question in a slightly different form, over and over.
Agent Teams grew out of that annoyance. Not as a plan for a multi-agent platform, but as a question that followed directly from the irritation: if the AI understands the problem well enough to keep asking about it, why does all the clarifying still end up on my plate? Why can't agents sort that out among themselves before it even reaches me?
Once I let go of the idea that a single chat window is enough, the next question followed on its own: if I have more than one agent, can they talk to each other, and can that happen without burning tokens on every exchange? Without a shared place, every agent would have to rebuild the context for the others each time, and that's exactly what I wanted to avoid. That led me first to shared memory, a place where agents in the same group can read and write instead of explaining the context to each other again and again.
Quality Cascading came out of the same thinking: not every step in a task needs the most expensive model, some steps need speed, others need depth. A fast, cheap step is enough for something like a simple summary or formatting, while a step with more depth is needed where a decision actually has consequences. Designing that as a dial instead of a fixed choice turned out to matter more than I expected, once real groups were actually running.
I didn't spend much time weighing local-first against the cloud. Privacy isn't negotiable for me, it's a given, not something I debate with myself. Once that was settled, local-first stopped being a separate decision and simply became the path that followed from it. Project files, conversation history, provider credentials, all of that stays on the machine by default, and the architecture grew around that requirement, not around convenience. That has meant more work at several points than a cloud solution would have, but the alternative, up sensitive data somewhere by default, was never an option for me.
The security work you can see in the changelog shortly before the public beta, safeStorage
for provider secrets, the isolated renderer, the MCP trust model, the strict origin checks on the optional REST API, wasn't a last-minute reaction to something I noticed, it was planned that way from the start. safeStorage
makes sure provider credentials aren't stored in plain text on disk, the isolated renderer separates the interface from the rest of the system, the MCP trust model defines which MCP servers and tools an agent is even allowed to trust, and the origin checks on the optional REST API stop unwanted calls from reaching the app in the first place. I wrote the threat model before most of the security code existed, and once it was in place, many implementation decisions weren't really open questions anymore.
If you'd asked me beforehand what would be difficult, I would have guessed the task graph or the parallel execution logic. It wasn't. The hardest part was Quality Cascading, and the reason is obvious once you see it: an agent's answer often just isn't good enough on the first pass, and something or someone has to catch that and force a better second pass before the work continues. The hard part wasn't the idea itself, it was deciding when an answer actually counts as insufficient and justifies a second, more expensive pass, instead of just passing every answer along unchecked. Quality Cascading catches exactly that concrete failure pattern, not a theoretical quality dial, but an actual answer that needed a second, better pass before the rest of the group could build on it. Shared memory is what makes that second pass worthwhile in the first place: a group can build on what another agent has already found out, instead of rediscovering it, and because quality can be tuned per step, cost and token usage stay in a range you actually control, instead of just watching them climb. Without shared memory, every improved second pass would stay isolated, because the other agents in the group would never find out about it. I think this will matter more in general, the more people run several agents at once instead of one after another.
Agent Teams is in public beta, currently Windows-first for the packaged release, MIT licensed. I don't see it as finished, and that's not the plan either. The more it gets used, and the more I use it myself for real work, the more requirements show up that weren't visible at the start, precisely because shared memory and Quality Cascading only reveal where they still struggle once there's real load. I expect to keep restructuring parts of it as that happens, ChatView.jsx
won't stay the only file that gets split up again.
If you want to see what a local-first, security-conscious approach to multi-agent coordination looks like in practice: the code and the full threat model are public, github.com/WittBen/agent-teams.