Sub-session Workflow and Team Assignment Design
Linear: IMP-1119, child of Snoonu IMP-700.Goal
Let workflows create a depth-one sub-session and let agents choose or change a sub-session’s support team both during creation and directly from the parent session’s Sub-sessions card.Existing behavior
- A sub-session is a normal
chat_sessionsrow withparent_session_idandparent_ticket_number. - The hierarchy is intentionally one level deep. Manual creation and retroactive linking lock the affected parent rows before writing so concurrent operations cannot create a depth-two tree.
- Agent-created sub-sessions are supported only where
InitiateSessionUtils.isSubSessionsEnabledis true: OpenCX ticketing and Zendesk v2. - Any opened sub-session can already use the normal header team switcher, and the existing
POST /backend/chat-session/update/:sessionId/teamroute enforcessessions:writeand the standard support-team assignment behavior. - The parent card renders each child inside a navigation link. Its embedded team badge is therefore intentionally non-interactive.
- Workflows have no sub-session action. The closest action, Create Ticket, inserts a standalone row and does not enforce or emit sub-session behavior.
Design
Create Sub-session workflow action
AddWorkflowActionEnum.CREATE_SUB_SESSION = 'create-sub-session' and register a Create Sub-session non-terminal action in both eager and lazy registries.
Inputs:
parentSessionNumber: number— required and resolved withinctx.organization.id.team: string | undefined— optional support-team lazy select.
sessionId: stringsessionNumber: number
SUB_SESSION_CREATED internal timeline event with the child identifiers plus workflow_id and workflow_run_id, and the parent is socket-refreshed. No new message enum or migration is needed.
Team during dashboard creation
ExtendCreateAgentSessionDto with optional group_id. The agent-initiated creation service validates an explicitly supplied team before any session row or outbound side effect is created and stores it as the initial inbox_id. Omitting the field preserves existing behavior.
The New Session dialog displays an optional Team select only when parentSessionId is present. It lists support-enabled teams, submits group_id for both existing- and new-contact branches, and resets the selection when the dialog closes. The current assignee selection remains authoritative; initial team selection does not invoke automatic distribution.
Inline team assignment from the parent card
The parent Sub-sessions card renders the existingSessionBadge__Team control outside the child’s navigation link, beside the unlink control. The embedded static team badge is hidden only when the external interactive control is shown, avoiding duplicate team labels.
The inline control is gated by sessions:write, independently of sessions-sub-sessions:write: changing ownership is a normal session mutation, while linking and unlinking remain sub-session-management mutations. It calls the existing team update route and assignment service, then refreshes the Sub-sessions SWR query so the card immediately reflects the new team.
Error behavior
- Missing or foreign parent session number: workflow action returns a runtime error and writes nothing.
- Parent is already a sub-session: runtime error and no child.
- Unsupported ticketing integration: runtime error and no child.
- Missing, foreign, deleted, or non-support team: action/service error and no child.
- No team supplied: child is created with
inbox_id = null. - Inline team mutation without
sessions:write: existing route returns 403.
Testing strategy
- Real Postgres workflow-action tests cover the success shape, inherited fields, optional team, all validation failures, tenant isolation, and parent-link concurrency.
- A real workflow-runner test executes the registered action and asserts step output, child linkage, and workflow-attributed timeline data.
- Real agent-initiated service/controller tests cover initial team persistence, omission, invalid teams, and no-orphan guarantees.
- A full-stack Playwright test uses development login plus real backend routes to create a parent, create a team-owned child through the dialog, and change that team inline from the parent card. It also checks that the standalone New Session dialog does not expose the sub-session-only Team field.
- Focused typechecks, lint, formatting, SDK generation checks, and touched-area tests run before commit and PR creation.
Non-goals
- No link/unlink workflow actions.
- No nested sub-sessions.
- No first-message composer inside the workflow action.
- No new shared abstraction, database migration, or public API endpoint.
- No change to automatic assignment strategy; workflows can follow the new action with the existing Assign Session to Support Team action when picker-based routing is desired.