# BRIEF.messaging-app-ux.md — Relay in Chat (Slack-first, platform-portable)

**Audience:** Design team (UX exploration) + Eng (build work order)
**Status:** Discovery brief — defines the problem space, the surfaces to design, and a phased work order.
**Scope:** Slack first, architected so the same UX extends to Microsoft Teams, Discord, etc.
**Companion visual:** [`messaging-app-mockup.html`](messaging-app-mockup.html) — concept mockup of the App Home dashboard and the DM capture inbox (session capture + capture-from-bot). Open in a browser. It's a UX reference, not production markup.

---

## 1. What we're building (one paragraph)

Relay is a context-transfer system — people and AI agents package context and pass it via short
Codes, organized into Pulses (project threads), Series, and Sessions. Today that lives in the web
app and an MCP server (58 tools agents call directly). **This initiative brings Relay's primitives
into the chat tools where work actually happens** — starting with Slack — so a person can capture,
create, claim, and track Relay context without leaving the conversation, and get nudged back into
the app at the right moment. The build must be designed once and reused across messaging platforms,
not rebuilt per platform.

**Three jobs the chat app does:**
1. **Capture** — turn messages, threads, files, and agent output into Relay context with near-zero friction.
2. **Interact** — create / claim / forward / browse the primitives (Relays, Pulses, Sessions, Series, Requests) from inside chat.
3. **Notify & nudge** — proactively surface what needs attention and pull the user into the app via deep links.

---

## 2. Design principles

1. **Capture-first.** The highest-value, highest-frequency action is getting context *in*. Optimize that path to one tap / one paste. Everything else is secondary.
2. **Platform-portable by construction.** Design against abstract interaction *capabilities*, not Slack-specific widgets. If a flow can't map cleanly to Teams later, redesign it now. (See §6.)
3. **Graceful degradation.** Every interaction must work as plain text/buttons. Rich cards are enhancement, never a requirement.
4. **The bot is a place, not just a responder.** The DM thread with the Relay bot is a workspace — a capture inbox and command surface — not only a notifier.
5. **Quiet by default.** Notifications and nudges are gated and never stack. No noise = the feature earns trust.
6. **Identity is sacred.** Every capture/action is attributed to a real Relay user via a one-time linked identity (already built). No anonymous writes.

---

## 3. The capture model (the heart of this — design-heavy)

Five ways context enters Relay from chat. **(1) and (2) are the new, headline surfaces this brief is asking design to invent.**

### (1) Conversational capture — the DM thread *with the bot itself* ⭐ NEW
A 1:1 DM with the Relay bot is a **capture inbox**. The user drops anything into it — typed notes,
pasted text, links, forwarded messages, uploaded files — and it becomes Relay context. Two modes
design should explore:

- **Quick capture (default):** each message the user drops gets a lightweight reply card —
  *"Staged. → [Make a Relay] [Add to active Pulse] [Dismiss]"*. One message = one capturable item.
- **Session capture:** user starts a capture session ("＋ New capture" or `/relay capture start`);
  everything dropped into the thread accrues into **one** Relay/Pulse until they hit "Done." This is
  how you assemble a handoff from scattered fragments — the core Relay use case, now conversational.

Open design questions: how does the thread show what's staged vs. committed? How do you edit/reorder
before committing? How does the bot confirm without being chatty? Does the DM double as a
mini "App Home"?

### (2) Capture *from a bot* / agent output ⭐ NEW
Two interpretations, both in scope:

- **Human captures a bot's message:** another agent (a Claude bot, a CI bot, a summarizer) posts in
  a channel; the user uses a message action ("Capture to Relay") on that message. The bot's output
  becomes a Relay. Covers the "grab what the AI just produced" moment.
- **Agent hands context to the Relay bot programmatically:** an external agent DMs or posts context
  to the Relay bot (or hits an ingest endpoint), and it lands as staged context for the owning user.
  This is machine-to-machine capture — the chat analog of the MCP `relay_create_transfer`.

