Skip to content

Start and continue conversations in the dashboard #1200

Description

@dcramer

Summary

People should be able to start a conversation in the Junior dashboard or open a conversation that started in Slack and continue it from the dashboard without losing context.

The dashboard is the complete transcript. Slack remains a delivery surface and may show only the Slack-originated parts of the conversation.

User story

As a conversation participant, I can open a Slack-started conversation in Junior, see its complete history, continue it from the dashboard, and later resume from Slack without losing context. Messages sent from the dashboard inherit the conversation's visibility but are not automatically copied into Slack.

Expected experience

Start in the dashboard

  • A user selects New conversation.
  • The conversation is public by default and has no provider Location, so people can share a link.
  • Private dashboard create remains a later product option (setting or UI control).
  • The submitted message is accepted durably and appears immediately as pending.
  • Junior's replies appear in the dashboard transcript.

Continue a Slack conversation in the dashboard

  • A Slack conversation includes an Open in Junior link.
  • The dashboard opens the same conversation and shows its complete transcript.
  • Messages identify whether they came from Slack or the dashboard.
  • The composer explains the conversation's visibility and that dashboard replies stay in Junior.
  • A dashboard message inherits the conversation's existing public or private visibility.
  • Junior's dashboard reply appears in the shared transcript but is not copied into Slack.

Return to Slack

  • A later Slack message continues the same conversation.
  • Junior receives the full conversation history, including dashboard messages and replies.
  • Slack replies include a link to the complete dashboard transcript.
  • When dashboard-only activity occurred since the last Slack turn, the Slack reply indicates that additional activity is available in Junior.

Unsubscribe from a Slack thread

  • Existing thread stop / opt-out behavior (!stop, clear stop/unsubscribe language, and classifier opt-out) is redefined as unsubscribe from the Slack location, not end the conversation.
  • After unsubscribe, Junior stops passive subscribed-thread participation in that Slack thread and cancels related resource watches for it.
  • The canonical conversation remains available in the dashboard, including full history and continued dashboard turns.
  • An explicit Slack mention can re-subscribe / re-engage the Slack location using the existing direct-mention re-engagement path.
  • Stop does not archive, delete, or privatize the conversation, and it does not block dashboard continuation.

Product decision

  • Dashboard-started conversations default to public so links are shareable.
  • Write access remains participant-only; public read alone does not grant write.
  • Private dashboard create is deferred to a later setting or UI control.
  • Slack thread stop means leave the Slack surface; the conversation record stays intact.

Access rules

  • Conversation visibility controls who can read its content.
  • Only verified participants can add dashboard messages.
  • Public read access alone does not grant write access.
  • Browser retries and refreshes must not create duplicate messages or turns.

Acceptance criteria

  • A user can create a public conversation from the dashboard without Slack installed.
  • Follow-up: a user can create or mark a dashboard conversation private from the UI.
  • A verified participant can open and continue a Slack-started conversation from the dashboard.
  • Slack and dashboard messages appear in one ordered dashboard transcript with clear source attribution.
  • Dashboard messages inherit the conversation's visibility.
  • Dashboard messages and replies do not call provider delivery automatically.
  • A later Slack turn uses dashboard activity as agent context.
  • Slack provides a clear path to the complete transcript when dashboard-only activity exists.
  • Non-participants cannot add messages, including to publicly readable conversations.
  • Repeated submissions with the same idempotency key create one message and one turn.
  • Pending, completed, failed, retry, and authorization states survive page refreshes and worker continuation.
  • Slack !stop / thread opt-out unsubscribes Junior from that Slack thread only (no passive replies; related resource watches canceled) without ending the conversation.
  • After Slack unsubscribe, participants can still open and continue the same conversation in the dashboard.
  • An explicit Slack mention can re-engage the previously unsubscribed Slack thread.

Design direction

  • One canonical conversation log stores all accepted messages.

  • Source is a tagged, provider-specific description of what produced the work. Slack retains native fields such as threadTs and messageTs; other providers may use different identifiers or have no thread concept.

  • Location is an optional provider-owned container associated with the conversation:

    type Location = {
      id: string;
      provider: string;
      tenantId?: string;
      providerId: string;
    };
  • Conversation visibility is separate from Location.

  • Slack subscribed-thread state is location participation, distinct from conversation lifetime/visibility.

  • Provider adapters own formatting, API calls, attachment loading, status, and external reply delivery.

  • The shared runtime owns history, agent execution, persistence, retries, yields, resumes, and turn completion.

Implementation outline

  1. Introduce the provider-neutral Location read model.
  2. Separate Source, Location, conversation visibility, and reply behavior in durable routing.
  3. Move Slack and local execution onto one shared conversation runtime.
  4. Add durable conversation creation and message APIs for the dashboard.
  5. Add the dashboard composer and source-aware transcript UI.
  6. Redefine existing Slack stop / unsubscribe behavior as leaving the Slack location while preserving the conversation.
  7. Remove legacy Destination contracts and persistence naming.

Non-goals

  • Automatically copying dashboard messages into Slack.
  • Multiple provider Locations for one conversation.
  • Moving a conversation to another provider Location.
  • An explicit Publish to Slack action in the first implementation.
  • Treating Slack unsubscribe as conversation delete/archive.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions