Put your own page, such as a fractions game or a lab simulation, inside a course activity. An agent can sit beside it, and what learners do there goes into the research export.
Courses are set up in the dashboard or with the CLI, not with API keys. Your page never learns who the learner is; VIABLE records its events with the learner.
Set up the activity
- Serve your page over https. Let
https://page.viablelearning.orgframe it, for example withContent-Security-Policy: frame-ancestors https://page.viablelearning.org. - Add the panel. In Teach → Courses, open the course, add an activity, and add an Embedded page panel with your page's address.
- Choose what the agent is shown. If the activity has an agent, pick Its events, Nothing or Custom.
- Say how it ends. Turn on It says when the learner is done if your page reports completion. Otherwise learners press "I'm done".
Serve the page from exactly that address: a redirect to another origin cuts the connection. The frame is sandboxed (allow-scripts allow-same-origin allow-forms allow-popups allow-pointer-lock) and gets no referrer.
Add the bridge
Any page works as it is. To record what happens and tell the agent, add a few postMessage calls. The panel's Connect your page (optional) offers them to copy:
let session = null
window.addEventListener('message', (e) => {
if (e.origin !== 'https://page.viablelearning.org') return
if (e.data?.viable === 1 && e.data.type === 'hello') session = e.data.session
})
const viable = (message) => window.parent.postMessage({ viable: 1, ...message }, 'https://page.viablelearning.org')
viable({ type: 'hello' }) // asks for hello again, if you started listening late
viable({ type: 'event', verb: 'answered', object: 'level-2', success: true, score: 1, max_score: 1 })
viable({ type: 'state', data: { level: 2, pieces: 3 } })
viable({ type: 'ask', text: 'Can I get a hint?' })
session is a random ID for this visit. Ignore other origins.
type |
What happens |
|---|---|
event |
Kept as an event: a verb and optionally object, score, max_score, success, completion, response, duration_ms and data. |
state |
What your page shows now, kept at most every 5 seconds. |
ask |
Puts text in the chat box for the learner to send. Nothing is sent for them. |
hello |
Asks for the hello again if your page started listening late. |
Prefer xAPI verbs: attempted, answered, completed, passed, failed, progressed, interacted. data holds up to 20 fields of numbers, true/false values or strings up to 200 characters. With It says when the learner is done, the first completed event, or one with completion: true, counts toward the activity being done.
What the AI sees
With Its events, when a learner asks while your panel is open, the step writing the reply sees your page's last ten events and its latest state. Custom sets 0–20 events and whether the state is included. The agent's Profile sets where this enters the prompt, and any step can read it as {{context.workspace}}. Learners are told on the panel what the agent sees.
What gets recorded
Events and states are kept with the learner, course, activity and activity version, at every recording level. The research export has them in workspace_events.csv. When a study runs in the course, its consent and conditions apply as in any activity.
- Activities: build the activity around your page.
- Export: download the events with the course's data.
