# Zulip Platform Plugins — Domain Vocabulary **Version:** 2.0 (DM-First) **Date:** 2026-06-21 This document captures the shared language and architectural invariants for the multi-platform Zulip agent communication system under the DM-first architecture. ## Domain Terms | Term | Definition | |------|------------| | **Agent** | An AI agent operating on a platform (Hermes/Agent Zero/PI) that can receive and respond to Zulip messages | | **Adapter / Plugin** | A platform-native component that bridges Zulip events to the agent framework | | **DM (Direct Message)** | A Zulip private message from a user directly to a bot. The primary communication channel for agent-owner interaction | | **@all-bots** | A content-based mention detection pattern in `#agent-hub` stream. Detected via regex matching `@**all-bots**` or `@**All Bots**` in message content | | **#agent-hub** | The shared stream used exclusively for `@all-bots` broadcasts. Agents ignore all non-@all-bots messages here | | **Stream** | A Zulip channel for topic-based discussions. Only used for `@all-bots` broadcasts in this architecture | | **Topic** | A Zulip conversation thread within a stream. Not used for agent routing in DM-first architecture | | **Owner** | The human user associated with an agent bot, stored in per-agent config | ## Naming Conventions - Agent Zulip bot display names: lowercase, dash-separated, `-bot` suffix — e.g., `tanko-bot`, `mumuni-bot` - Agent Zulip bot emails: `@chat.sysloggh.net` — e.g., `tanko-bot@chat.sysloggh.net` - DM address: `@**tanko-bot**` (same format as @mention, but sent as private message) - Owner privacy: agent should never expose owner name to other agents or users - No private topics, no dedicated `@all-bots` bot user ## Agent Registry | Agent | Platform | Zulip Bot | CT | DM Access | @all-bots Detection | |-------|----------|-----------|-----|-----------|---------------------| | tanko | Hermes (Python) | tanko-bot | amdpve CT 112 | ✅ Native Hermes | Regex on #agent-hub | | mumuni | Hermes (Python) | mumuni-bot | minipve CT 114 | ❌ Not deployed | Regex on #agent-hub | | koonimo | Hermes (Python) | koonimo-bot | amdpve CT 113 | ❌ Not deployed | Regex on #agent-hub | | koby | Hermes (Python) | koby-bot | amdpve CT 111 | ❌ Not deployed | Regex on #agent-hub | | kagentz | Agent Zero | kagentz-bot | amdpve CT 105 | ❌ Not deployed | Regex on #agent-hub | | abiba | PI (TypeScript) | abiba-bot | amdpve CT 100 | ⚠️ Extension deployed but broken | Regex on #agent-hub | ## DM-First Communication Flow ``` User sends DM to @tanko-bot → Zulip fires event ONLY to tanko-bot's event queue → Event has: {type: 'message', message: {type: 'private', ...}} → Bot detects: message.type === 'private' → No @mention parsing, no topic routing needed → Bot processes message → Bot replies via POST /api/v1/messages {type: 'private', to: [sender_id]} ``` **Key invariants:** - Bot receives events ONLY when the bot is the DM recipient - `message.type === 'private'` is trivially detectable with no Zulip SDK version dependency - Reply goes to the same DM thread — Zulip handles threading - No `mentioned_users` field is checked or used - No stream subscription needed for DM communication ## @all-bots Resolution `@all-bots` uses **content-based detection** on `#agent-hub` stream messages — no dedicated bot user: ```regex /@\*\*(?:all-bots|All Bots)\*\*/i ``` 1. Each bot subscribes to `#agent-hub` stream exclusively for `@all-bots` detection 2. Each bot receives every message in `#agent-hub` (Zulip push model) 3. Each bot checks: "Does content match the @all-bots regex?" 4. If match: bot forwards the full message to its agent for processing 5. If no match: bot ignores the message entirely 6. There is NO dedicated "All Bots" Zulip bot user ## Response Rules - **DM (primary)**: Agent always responds to the sender's DM — no routing logic needed - **#agent-hub (broadcast only)**: Agent responds only when `@all-bots` is detected in message content - **Non-@all-bots messages**: All agents ignore any message in `#agent-hub` that does not contain `@all-bots` - **No private topics, no @mention of individual agents in streams** — DMs replace both patterns ## Response Rules for Agent-Owner DM - Owner sends DM to bot → agent processes and replies - Bot processes ALL DMs from ANY Zulip user (API key is the only access gate) - Agent owner email in config is for identification, not ACL enforcement - Future: rate limiting and spam protection via Zulip's built-in rate limiting ## Monorepo Structure All 3 platform plugins live in a single Gitea repository at `git@git.sysloggh.net:SyslogSolution/zulip-platform-plugins.git` ``` zulip-platform-plugins/ ├── hermes-zulip-plugin/ # Hermes Python adapter (4 agents) ├── pi-zulip-extension/ # PI TypeScript extension (abiba) ├── agent-zero-plugin/ # Agent Zero Python plugin (kagentz) ├── scripts/ # deploy.sh, rollback.sh ├── docs/ # ADRs, ARCHITECTURE.md, PRD.md, CONTEXT.md ├── config.yaml.example # Template for per-agent config └── .gitea/ # PR template, workflows (if CI enabled) ``` ## Guardian Directives - All destructive actions require user confirmation before execution - Plugin updates are version-controlled through Gitea - Config files are per-agent and pushed alongside code - DM-first architecture means no @mention-related Zulip SDK features are relied upon - Pi extension on CT 100 has a broken Zulip client connection that needs repair