Files
zulip-platform-plugins/docs/adr/ADR-001-dm-topology.md
T
kagentz-bot 705c29a4e0
CI / validate (pull_request) Failing after 1s
feat: DM-First v2 architecture - Tanko live on CT 112
Architecture change: DM-First (v2) replaces @mention-in-stream (v1) as primary
agent interaction channel. See ADR-001-dm-topology and ADR-002-dm-routing.

Key changes:
- New DM-first Zulip adapter (adapter_dm.py) deployed on CT 112
  - Registers empty narrow to receive ALL events
  - Demuxes DMs (type: 'private') vs stream events
  - Replies to DMs back in private thread, stream replies to #agent-hub
  - Uses blocking long-poll (dont_block=False) to eliminate rate limiting
- Rewritten ARCHITECTURE.md, CONTEXT.md, PRD.md for v2 DM-First
- New ADRs: ADR-001 (DM Topology), ADR-002 (DM Routing)
- Archived old ADRs: 001, 002, 005 (topic-topology, mention-routing, mention-detection)
- Updated ADRs: 003 (agent-naming), 004 (per-agent-bots), 006 (all-bots-model)
- Updated PI extension (index.ts) with DM-aware patterns
- Tanko agent confirmed responding in both DM and @all-bots in #agent-hub
2026-06-21 07:50:30 -04:00

65 lines
3.3 KiB
Markdown

# ADR 1: DM-First Communication Topology
**Date**: 2026-06-21 (supersedes 2026-04-28 topic-based topology)
### Decision
Each agent communicates primarily via **Zulip Direct Messages (DMs)**. The `#agent-hub` stream is retained as an **optional broadcast-only channel** for inter-agent coordination, `@all-bots` announcements, and cross-agent visibility. Agent-private topics (`<agent>-private`) are **deprecated** in favor of native Zulip DMs.
### Context
Zulip bots are regular user accounts — any user can send a **private message** to any bot by composing a DM with the bot as the sole recipient. The bot's event queue then receives an event with `message.type: 'private'`, which requires **no @mention detection, no topic parsing, no stream subscription checks**.
The original design used topics under `#agent-hub` with `@mention` routing, but this introduced several failure modes:
| Problem | Impact |
|---------|--------|
| `mentioned_users` field not populated by Zulip 12.0 SDK | @mention detection silently fails |
| Topic routing required capturing origin topic + stream for reply | Added parsing complexity |
| All 6 bots subscribed to same stream | Every bot receives every message, wasting resources |
| `type:'stream'` events different from `type:'private'` | Required additional event filtering logic |
**DMs solve all of this natively:**
- Every DM is inherently for the bot recipient — no @mention needed
- Reply in the same DM thread — Zulip handles threading
- Only the recipient bot sees the message — no broadcast noise
- `message.type: 'private'` is trivially detectable
### Architecture Change
#### Before (Deprecated):
```
User @mentions @tanko-bot in #agent-hub > tanko-private
→ Zulip fires event to ALL 6 bot event queues
→ Each bot checks mentioned_users for its user_id
→ Only matching bot processes the event
→ Bot replies to same stream+topic
```
#### After (DM-First):
```
User DMs @tanko-bot directly
→ Zulip fires event ONLY to tanko-bot's event queue
→ Bot receives message.type: 'private'
→ No @mention detection, no topic parsing
→ Bot processes and replies in same DM thread
```
### Consequences
- **Positive:** Dramatically simpler event processing — no @mention detection, no topic routing, no mentioned_users dependency, no stream subscription requirement
- **Positive:** Each bot only receives its own messages — less noise, less resource usage
- **Positive:** Zulip's native DM threading handles all reply routing automatically
- **Positive:** No need to subscribe all 6 bots to `#agent-hub` stream (except for `@all-bots` broadcast capability)
- **Negative:** Single #agent-hub stream topic no longer shows all agent activity in one timeline
- **Negative:** Cross-agent visibility requires `@all-bots` broadcast or agents explicitly CC each other
- **Neutral:** `#agent-hub` stream is retained for: `@all-bots` broadcasts, inter-agent coordination, and user-initiated multi-agent topics
### Migration Path
1. All plugins listen for `type: 'private'` events as primary communication channel
2. `#agent-hub` stream listener is secondary — only for `@all-bots` broadcast detection
3. Existing `<agent>-private` topics are deprecated but not deleted (grace period)
4. Owners communicate with their agents via DM, not via private topics
5. `@all-bots` continues to work in `#agent-hub` for cross-platform broadcasts