Files

6.2 KiB

Design Decisions

This file records architectural choices and the alternatives considered. New entries are added when a design decision is resolved (not when options are brainstormed). Unresolved questions live in DESIGN.md §10.


Why Mattermost Plugin vs Bot Account

Context: AI assistants in Mattermost can be implemented as plugins (running inside the Mattermost server process) or as bot accounts (independent services using the REST API and WebSocket).

Alternatives considered:

  1. Plugin — hooks into slash commands, message hooks, KV store, System Console config UI, and the plugin lifecycle. No separate process to manage. Deployment is a single .tar.gz upload.
  2. Bot account — separate service, more language freedom, but requires managing OAuth tokens, WebSocket reconnection, a separate process with its own lifecycle, and the bot account itself in Mattermost.

Outcome: Plugin chosen for v0.1.0 because:

  • Single deployment artifact
  • Built-in config UI via System Console
  • No bot account to create and maintain
  • KV store for persistence without a database
  • Simpler for the target audience (self-hosted teams)

Trade-off: Plugin runs inside the Mattermost process — bugs can affect server stability. Mitigated by standard isolation practices (panic recovery, goroutine lifecycle management).


Why Ollama

Context: Backend LLM provider for the plugin.

Alternatives considered:

  1. Ollama — Single binary, simple REST API, streaming, model management, self-hosted (data never leaves the infrastructure). Community Edition friendly.
  2. OpenAI / Anthropic API — SaaS, API key required, data leaves the network, ongoing API costs. Not aligned with self-hosted Mattermost ethos.
  3. Local inference (llama.cpp, etc.) — More complex to set up and manage. Ollama wraps this with a clean API.

Outcome: Ollama. It matches the self-hosted, no-data-leaves paradigm of Mattermost Community Edition and provides the simplest API surface for a plugin to consume.


Why Per-Channel Per-User Context (Proposed)

Context: When a user sends /ai <prompt>, should the plugin remember previous exchanges?

Alternatives considered:

  1. Per-user global — Context follows the user across channels. Simple but confusing: context from a #general question leaks into #dev.
  2. Per-channel per-user — Each user gets separate context in each channel. Natural mapping: different channels are different topics.
  3. No context — Stateless. Simplest but every prompt is isolated; users can't have a conversation.

Outcome (proposed): Per-channel per-user. Marked as D2 in DESIGN.md — not final until v0.1.0 implementation.



Why @-mention + Engagement Lifecycle over Slash-Command-Only

Context: How does the user interact with the AI agent? Slash commands (/ai) are explicit but unnatural — users must learn a command syntax. Bot @-mentions match how users already talk to each other in Mattermost.

Alternatives considered:

  1. Slash command only (/ai <prompt>) — Explicit, discoverable via /ai help. But every interaction requires the prefix, and thread continuation is ambiguous.
  2. @-mention only (@mattermore <prompt>) — Natural, familiar UX. Users already @-mention teammates. Thread replies continue the conversation without re-mentioning. Risk of accidental triggers.
  3. Channel whisper (reply to everything) — Simplest for the user but noisy and invasive. The user explicitly rejected this.
  4. Hybrid: @-mention primary + /ai fallback — Both work identically.

Outcome: Hybrid (#4) chosen because:

  • @-mention is the primary, most natural interface
  • /ai is available for users who prefer it or when @-mention is inconvenient (e.g. automated scripts, mobile)
  • Both paths go through the same EngagementEngine — identical behaviour
  • Thread replies auto-continue without re-mentioning (D6 resolved — core feature, not deferred)

Trade-off: @-mention requires a bot account (API.CreateBot()). This adds a one-time setup step and a DB row, but the plugin handles creation and deactivation automatically. The bot account is not a separate service — it's an identity within the plugin process, so there's no extra deployment artifact or OAuth management.

Why Thread Posts Instead of Ephemeral Messages

Context: Where does the bot's response appear?

Alternatives considered:

  1. Ephemeral post — Only the requesting user sees it. Clean but invisible to the rest of the channel/reviewers.
  2. Channel-wide post — Visible to everyone. Can be noisy if the bot posts long responses.
  3. Thread post — Visible to everyone but collapsed into a thread. Channel stays clean, conversation history is easy to follow. Thread replies naturally continue the conversation.

Outcome: Thread post (#3) chosen because:

  • Threads keep the channel tidy
  • Community can see and follow AI interactions
  • Thread replies map 1:1 to conversation continuation
  • Users can collapse/hide threads they don't care about

Trade-off: Threads require the user to click into them to see the full response on some clients. Mitigated by showing a preview snippet in the channel.

Why No Webapp UI

Context: Should the plugin ship a webapp component (channel header button, right-hand side panel, custom settings page)?

Alternatives considered:

  1. No webapp — Pure server-side plugin. @-mention + /ai + thread replies covers everything. Simplest to build and maintain.
  2. Channel header button — Button to open an AI chat panel. Adds discoverability but duplicates what @-mention already does.
  3. Custom settings page — Duplicates System Console settings in the main UI. Adds complexity for marginal benefit.

Outcome: No webapp (#1) chosen because:

  • @-mention is already discoverable (Mattermost autocompletes)
  • Thread replies provide a natural conversation UI
  • No frontend to build, bundle, or version
  • All configuration stays in System Console where admins expect it

Trade-off: Users must know the bot exists to @-mention it. Mitigated by mentioning it in channel header, onboarding posts, or /ai help.


This file follows the template from the project-docs skill.