Repository navigation
AutoTutor Prompt Production Rule
This modern agent-selected production starts work on an expectation by offering an explanation, a worked example or teaching figure, and a question about an analogous case. Here, expectation means an authored idea the learner should understand. Expectancy is the model's estimate of the learner's knowledge, expressed as a logit for selection.
The numbered comments connect the pseudocode to objects in the annotated rule below. The competition step belongs to the selector; it is shown between eligibility and execution so the whole instructional decision is visible.
CONSIDER: Explain this expectation, support it, then ask an analogous question.
WHEN
The learner's answer has been evaluated. # [1] interface-event + instructional.assessmentSnapshot
Feedback for that answer has already been produced. # [2] dialogue.utterance with action instruction.feedback
More instruction remains, and no move has been chosen yet. # [3] controller.completionState + absence of instructional.decision
It is time to start a target cycle, rather than continue one. # [3] instructional.cycleStatus.continuable = false
This is the highest-ranked expectation still eligible. # [3] instructional.candidate: eligible + isMaximumWithinKind
No eligible misconception needs priority. # [4] absence of an eligible misconception candidate
ENTER THIS MOVE INTO COMPETITION
Compare learner expectancy + this move's assistance
with the desired instructional target, all in logit units. # [5] expectancyLogit + assistance versus oetLogit
Give closer matches higher selection probability.
Sample one move using the Boltzmann temperature. # [5] selector behavior; enabled by the competition module
IF THIS PRODUCTION IS SELECTED, THEN
Save the target, chosen move, and selection evidence. # [6] instructional.decision
Record the chosen action and begin teaching this expectation. # [7] controller.selectedAction + instructional.activeCycle
Invoke its component primitives. # [8] invoke-action: autotutor.generate-move
Obtain a worked example OR teaching figure.
Generate an explanation aligned with that support.
Generate a question about an analogous case.
Present: explanation, support, question. # [8] generation action's behavior, not extra rule fields
This is one alternative, not a command to supply this much assistance whenever its conditions match. Other instructional moves compete for the same expectation. Target ranking and move competition are separate decisions. The figure-versus-worked-example choice is made inside the rich-content primitive after the composite move is selected.
These are the current runtime fields and values, with explanatory comments added. A factType names a kind of information available to the tutor; slots contains that information. literal requires a specified value, bind gives a matched value a name, and bound requires the same previously named value. That is how the rule keeps the answer, assessment, and expectation aligned.
This block is JSONC for reading. Comments are not valid in TutorScript's plain JSON; the expandable copy below contains the identical production without comments. The rule is supplied by the dynamic controller, not pasted into an AutoTutor lesson's authored rule array.
Uncommented JSON — exact current runtime production
{
"id": "instruction.dynamic.agent.expectation.start.instruction.dynamic.explanation-rich-question",
"module": "dialogue.instructional-competition",
"when": [
{
"factType": "interface-event",
"slots": {
"eventType": {
"type": "literal",
"value": "response-submitted"
},
"eventId": {
"type": "bind",
"variable": "snapshotId"
}
}
},
{
"factType": "instructional.assessmentSnapshot",
"slots": {
"snapshotId": {
"type": "bound",
"variable": "snapshotId"
}
}
},
{
"factType": "dialogue.utterance",
"slots": {
"eventId": {
"type": "bound",
"variable": "snapshotId"
},
"action": {
"type": "literal",
"value": "instruction.feedback"
},
"speaker": {
"type": "literal",
"value": "tutor"
}
}
},
{
"factType": "controller.completionState",
"slots": {
"completed": {
"type": "literal",
"value": false
}
}
},
{
"type": "not",
"pattern": {
"factType": "instructional.decision",
"slots": {
"snapshotId": {
"type": "bound",
"variable": "snapshotId"
}
}
}
},
{
"factType": "instructional.cycleStatus",
"slots": {
"snapshotId": {
"type": "bound",
"variable": "snapshotId"
},
"continuable": {
"type": "literal",
"value": false
}
}
},
{
"factType": "instructional.candidate",
"slots": {
"snapshotId": {
"type": "bound",
"variable": "snapshotId"
},
"targetKind": {
"type": "literal",
"value": "expectation"
},
"targetId": {
"type": "bind",
"variable": "targetId"
},
"targetKey": {
"type": "bind",
"variable": "targetKey"
},
"currentValue": {
"type": "bind",
"variable": "currentValue"
},
"eligible": {
"type": "literal",
"value": true
},
"isMaximumWithinKind": {
"type": "literal",
"value": true
}
}
},
{
"type": "not",
"pattern": {
"factType": "instructional.candidate",
"slots": {
"snapshotId": {
"type": "bound",
"variable": "snapshotId"
},
"targetKind": {
"type": "literal",
"value": "misconception"
},
"eligible": {
"type": "literal",
"value": true
}
}
}
},
{
"factType": "instructional.candidate",
"slots": {
"snapshotId": {
"type": "bound",
"variable": "snapshotId"
},
"targetKind": {
"type": "literal",
"value": "expectation"
},
"targetId": {
"type": "bound",
"variable": "targetId"
},
"eligible": {
"type": "literal",
"value": true
},
"expectancyLogit": {
"type": "bind",
"variable": "expectancyLogit"
},
"oetLogit": {
"type": "bind",
"variable": "oetLogit"
}
}
},
{
"factType": "instructional.move",
"slots": {
"action": {
"type": "literal",
"value": "instruction.dynamic.explanation-rich-question"
},
"assistance": {
"type": "bind",
"variable": "assistance"
}
}
},
{
"factType": "session.turnState",
"slots": {
"turnCount": {
"type": "bind",
"variable": "turnNumber"
}
}
}
],
"then": [
{
"type": "assert-fact",
"persist": true,
"identitySlots": [
"snapshotId"
],
"fact": {
"factType": "instructional.decision",
"slots": {
"snapshotId": {
"type": "variable",
"name": "snapshotId"
},
"targetKind": {
"type": "literal",
"value": "expectation"
},
"targetId": {
"type": "variable",
"name": "targetId"
},
"targetKey": {
"type": "variable",
"name": "targetKey"
},
"action": {
"type": "literal",
"value": "instruction.dynamic.explanation-rich-question"
},
"transition": {
"type": "literal",
"value": "start"
},
"sourceRuleId": {
"type": "literal",
"value": "instruction.dynamic.agent.expectation.start.instruction.dynamic.explanation-rich-question"
},
"reason": {
"type": "literal",
"value": "oet-distance"
},
"expectancyLogit": {
"type": "variable",
"name": "expectancyLogit"
},
"assistance": {
"type": "variable",
"name": "assistance"
},
"oetLogit": {
"type": "variable",
"name": "oetLogit"
},
"utility": {
"type": "variable",
"name": "utility"
},
"temperature": {
"type": "variable",
"name": "temperature"
},
"selectionProbability": {
"type": "variable",
"name": "selectionProbability"
}
}
}
},
{
"type": "assert-fact",
"persist": true,
"identitySlots": [],
"fact": {
"factType": "controller.selectedAction",
"slots": {
"targetType": {
"type": "literal",
"value": "expectation"
},
"targetId": {
"type": "variable",
"name": "targetId"
},
"targetKey": {
"type": "variable",
"name": "targetKey"
},
"action": {
"type": "literal",
"value": "instruction.dynamic.explanation-rich-question"
},
"sourceRuleId": {
"type": "literal",
"value": "instruction.dynamic.agent.expectation.start.instruction.dynamic.explanation-rich-question"
},
"snapshotId": {
"type": "variable",
"name": "snapshotId"
}
}
}
},
{
"type": "assert-fact",
"persist": true,
"identitySlots": [],
"fact": {
"factType": "instructional.activeCycle",
"slots": {
"cycleId": {
"type": "variable",
"name": "snapshotId"
},
"targetKind": {
"type": "literal",
"value": "expectation"
},
"targetId": {
"type": "variable",
"name": "targetId"
},
"targetKey": {
"type": "variable",
"name": "targetKey"
},
"stage": {
"type": "literal",
"value": "DYNAMIC"
},
"priorValue": {
"type": "variable",
"name": "currentValue"
},
"startedAtTurn": {
"type": "variable",
"name": "turnNumber"
},
"cycleTurnCount": {
"type": "literal",
"value": 0
},
"status": {
"type": "literal",
"value": "active"
}
}
}
},
{
"type": "invoke-action",
"actionId": "autotutor.generate-move"
}
]
}The production is generated by createSparcDynamicInstructionRules. Competition is implemented by selectCompetitiveActivation; component composition is defined in sparcMoveDefinitions.ts. See TutorScript's selection cycle for the surrounding flow.
Getting Started
- Teacher: First Hour
- Quick Start: Content Creation
- Class Setup and Assignment Workflow
- Anki Import Guide
Authoring Reference
- Introduction to TutorScript
- Content Creation Reference Tables
- Stimulus Files (Content)
- Trial Types Reference
- Audio and Speech Settings
Advanced Authoring
Reports and Help
- Researcher Guide
- TDF field tables
- Gaze tracking prototype
- Data Output and Reports
- Data Privacy, IRB, and FERPA Notes
- Experiment Routes
- SPARC Instructional Cycles
- Public Demonstrations
- Learning Algorithms Reference
- Video Units and Adaptive Logic
- AutoTutor Sessions
- Deployment Guide
- Security Audit Operations
- Remote Install
- Runtime Settings Reference
- Admin Features Reference
- Custom Help Page Setup
- Troubleshooting
- Local Install
- Developer Reference Guide
- Learning Algorithms Reference
- Introduction to TutorScript
- AutoTutor Sessions
- Runtime Settings Reference
- Deployment Guide
- Glossary
- FAQ
- Screenshots
- License Guidance
- Implementation Cost Analysis
- GitHub Repository
- GitHub Issues
{ "id": "instruction.dynamic.agent.expectation.start.instruction.dynamic.explanation-rich-question", // [5] The selector compares this instructional alternative with other eligible moves for ONE target. "module": "dialogue.instructional-competition", "when": [ // [1] Start with a submitted answer. Remember its event ID so later conditions use the same assessment. { "factType": "interface-event", "slots": { "eventType": {"type":"literal","value":"response-submitted"}, "eventId": {"type":"bind","variable":"snapshotId"} } }, // [1] That answer must already have been evaluated. { "factType": "instructional.assessmentSnapshot", "slots": {"snapshotId":{"type":"bound","variable":"snapshotId"}} }, // [2] Its tutor feedback must already exist before this move can be selected. { "factType": "dialogue.utterance", "slots": { "eventId": {"type":"bound","variable":"snapshotId"}, "action": {"type":"literal","value":"instruction.feedback"}, "speaker": {"type":"literal","value":"tutor"} } }, // [3] There is still instruction to do. {"factType":"controller.completionState","slots":{"completed":{"type":"literal","value":false}}}, // [3] Do not make a second instructional decision for this assessment. { "type": "not", "pattern": {"factType":"instructional.decision","slots":{"snapshotId":{"type":"bound","variable":"snapshotId"}}} }, // [3] This is a START rule: the previous target cycle cannot continue. A separate rule handles continuation. { "factType": "instructional.cycleStatus", "slots": {"snapshotId":{"type":"bound","variable":"snapshotId"},"continuable":{"type":"literal","value":false}} }, // [3] Choose the highest-ranked eligible expectation at this boundary. // An expectation is an authored idea the learner should understand, not a probability. // isMaximumWithinKind refers to target-policy ranking, not simply the highest knowledge score. { "factType": "instructional.candidate", "slots": { "snapshotId": {"type":"bound","variable":"snapshotId"}, "targetKind": {"type":"literal","value":"expectation"}, "targetId": {"type":"bind","variable":"targetId"}, "targetKey": {"type":"bind","variable":"targetKey"}, "currentValue": {"type":"bind","variable":"currentValue"}, "eligible": {"type":"literal","value":true}, "isMaximumWithinKind": {"type":"literal","value":true} } }, // [4] An eligible misconception takes priority, so this expectation rule must wait. { "type": "not", "pattern": { "factType": "instructional.candidate", "slots": { "snapshotId": {"type":"bound","variable":"snapshotId"}, "targetKind": {"type":"literal","value":"misconception"}, "eligible": {"type":"literal","value":true} } } }, // [5] For that SAME expectation, retrieve learner expectancy and the instructional target (OET), in logits. { "factType": "instructional.candidate", "slots": { "snapshotId": {"type":"bound","variable":"snapshotId"}, "targetKind": {"type":"literal","value":"expectation"}, "targetId": {"type":"bound","variable":"targetId"}, "eligible": {"type":"literal","value":true}, "expectancyLogit": {"type":"bind","variable":"expectancyLogit"}, "oetLogit": {"type":"bind","variable":"oetLogit"} } }, // [5] Retrieve the assistance assigned to this composite move, also in logit units. // The rule can compete; these conditions do not guarantee it will win. { "factType": "instructional.move", "slots": { "action": {"type":"literal","value":"instruction.dynamic.explanation-rich-question"}, "assistance": {"type":"bind","variable":"assistance"} } }, {"factType":"session.turnState","slots":{"turnCount":{"type":"bind","variable":"turnNumber"}}} ], "then": [ // [6] If selected, save what was chosen, for which target, and why. persist makes the decision durable. { "type": "assert-fact", "persist": true, "identitySlots": ["snapshotId"], "fact": { "factType": "instructional.decision", "slots": { "snapshotId": {"type":"variable","name":"snapshotId"}, "targetKind": {"type":"literal","value":"expectation"}, "targetId": {"type":"variable","name":"targetId"}, "targetKey": {"type":"variable","name":"targetKey"}, "action": {"type":"literal","value":"instruction.dynamic.explanation-rich-question"}, "transition": {"type":"literal","value":"start"}, "sourceRuleId": { "type": "literal", "value": "instruction.dynamic.agent.expectation.start.instruction.dynamic.explanation-rich-question" }, "reason": {"type":"literal","value":"oet-distance"}, "expectancyLogit": {"type":"variable","name":"expectancyLogit"}, "assistance": {"type":"variable","name":"assistance"}, "oetLogit": {"type":"variable","name":"oetLogit"}, // [6] The selector supplies these three values. They record the competition, not an AI wording choice. // utility = -abs(expectancyLogit + assistance - oetLogit); temperature controls sampling. "utility": {"type":"variable","name":"utility"}, "temperature": {"type":"variable","name":"temperature"}, // Chance of selecting this move among eligible alternatives; NOT the learner's probability of success. "selectionProbability": {"type":"variable","name":"selectionProbability"} } } }, // [7] Tell the generation action which move and expectation were selected. { "type": "assert-fact", "persist": true, "identitySlots": [], "fact": { "factType": "controller.selectedAction", "slots": { "targetType": {"type":"literal","value":"expectation"}, "targetId": {"type":"variable","name":"targetId"}, "targetKey": {"type":"variable","name":"targetKey"}, "action": {"type":"literal","value":"instruction.dynamic.explanation-rich-question"}, "sourceRuleId": { "type": "literal", "value": "instruction.dynamic.agent.expectation.start.instruction.dynamic.explanation-rich-question" }, "snapshotId": {"type":"variable","name":"snapshotId"} } } }, // [7] Retain this expectation as the active teaching focus for subsequent turns. // priorValue stores its current evaluated coverage for later progress comparisons. { "type": "assert-fact", "persist": true, "identitySlots": [], "fact": { "factType": "instructional.activeCycle", "slots": { "cycleId": {"type":"variable","name":"snapshotId"}, "targetKind": {"type":"literal","value":"expectation"}, "targetId": {"type":"variable","name":"targetId"}, "targetKey": {"type":"variable","name":"targetKey"}, "stage": {"type":"literal","value":"DYNAMIC"}, "priorValue": {"type":"variable","name":"currentValue"}, "startedAtTurn": {"type":"variable","name":"turnNumber"}, "cycleTurnCount": {"type":"literal","value":0}, "status": {"type":"literal","value":"active"} } } }, // [8] Invoke the action that carries out the selected move using component primitives. // Learner-facing order: explanation, worked example OR teaching figure, then an analogous question. // The rich-content primitive chooses the support form; this rule does not require an image every time. {"type":"invoke-action","actionId":"autotutor.generate-move"} ] }