You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add channels to Workshop as the second conversation container alongside direct messages. The model: a direct message is exactly one human and one agent, and the agent responds to every message with no mention needed. Every other conversation is a channel, where agents respond only when addressed. Agent attention derives from the container kind alone; there is no per-conversation wake setting.
Why
Today every Workshop conversation behaves like a DM: each accepted inbound message atomically creates a run, so the agent answers everything everywhere. That is correct for the bootstrap direct channel and wrong for any container with more than one human-agent pair. Channels unlock topic separation (a channel per project), multiple agents as members, and eventually multi-human membership, while keeping agent attention deterministic and loop-safe.
Architecture
The schema already anticipates this work: channels has a kind column, explicit channel_memberships exist, the inbound resolver already accepts a group kind, the event vocabulary already covers channel.created / channel.member_added / channel.agent_attached, and runtime resolution already accepts an optional agent id. What this epic adds is the interaction layer:
Lifecycle: a client-facing create-channel route, event-sourced with the existing vocabulary; kind group, private by default, membership fixed at creation.
Mentions: @display-name parsed server-side at message acceptance as the single source of truth, stored on the message payload as resolved principal references.
Wake policy: decided inside the atomic message-acceptance transaction. Direct channels wake on every human message (unchanged). Group channels route by mention first: a message that mentions agents wakes exactly the mentioned agents, regardless of who is engaged; a message that mentions no agent wakes the currently engaged agents; human mentions are notification only. Non-waking messages are appended canonically with a new MESSAGE_ONLY disposition and no run. Agent-authored messages never wake other agents.
Engagement: derived, not stored. A mention engages the agent for the containing scope until it is quiet for a fixed window (900 seconds) or the agent is dismissed via a new channel.agent_dismissed fact. Before threads exist the scope is the channel; once threads land the same rule re-scopes to the thread.
Threads: a nullable thread_root_id on messages, a thread timeline route, and a client thread pane.
Two non-negotiables: the wake decision must live inside the same transaction as message acceptance so replay stays idempotent, and run.accepted gains the woken agent's id so multi-agent channels resolve the correct runtime.
Critical path is 1 → 2 → 3. Each sub-issue is one PR and closes itself with fixes #N.
Out of scope
Multi-human provisioning; membership mutation on existing channels (forking a new channel is the supported flow); public channel discovery; Telegram transport bindings for group channels; agent-to-agent delegation controls; named teams and channel default agents.
Sequencing
Decision 2026-08-19: this epic is deliberately queued behind the memory audit remediation epic (#1013), which runs to completion first. Not stale; work begins when #1013 closes.
Goal
Add channels to Workshop as the second conversation container alongside direct messages. The model: a direct message is exactly one human and one agent, and the agent responds to every message with no mention needed. Every other conversation is a channel, where agents respond only when addressed. Agent attention derives from the container kind alone; there is no per-conversation wake setting.
Why
Today every Workshop conversation behaves like a DM: each accepted inbound message atomically creates a run, so the agent answers everything everywhere. That is correct for the bootstrap direct channel and wrong for any container with more than one human-agent pair. Channels unlock topic separation (a channel per project), multiple agents as members, and eventually multi-human membership, while keeping agent attention deterministic and loop-safe.
Architecture
The schema already anticipates this work:
channelshas akindcolumn, explicitchannel_membershipsexist, the inbound resolver already accepts agroupkind, the event vocabulary already coverschannel.created/channel.member_added/channel.agent_attached, and runtime resolution already accepts an optional agent id. What this epic adds is the interaction layer:group, private by default, membership fixed at creation.@display-nameparsed server-side at message acceptance as the single source of truth, stored on the message payload as resolved principal references.MESSAGE_ONLYdisposition and no run. Agent-authored messages never wake other agents.channel.agent_dismissedfact. Before threads exist the scope is the channel; once threads land the same rule re-scopes to the thread.thread_root_idon messages, a thread timeline route, and a client thread pane.Two non-negotiables: the wake decision must live inside the same transaction as message acceptance so replay stays idempotent, and
run.acceptedgains the woken agent's id so multi-agent channels resolve the correct runtime.Sub-issues
Critical path is 1 → 2 → 3. Each sub-issue is one PR and closes itself with
fixes #N.Out of scope
Multi-human provisioning; membership mutation on existing channels (forking a new channel is the supported flow); public channel discovery; Telegram transport bindings for group channels; agent-to-agent delegation controls; named teams and channel default agents.
Sequencing
Decision 2026-08-19: this epic is deliberately queued behind the memory audit remediation epic (#1013), which runs to completion first. Not stale; work begins when #1013 closes.