Feature detail
Per-question experiment gating
Deterministic cohort resolution, exposure records, and served-question metadata for experimental or LLM-variant questions — so gated content stays visible, auditable, and WF-testable before it reaches learners.
Worked example
Gated experiment exposure
Same turn + same source question produce the same resolution key and arm; served questions carry experiment metadata that WF can gate on.
Input
{
"resolution": {
"sessionId": "sess-42",
"currentTurn": 7,
"sourceQuestionId": "factoring-q1",
"conceptId": "factoring",
"targetLayer": "support"
},
"experimentKey": "llm-support-v1"
}Output
{
"resolutionKey": "sess-42:7:factoring-q1:factoring:support",
"arm": "control",
"exposure": {
"exposureId": "exp-0001",
"resolutionKey": "sess-42:7:factoring-q1:factoring:support",
"learnerId": "learner@example.edu",
"sessionId": "sess-42",
"experimentKey": "llm-support-v1",
"cohortMode": "randomized",
"resolvedArm": "control",
"conceptId": "factoring",
"sourceQuestionId": "factoring-q1",
"servedQuestionId": "factoring-q1",
"unitId": "unit-3",
"sectionId": "section-3a",
"targetLayer": "support",
"interventionKind": "llm-support",
"createdAt": "2026-04-18T12:30:00Z"
},
"servedQuestion": {
"id": "factoring-q1",
"sourceQuestionId": "factoring-q1",
"experimentKey": "llm-support-v1",
"experimentArm": "control",
"exposureId": "exp-0001",
"questionOrigin": "llm-generated",
"interventionKind": "llm-support"
}
}Real source excerpt
Intervention cohort resolution and exposure contracts
export type WorkflowInterventionCohortMode = 'off' | 'randomized' | 'control' | 'treatment';
export type ActiveWorkflowInterventionCohortMode = Exclude<WorkflowInterventionCohortMode, 'off'>;
export type ResolvedWorkflowInterventionArm = 'control' | 'treatment';
export interface WorkflowInterventionResolutionInput {
sessionId: string;
currentTurn: number;
sourceQuestionId: string;
conceptId: string;
targetLayer?: string | null;
}
export interface WorkflowInterventionExposureMetadata<
TCohortMode extends string = ActiveWorkflowInterventionCohortMode,
> {
exposureId: string;
resolutionKey: string;
cohortMode: TCohortMode;
resolvedArm: ResolvedWorkflowInterventionArm;
}
export interface WorkflowInterventionExposureRecord<
TExperimentKey extends string = string,
TInterventionKind extends string = string,
TCohortMode extends string = ActiveWorkflowInterventionCohortMode,
> extends WorkflowInterventionExposureMetadata<TCohortMode> {
learnerId: string;
sessionId: string;
experimentKey: TExperimentKey;
conceptId: string;
sourceQuestionId: string;
servedQuestionId: string;
unitId: string;
sectionId: string;
targetLayer: string;
interventionKind: TInterventionKind;
createdAt: string;
}
export interface WorkflowInterventionExposureStoreInput<
TExperimentKey extends string = string,
TInterventionKind extends string = string,
TCohortMode extends string = ActiveWorkflowInterventionCohortMode,
> {
learnerId: string;
sessionId: string;
experimentKey: TExperimentKey;
cohortMode: TCohortMode;
resolutionKey: string;
conceptId: string;
sourceQuestionId: string;
servedQuestionIdByArm: Record<ResolvedWorkflowInterventionArm, string>;
unitId: string;
sectionId: string;
targetLayer: string;
interventionKind: TInterventionKind;
}
export interface WorkflowInterventionServedQuestionMetadata<
TExperimentKey extends string = string,
TQuestionOrigin extends string = string,
TInterventionKind extends string = string,
> {
experimentKey: TExperimentKey;
experimentArm: ResolvedWorkflowInterventionArm;
exposureId: string;
sourceQuestionId: string;
questionOrigin: TQuestionOrigin;
interventionKind?: TInterventionKind;
}
export interface WorkflowInterventionQuestionLike {
id: string;
sourceQuestionId?: string | null;
}
export interface WorkflowInterventionQuestionOverride<
TQuestion,
TCohortMode extends string = ActiveWorkflowInterventionCohortMode,
> {
question: TQuestion;
served: boolean;
rejected: boolean;
reason: string;
cohortMode?: TCohortMode;
resolvedArm?: ResolvedWorkflowInterventionArm;
exposureId?: string | null;
resolutionKey?: string | null;
}