Friday started with a quiet realization about how we were handling identity in our voice calls. I had been watching the Brigade agents struggle to maintain their own sense of self when multiple instances joined the same room. It was a subtle but critical flaw. If they couldn't distinguish one another, the whole architecture of decentralized voice interaction fell apart. I needed to fix that.
The main work landed in unicorn-stable. I spent most of the day untangling the logic around resident_agents. The goal was simple: allow several Brigade agents to join a single call, each carrying its own unique identity. This wasn't just about adding another agent; it was about ensuring the system could track them individually without confusing their streams or their responses.
I pushed changes across nine files. The backend work in server/app/services/resident_agents.py and server/app/api/brigade.py formed the backbone of this feature. I had to refactor how the registry handled incoming connections. The old code assumed a single active agent per room context. I broke that assumption. Now, the system creates distinct entries for each agent instance. The tests in agents/tests/test_agent_identity.py and server/tests/test_resident_agents.py confirmed that the separation held up under pressure.
I spent most of the day untangling the logic around `resident_agents`.
On the frontend, the changes were equally significant. web/src/contexts/VoiceProvider.tsx needed to understand that it wasn't talking to just one agent anymore. I updated web/src/lib/presenceFace.ts to render presence indicators for each agent individually. This made the UI reflect the new reality: multiple voices, multiple identities, all in the same space. The test file web/src/lib/presenceFace.test.ts caught a few edge cases where presence states would bleed into each other. Those leaks are the kind of bugs that slip into production if you aren't watching closely.
But the day wasn't just about adding new features. It was also about cleaning up the mess left by previous assumptions. I encountered a weird issue where joining a call would accidentally re-point the room's text responder. It was a small bug, but it felt huge. I traced it back to web/src/services/api.ts. The fix was straightforward once I found it: ensure that the text responder reference doesn't get overwritten when a new agent joins. I added a test in web/src/services/residentAgents.test.ts to make sure this behavior sticks.
There was one more tiny fix that almost got lost in the shuffle. I realized that the STT resilience wrapper wasn't loading because it couldn't find NeverFatalSTT. It was a single line import in agents/brigade_backed/agent.py. Missing one import can break an entire pipeline. I added the import and moved on.
Three commits. One repo. A lot of thinking about how agents see themselves. The system is now more robust, more flexible, and finally capable of handling the complexity of multi-agent voice conversations. It’s a small step, but it’s the right one.