Skip to content

Chat cards (Slack & Teams)

Operators

Telha speaks to people through one bot in Slack and Microsoft Teams. Every message is a card: a clarification to answer, a grounded answer with receipts, or a notification that memory changed. This page is the visual catalogue of those cards, what they contain, and the rules that govern where they can go.

Build status

The clarification and grounded answer cards ship today in the @telha/clarify-bot package (slack_blocks.ts, cards.ts). The three memory cards (Memory Change, Weekly Memory Brief, Saved Answer Updated) and the [Watch this] action are specified in the memory-cards spec (Phase 3d) and being wired. The layouts below are the design of record.

Normative specs

Card templates and actions: memory-cards. Transport, identity binding, hook verification, and the Block Kit primitives: chat-delivery-surface. Producers: memory-watch.

The delivery rule: DM-only, RBAC-checked

Two rules apply to every card, and neither is configurable:

  • Every card is delivered to an RBAC-checked person's DM. A shared or team watch fans out a DM to each authorised member; a member who fails the fire-time access check receives nothing.
  • No card ever posts to a channel. Channel membership is administered in Slack/Teams, outside Telha's RBAC and audit, so it is not an access boundary. Even entity names and counts are content, so there is no channel-post code path to leak through.

The cards are built from authentic modern Block Kit blocks (header, section, context, fields, actions) with a Teams Adaptive Card twin. Delivery is idempotent: one live card per fire per recipient.

The clarification card

When ingestion cannot pin a fact (an ambiguous or conflicting date, an undated scan), Telha applies its best guess at reduced confidence and asks the right person to confirm. See Clarifications and the Clarify bot runbook.

T
TelhaApp 9:41 AM
Quick check on the Meridian contract

The renewal clause looks like it takes effect next quarter, but the document is not explicit. When should it be in force from?


📎 Evidence · Meridian_MSA_2026.pdf, page 4
1 April 2026 1 July 2026 Pick another date This isn't right

One tap records the answer append-only as evidence, with the responder's verified corporate identity (from Entra, not a chat display name). High-stakes facts require a second confirmation; disagreements route to a steward.

The grounded answer card

When someone asks a question, Telha answers from planned evidence and shows the receipts: the claims it made, the sources behind them, and the verification verdict. See Verified answers.

T
TelhaApp 10:12 AM

Meridian's liability cap is EUR 5,000,000, raised from EUR 2,000,000 by the 2026 amendment, effective 1 April 2026.


📎 Evidence
Meridian_MSA_Amendment_2026.pdf · clause 11.2
"...the aggregate liability cap shall be EUR 5,000,000..."
✅ 3 claims verified against source
Open full trace Watch this

The [Watch this] button (Phase 3d) creates a watch owned by the person who tapped it, so they hear about it the next time this state changes.

Memory Change card

A watch fired. The card names the scope, lists what changed by event kind with counts, and links into the evidence. Delivered to the watch owner's DM (or fanned out to a team watch's authorised members).

T
TelhaApp 2:03 PM
Memory changed · Meridian
Facts changed
2
New source versions
1
Clarifications resolved
1
🕑 Coalesced over the last hour · watch: "Anything about Meridian"
View evidence Show timeline Stop watching

The payload behind this card carries only ids and event kinds. The bot fetches the human-readable detail at render time, filtered to what the recipient is allowed to see.

Weekly Memory Brief

A weekly-cadence watch is the brief: the habit-forming digest of what moved in your corner of the world. Fires are deduplicated per recipient, so a change matched by an entity watch, a label watch, and a query watch appears once.

T
TelhaApp Mon 8:00 AM
Weekly Memory Brief · Supplier risks
Facts changed
14
Clarifications resolved
3
Answers gone stale
2
Conflicts for review
1

Meridian exposure raised · Northwind contract superseded · 2 undated incidents clarified
Open changes

Saved Answer Updated card

The differentiator: an answer you saved knows when its evidence moved, and tells you exactly which claims changed, old value to new. Delivered to the owner's DM only, filtered to their RBAC.

T
TelhaApp 4:20 PM
A saved answer is now partially stale

"What is our exposure to Meridian?" has changed since you saved it.


🧾 What changed
Liability cap
EUR 2m → EUR 5m
Effective-date clarification
has now bound
Refresh answer View changed claims Keep original

A severity: material transition escalates the header emphasis; it does not change who is notified. [Refresh answer] spends generation budget, so it always confirms first, and it only appears for a role that holds generation authority. A viewer sees [View changed claims] and a deep link instead of a dead-end button.

Card actions and the write-action security model

Buttons that only read (View evidence, Show timeline, Open changes, View changed claims) are authenticated deep links into the web app. Buttons that write ([Watch this], [Refresh answer], [Stop watching]) run under a strict, least-privilege flow:

sequenceDiagram
    autonumber
    participant U as Person (Slack/Teams)
    participant Bot as Telha bot
    participant Core as telha-core
    U->>Bot: taps a write action (nonce)
    Bot->>Bot: verify platform signature, then ack
    Bot->>Bot: bind callback identity to a tenant PERSON
    Bot->>Core: mint single-use action token (aud core.card_write_action)
    Core->>Core: execute AS that person, re-check authority
    Core-->>Bot: done, or rejected (expired, replay, wrong action or target, lost authority)

The tenant service token never performs the write. The bot mints a short-lived (~120s), single-use, person-and-action-and-target-scoped internal token; core alone decides whether that person is allowed to do it, and rejects on any mismatch, replay, expiry, or lost permission. Blast radius of a leaked token: one person, one action, one target, once.

Teams parity

Every Slack Block Kit card has a Microsoft Teams Adaptive Card twin with the same content, the same actions, and the same {kind, ..., nonce} action payloads. Delivery, verification, and the DM-only rule are identical across both surfaces.

Configuration

Cards reuse the clarify-bot's channel credentials and card_span_max_chars, plus [memory_cards]: brief_max_lines (25, with an explicit "+N more"), refresh_confirm (true), and action_token_ttl_secs (120). See the Clarify bot runbook for install and credentials.