feat: initial monorepo with PRD, 12 ADRs, and plugin skeletons
This commit is contained in:
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
Reference in New Issue
Block a user