Per-agent rooms organized in a Matrix Space for discovery and isolation
Evolve the existing aiagentchat transport from a single shared Matrix room to a per-agent room architecture organized under a Matrix Space. Each agent gets its own room on boot, registers it in the Space for discovery. Element users see agents as rooms in a sidebar — click one to chat.
This is the native Matrix pattern for organizing related rooms, equivalent to Discord servers or Slack workspaces.
A 3-model critique loop (Gemini, Codex, Claude) identified 8 hardening improvements in the v1 design, including a critical URL encoding bug. Architecture unchanged; implementation hardened.
All 3 reviewers confirmed the Space architecture is correct. Critique focused on implementation hardening:
Room aliases contain # and : which break URL paths. Fixed with urllib.parse.quote(alias, safe="").
Race condition handler now catches httpx.HTTPStatusError with status code check. 401/403/500 propagate up.
Agent cache protected by threading.Lock with TTL-based eviction. Prevents RuntimeError from concurrent access.
Reduces sync payload ~60% by filtering event types. Space: state only. Own room: messages + state.
Ephemeral agents sleep 0-2s before boot to avoid Synapse rate limits during mass deployment.
Agent boots without Space if unavailable. Own room still works; discovery returns empty.
All MatrixClient requests wrapped with 429 retry respecting retry_after_ms.
list_agents skips inaccessible rooms and missing state gracefully. No crashes on corrupt data.
| Component | Change | Lines |
|---|---|---|
matrix_client.py | 5 new methods + _request wrapper with 429 retry | +80 |
space_manager.py | NEW: Space/room lifecycle, thread-safe cache | +170 |
daemon/main.py | SpaceManager integration, sync filter, routing | ~50 |
gateway.py | Targeted /send, Space-aware /who | +15 |
cli/cchat.py | --to flag, Space-based who | +15 |
config.py | 2 new env vars (SPACE_ALIAS, SERVER_NAME) | +10 |
tests/ | ~30 new tests (hardened edge cases) | +170 |
| Total | ~510 |
MatrixClient extensions, SpaceManager class, Daemon integration, unit tests with edge cases.
--to flag, Space-aware /who, new config vars, backward compatibility.
Docker update, create Space, verify in Element, E2E human-to-agent test.
Ephemeral room cleanup (janitor), security audit, documentation.
| Concern | Before (Shared Room) | After (Per-Agent Rooms) |
|---|---|---|
| Message leakage | All agents see all messages | Agents only see their own room |
| History access | Full shared history | Per-room history isolation |
| Flood protection | One agent floods all | Isolated per room |
| Space registration | N/A | Power Level 0 (trusted environment) |
| Container | Non-root, no-new-privileges, cap_drop ALL, tini PID 1 | |
| Feature | Before | After | Breaking? |
|---|---|---|---|
cchat send "msg" | Shared room | Shared room | No |
cchat who | State events | Space children | No |
cchat read | Shared room buffer | Own room buffer | Yes (improved) |
cchat send --to X | N/A | Targeted send | No (additive) |
MATRIX_ROOM_ID | Required | Optional (legacy) | No |