Service Composition

Diminuendo uses Effect TS Layers for dependency injection. The main.ts composes 22 services:
main.ts
 └── Bun.serve()
      ├── HttpRouter          # REST API + WebSocket upgrade
      ├── WsRouter            # ACP WebSocket message dispatch
      ├── AuthService         # Auth0 JWT verification
      ├── MembershipService   # Tenant membership + RBAC
      ├── SessionRegistry     # Active session tracking
      ├── MessageRouter       # Route messages to Podium
      ├── AcpPodiumBridge     # ACP ↔ Podium coordinator bridge
      ├── AcpEventMapper      # Map Podium events to ACP notifications
      ├── DeltaCoalescer      # Batch high-frequency text deltas
      ├── ProjectRegistry     # Project management
      ├── ProjectRuntime      # Agent spawning per project
      ├── PodiumClient        # Upstream HTTP/WS to Podium
      ├── EnsembleClient      # Upstream HTTP to Ensemble
      ├── GitHubClient        # GitHub API integration
      ├── ChatBridge          # Chat platform adapters
      ├── AutomationEngine    # Automation workflows
      ├── SkillService        # Skill management
      ├── FileStorageService  # File upload/download
      ├── AuditService        # Audit logging
      ├── CredentialService   # OAuth credential storage
      ├── InvitationService   # Team invitations
      └── WorkerManager       # SQLite background workers

Per-Tenant Data Isolation

Every tenant gets its own SQLite database. Every session gets its own database too:
data/
├── tenants/
│   ├── {tenant_id}/
│   │   └── registry.db      # Threads, projects, members, settings
│   └── ...
└── sessions/
    ├── {session_id}/
    │   ├── session.db        # Messages, turns, elements, approvals
    │   └── memory.db         # Agent memory entries
    └── ...
Benefits:
  • Zero write contention between tenants
  • Trivial deletion (rm -rf data/tenants/{id})
  • Copy-based backup via Litestream
  • Horizontal scaling by moving directories

Upstream Connections

PodiumClient

Diminuendo ──Native WebSocket──► Podium Coordinator /agent/{instanceId}
Diminuendo ──HTTP REST──► Podium (DELETE /agent/{id}, GET /agent/{id}/info, POST /instances)
The AcpPodiumBridge maintains persistent WebSocket connections to Podium coordinators. Podium sends its native StreamUpdate events (e.g. { type: "update", content: {...}, event_type: "tool_call_start" }), and Diminuendo sends native format messages back (e.g. { type: "process_message", content: { text: "...", messages: [...] } }). The PodiumNativeMapper translates 40+ native event types into ACP notifications, which are then persisted to SQLite and broadcast to clients via pub/sub.

EnsembleClient

Diminuendo ──HTTP──► Ensemble /api/v1/models (config)
Agents ──HTTP──► Ensemble /api/v1/stream (inference, direct)
Diminuendo queries Ensemble for model configuration. Agents call Ensemble directly for inference (not proxied through Diminuendo).

GitHubClient

Diminuendo ──HTTP──► GitHub API (repos, PRs, issues, webhooks)
Full GitHub integration for repo management, PR workflows, and webhook dispatch.

Scalability Design

ResourceBudget per Instance
WebSocket connections~10,000
Active sessions~5,000
SQLite databases open~500 (LRU eviction)
Memory~2GB
Scale horizontally by routing tenants to different instances. No shared state between instances.