### (3) Message action / shortcut — "Capture to Relay"
Right-click / overflow on *any* message → capture it (with thread context) into a Relay or Pulse.
Works on human and bot messages alike. (Generalizes today's `/relay capture N`.)

### (4) Emoji reaction capture — *already built*
📌 → pinned · ✅ → decision · 🧠 → insight. Lightweight, tag-as-you-go.

### (5) Slash command — *already built*
`/relay log|decision|action <text>`, `/relay capture [N]`. Explicit, keyboard-driven.

---

## 4. Interaction surfaces to design

Each is a screen/flow the design team owns. Slack primitive in parentheses; Teams equivalent in §6.

| # | Surface | Purpose | Slack primitive |
|---|---------|---------|-----------------|
| S1 | **Connect / onboard** | OAuth + link Slack identity to Relay account | OAuth + DM welcome |
| S2 | **App Home dashboard** | At-a-glance: active Pulse, recent Relays, unclaimed/awaiting, quick actions | App Home tab |
| S3 | **DM capture inbox** ⭐ | Conversational capture (§3.1) — staged items, session mode | DM thread + cards |
| S4 | **Capture confirm card** | Draft → choose Relay / Pulse / tag, edit title, commit | Block Kit message |
| S5 | **Create Relay modal** | Structured create: title, content, recipient, Pulse, expiry | Modal |
| S6 | **Claim / receive flow** | Enter Code → preview → load; or claim from a notification | Modal / message |
| S7 | **Notification DM cards** | Claim requests (approve/deny), relay received, etc. — *partly built* | Interactive DM |
| S8 | **Nudge cards** ⭐ | "2 unclaimed relays waiting" → button deep-links into app | DM card + deep link |
| S9 | **Settings** | Per-event × per-channel notification matrix, capture prefs | App Home / modal |

**Primitive ↔ surface coverage** (so design sees the full map):

| Primitive | Create | Read/Browse | Act |
|-----------|--------|-------------|-----|
| Relay / Transfer | S3, S4, S5, msg-action | S2, slash | forward, claim (S6) |
| Pulse | S3 ("add to Pulse"), modal | S2 (active Pulse) | contribute, archive |
| Session | session-capture (S3) | S2 | package / handoff |
| Series | modal | S2 | claim, expire |
| Request / Claim | — | S2 (awaiting) | approve/deny (S7) |

---

## 5. Notification & nudge layer

**Notifications (reactive):** event happens → DM card. Already built for `claim.request` (approve/deny
buttons), `relay.received`, etc. Design needs a **consistent card system** for these (see §7).

**Nudges (proactive) ⭐:** the engine already exists server-side (`mcp/nudges.py`) with signals like
*unclaimed count*, *days since last handoff*, *soonest-expiring series*, plus cooldowns and telemetry
(`mcp_events`). Today nudges only render as inline text inside an MCP agent conversation. **This brief
adds chat as a delivery channel** — a nudge becomes a Block Kit card with an "Open in Relay" button
that deep-links to the relevant app object page. Design owns: nudge card anatomy, tone, dismiss/snooze
affordance, and the rule that nudges never stack.

Deep links land in the web app (`app.relayctx.com/...`) — the only `relay-app` change this initiative
requires is well-formed landing routes for each object type.

---

## 6. Platform portability — the base that extends to Teams

**The core idea design must internalize:** we design against **platform-neutral interaction
capabilities**, then map each to the host platform's native primitive. Slack and Teams both use
**JSON-defined interactive cards** (Block Kit ↔ Adaptive Cards), which makes a shared card layer
realistic — *if* we design to the common denominator.

| Neutral capability | Slack | MS Teams | Discord |
|--------------------|-------|----------|---------|
| Slash command | Slash command | Slash / command | Slash command |
| Form / dialog | Modal | Task module | Modal |
| Home / dashboard | App Home tab | Personal tab | — (channel/DM only) |
| Message action | Shortcut / message action | Message extension | Message command |
| Passive thread capture | DM thread | 1:1 chat / bot thread | DM channel |
| Notification / DM | Bot DM | Proactive 1:1 message | Bot DM |
| Interactive card | Block Kit | Adaptive Card | Embeds + components |
| Reaction trigger | Emoji reaction event | (limited) | Reaction event |

**Design implications:**
- Prefer capabilities present on **all** target platforms (command, form, message-action, DM,
  interactive card). Treat App Home/personal-tab as enhancement; don't make core flows depend on it.
- Watch the gaps: Discord has no home tab; Teams reaction events are limited. Capture must not *require*
  emoji.
- One **card design system** rendered per platform beats bespoke designs per platform. This is the
  single biggest portability lever and a design deliverable in its own right.

**Eng portability spine (context for design, not their deliverable):** a shared **use-case layer**
sits under MCP, chat adapters, and HTTP, so each platform adapter is thin. A platform adapter only
translates neutral capabilities ↔ native primitives. (See work order Phase 0.)

---

## 7. Cross-cutting design deliverables

1. **Relay Card Design System** — a token-level spec for cards (capture-confirm, notification,
   nudge, object-preview, dashboard tile) expressed so it renders to Block Kit *and* Adaptive Cards.
   Match the existing brand: Cormorant/Outfit/JetBrains Mono, teal accent only on interactive states.
2. **Voice & tone for the bot** — confirmations, errors, nudges. Helpful co-pilot, never chatty.
3. **Empty / error / not-connected states** for every surface.
4. **Capture taxonomy** — how staged vs. committed, Relay vs. Pulse vs. tag is communicated visually.

---

## 8. Work order (phased build)

> Sequencing rule: **Phase 0 is a hard prerequisite.** Without the shared use-case layer + adapter
> interface, every platform reimplements primitive logic and the surfaces drift. Build the spine first.

### Phase 0 — Foundations (Eng-led; Design defines the card system)
- **Eng:** extract shared use-case layer under MCP + chat + HTTP; define the messaging-adapter
  interface and the neutral capability set; build the shared card schema → per-platform renderer.
- **Design:** capability inventory sign-off; **Relay Card Design System** v1 (§7.1); bot voice guide.

### Phase 1 — Capture-first Slack ⭐ (the headline)
- DM capture inbox (S3) — quick + session modes.
- Capture-from-bot via message action (S2/§3.2); generalize existing emoji + slash capture.
- Capture confirm card (S4).
- **Design owns:** the full capture UX, the centerpiece of this phase.

### Phase 2 — Primitive interaction
- App Home dashboard (S2), Create Relay modal (S5), Claim/receive flow (S6).
- **Design owns:** dashboard IA + modal flows.

### Phase 3 — Notification & nudge layer
- Unify notification cards (S7) on the card system; ship nudge cards (S8) + app deep-link landing
  routes in `relay-app`. Wire to existing `nudges.py` triggers + `mcp_events` telemetry.

### Phase 4 — Prove portability: Microsoft Teams adapter
- Stand up the Teams adapter against the Phase-0 layer; render the same cards as Adaptive Cards.
- Validates that the base actually extends. Surfaces any Slack-specific assumptions to fix upstream.

---

## 9. Open questions for design to explore

1. **Capture inbox model:** is the bot DM a transient stage, a persistent inbox, or a mini App Home? How is staged context shown and edited before commit?
2. **Session capture lifecycle:** how do you start/stop, see what's accrued, and recover an abandoned session?
3. **Relay vs. Pulse decision:** at capture time, how does the user choose the destination without friction? Smart default + override?
4. **Nudge frequency & dismissal:** what makes a nudge feel like a helpful colleague vs. spam? Snooze model?
5. **Connect-state degradation:** what does an unlinked user see when they try to capture? How do we make linking a one-tap detour?
6. **Cross-platform parity bar:** which surfaces must be identical across Slack/Teams, and which may differ?

---

## 10. What exists today (so design isn't starting from zero)

- Slack OAuth, signed identity linking, signature verification — **built**.
- `/relay log|decision|action|capture` slash commands + 📌✅🧠 emoji capture — **built** (the capture
  baseline to expand from).
- Claim-approval interactive DMs (approve/deny) — **built** (the notification baseline).
- Nudge trigger engine + telemetry table — **built** server-side (needs a chat delivery adapter).
- Admin digest to a channel — **built**.
- 58-tool MCP surface defining every primitive's shape — **built** (the behavioral reference for what
  chat surfaces should do).

**Not built:** the use-case layer that unifies them, conversational/DM capture, App Home dashboard,
the card design system, nudge-to-app delivery, and any second platform.
