How a hosted tool works
A hosted tool is a web component: one custom HTML element, defined in a JavaScript file, that Voshi loads inside the course page when someone opens your tool. Voshi does everything around it — the LMS integration, hosting your files on a CDN, logging the student in, placement in courses, provisioning, storage, and grade passback. Your code draws the activity and talks to Voshi through one object.
The lifecycle of a launch
- Someone opens your tool from a course. Voshi handles the LMS side and works out who they are, which course they are in, and which of your locations the link points at.
- Voshi loads your code — the version of your tool that course runs — and your styles and templates.
- Voshi constructs your element, passing it one argument: the Voshi API, already loaded with the launch details and ready to call.
- Your element renders whatever the learner should see, reads any saved work from
api.storage, and, when the learner finishes graded work, callsapi.submitGrade().
The page around your element belongs to Voshi. It watches your element's height and tells the LMS, so the frame fits your content — give your element :host { display: block } and it just works.
What your code looks like
The smallest possible tool:
// app.js
class HelloTool extends HTMLElement {
constructor(api) {
super()
this.api = api // keep the Voshi API for later
this.attachShadow({ mode: 'open' }) // your markup and styles live in here
}
connectedCallback() {
const name = this.api.isStaff ? this.api.user.full_name : 'there'
this.shadowRoot.innerHTML = `<p>Hello, ${name}. You opened ${this.api.location.label}.</p>`
}
}
customElements.define('hello-tool', HelloTool)
Three things every tool does, and the AI Builder does them for you:
- The constructor takes
apiand stores it. It attaches a shadow root and nothing else; browsers forbid a constructor from touching the page. - Rendering happens in
connectedCallback, after the element is on the page. Querythis.shadowRoot, neverdocument— your element's markup is inside the shadow root, anddocument.querySelectorcannot see it. This is the most common mistake in hand-written tools. - The tag is registered with
customElements.define. The tag must be lowercase and contain a dash.
A real tool usually keeps its markup in index.html and its styles in styles.css, which Voshi loads for it and hands over as api.assets. See Your tool's files and Assets.
What Voshi does for you
| Need | How it is met |
|---|---|
| Hosting | Your files are served from a CDN. Upload or build, and they are live in the Sandbox. |
| Login and identity | api.user says who launched, with a stable ID. No passwords, no accounts, no sessions to manage. |
| Which course, which activity | api.course and api.location. |
| Saving work | api.storage — four JSON rows per launch, plus files on each. See Storage. |
| Grades | api.submitGrade(). See Grades. |
| Course setup | Automatic. When a course is copied into a new term, its course and location storage come along. |
| Placement in courses | Instructors pick from your locations in a picker Voshi presents. |
| Versions | You publish; courses adopt a version and keep it. See Versions. |
The rules
Hosted tools run inside other people's course pages, so a few things are off limits. Voshi checks what it can at upload time, and the AI Builder already follows them.
- No server, no network calls of your own. Everything your tool needs from the platform comes through
api; the only thing it ever fetches is its own files, throughapi.assets. There is no API key, because there is no server to keep one on. - No libraries, no CDNs, no build step. Your files are plain JavaScript, CSS, and HTML, served exactly as uploaded.
importother files of your own by relative path; a bare name likeimport 'lit'cannot be resolved. - No
localStorageorsessionStorage. Nothing about a learner may be kept in the browser. Useapi.storage. - No
documentqueries, noeval. Work insidethis.shadowRoot. - Keep state in the element unless it must survive between visits, in which case it goes in
api.storage.
Where things happen
Everything about your tool lives in the dashboard: building, testing, locations, versions, logs. There is nothing to configure anywhere else.