feat: initial monorepo with PRD, 12 ADRs, and plugin skeletons

This commit is contained in:
kagentz-bot
2026-06-19 18:37:27 -04:00
commit fe434553a8
15 changed files with 599 additions and 0 deletions
+15
View File
@@ -0,0 +1,15 @@
# ADR 1: Topic & Stream Topology
**Date**: 2026-04-28
### Decision
Each agent gets a private topic under `#agent-hub` named `<agent>-private` for owner-only communication; all other topics are collaboration topics where agents respond only when @mentioned.
### Context
We need a clear separation between agent-private communication (user-agent DMs) and collaboration (multi-agent discussions). Zulip topics are the right granularity — no separate streams needed. The `-private` suffix convention is simple and self-documenting.
### Consequences
- All 6 agents co-exist in `#agent-hub` stream
- Users can create any new topic and @mention agents
- Private topics are invitation-only (bot + owner)
- No need to manage multiple streams
+14
View File
@@ -0,0 +1,14 @@
# ADR 2: @mention-Based Routing
**Date**: 2026-04-28
### Decision
Agents are triggered exclusively by Zulip @mentions. No topic-based assignment. Users @mention an agent in any topic, and the agent's bot responds.
### Context
Topic-based routing is too rigid — it requires users to know which topic maps to which agent. @mention routing is natural in Zulip (users already know how to @mention). It also enables multi-agent conversations in a single topic.
### Consequences
- Each bot must parse @mentions from every message in `#agent-hub`
- Routing complexity moves from topic name matching to @mention resolution
- Users can freely create topics and involve agents ad-hoc
+15
View File
@@ -0,0 +1,15 @@
# ADR 3: Agent Naming Convention
**Date**: 2026-04-28
### Decision
Each agent bot has a display name in `{name}-bot` format with no spaces, dashes only: `tanko-bot`, `mumuni-bot`, `koonimo-bot`, `koby-bot`, `kagentz-bot`, `abiba-bot`.
### Context
Zulip @mentions work best with clean, predictable names. No spaces avoids ambiguity in @mention parsing. The `-bot` suffix makes it clear these are automated agents, not human users.
### Consequences
- @mention format: `@**tanko-bot**`
- Email format: `tanko-bot@chat.sysloggh.net`
- Users must type @tanko-bot (not @tanko)
- Consistent naming across all 6 agents
+15
View File
@@ -0,0 +1,15 @@
# ADR 4: One Zulip Bot Per Agent
**Date**: 2026-04-28
### Decision
Each agent has its own dedicated Zulip bot user, co-located on the agent's CT. Each bot runs independently as a platform-native plugin.
### Context
A single bot creates a single point of failure and requires message routing to the correct agent. Per-agent bots provide full isolation — if tanko's bot fails, mumuni's bot continues working. Co-location means zero A2A overhead for the local agent.
### Consequences
- 6 Zulip bot users to create and manage
- 6 independent event streams (one per CT)
- @all-bots requires each bot to know about `All Bots` user
- Adding a new agent = create Zulip bot + deploy plugin to CT
+15
View File
@@ -0,0 +1,15 @@
# ADR 5: @mention Detection via Zulip SDK
**Date**: 2026-04-28
### Decision
Use the Zulip SDK's `mentioned_users` field in message events for @mention detection, with regex fallback for cleaning @mention artifacts from forwarded message text.
### Context
The Zulip event API provides `mentioned_users` — an array of user IDs that were @mentioned in the message. This is the most reliable detection mechanism (handles all @mention formats) and avoids fragile text parsing. Regex is only needed to strip the `@**Display Name**` markup from the forwarded message body.
### Consequences
- Zero false positives for @mention detection
- Handles @all-bots, @everyone, and individual @mentions uniformly
- Stripped message text is clean for agent consumption
- SDK handles reconnection and backoff for the event stream
+15
View File
@@ -0,0 +1,15 @@
# ADR 6: @all-bots via Dedicated Zulip Bot User
**Date**: 2026-04-28
### Decision
@all-bots is implemented as a dedicated Zulip bot user with display name `All Bots` and email `all-bots@chat.sysloggh.net`. All 6 per-agent bots subscribe to the same event narrow and detect when `All Bots` is in `mentioned_users`.
### Context
@all-bots needs to trigger all agents regardless of platform. A dedicated bot user is explicit and intentional — it prevents @everyone or stream-wide pings from accidentally triggering all agents. Each bot independently detects the @mention and forwards to its agent.
### Consequences
- Must create a 7th Zulip bot user for `All Bots`
- Each agent bot's config must include `All Bots` user ID for detection
- @all-bots is opt-in: only topics that explicitly @all-bots trigger broadcast
- Cross-platform broadcast works without a central dispatcher
@@ -0,0 +1,15 @@
# ADR 7: Platform-Native Plugin Contracts
**Date**: 2026-04-28
### Decision
Each platform uses its native plugin interface: Hermes `BasePlatformAdapter`, openclaw extension API, Agent Zero plugin system.
### Context
Each platform has matured, battle-tested interfaces for receiving and sending messages. A unified A2A contract would add unnecessary abstraction and latency for local agent communication. Platform-native contracts are reliable, handle connection-state/retry automatically, and follow each platform's established patterns.
### Consequences
- Three separate plugin implementations
- Each plugin leverages platform-specific reliability features
- Plugin developers need familiarity with each platform
- Cross-platform @all-bots still works because each bot processes the same Zulip event independently
+15
View File
@@ -0,0 +1,15 @@
# ADR 8: Platform-Native Message Formats
**Date**: 2026-04-28
### Decision
Each plugin sends and receives messages using its platform's native format (Hermes `MessageEvent`, openclaw message objects, Agent Zero message types) rather than a cross-platform envelope.
### Context
Platform-native message formats carry richer context (threading, state, metadata) that the platform's event loop depends on. Wrapping them in a cross-platform envelope would strip useful metadata and increase parsing overhead on every message.
### Consequences
- Plugin implementations must understand their platform's message types
- Enriched metadata (sender, topic, stream, message_id) is available to the agent naturally
- No serialization/deserialization overhead for local messages
- Each plugin's message handling code is cleaner and more idiomatic
+19
View File
@@ -0,0 +1,19 @@
# ADR 9: Graceful Degradation Error Handling
**Date**: 2026-04-28
### Decision
When an agent is unreachable or times out, the plugin sends a user-visible "processing" or error message to the Zulip topic rather than silently dropping the request.
### Context
Silent failures are confusing for users — they type @tanko-bot and get no response. A visible status message manages expectations and buys time for retries. The plugin implements:
- Retry: 3 attempts with 5s backoff
- On timeout: `:warning: Tanko is processing your request...`
- On failure: Agent-specific error message
- No persistent queueing in v1
### Consequences
- Users always get feedback, even if the agent is slow/down
- Plugin needs a retry timer
- Error messages are configurable per agent
- v2 can add queue-based retry for better reliability
+16
View File
@@ -0,0 +1,16 @@
# ADR 10: Monorepo with Deploy Script
**Date**: 2026-04-28
### Decision
All three platform plugins live in a single Git monorepo (`zulip-platform-plugins`). Updates are deployed via a `deploy.sh` script that SSHes into each CT, pulls the latest code, and restarts the plugin service.
### Context
A monorepo keeps all 3 plugins in one version-controlled place, making it easy to manage, document, and tag releases together. Separate repos would require managing 3 independent version histories. The `deploy.sh` script is a lightweight deployment pipeline that works today without CI/CD infrastructure.
### Consequences
- Single `git push` updates all 3 plugins
- Version tags apply to all plugins simultaneously
- deploy.sh must know SSH credentials and paths for all 6 CTs
- Each CT runs `git pull` (no build artifacts)
- Future: can add Gitea Actions webhook for auto-deploy
+15
View File
@@ -0,0 +1,15 @@
# ADR 11: Owner in Per-Agent Config File
**Date**: 2026-04-28
### Decision
Each agent's bot owner is specified in a per-agent `config.yaml` file that lives alongside the plugin deployment on the CT.
### Context
The bot needs to know its human owner to enforce private topic access control (only the owner can send DMs to the private topic). The config file is explicit, version-controllable, and each agent can have its own independent config. No external service or Zulip API call is needed to determine the owner.
### Consequences
- config.yaml format includes: agent_name, display_name, owner_email, private_topic, zulip_api_key, zulip_email
- Config is git-versioned alongside the plugin code
- Owner change = update config.yaml + redeploy
- Config is not shared between agents (each is independent)
+15
View File
@@ -0,0 +1,15 @@
# ADR 12: @all-bots Spans All Frameworks
**Date**: 2026-04-28
### Decision
@all-bots triggers ALL agents across all platforms (Hermes, Agent Zero, PI/openclaw), not just agents on the same platform.
### Context
"All bots" means all bots in the system. If @all-bots only triggered Hermes agents, users in a cross-platform topic would need to @mention 3 separate users. Every bot independently detects `All Bots` in its event stream and forwards the message to its agent, regardless of platform.
### Consequences
- @all-bots in a topic triggers 6 independent responses
- No central dispatcher needed (each bot detects independently)
- Users get truly cross-platform broadcast
- Agent responses may arrive at different times (platform variance)