[{"data":1,"prerenderedAt":1001},["ShallowReactive",2],{"docs-index":3,"docs-page-connect\u002Fembed":984},[4,102,343,490,671,828,929],{"id":5,"title":6,"lead":7,"pages":8},"start","Get started","What VIABLE is made of, and its words.",[9,42],{"path":10,"title":11,"description":12,"updated":13,"minutes":14,"sections":15},"start\u002Fkey-ideas","Key ideas","Learn the four parts VIABLE is made of, the ways to reach them, and who does what, so you know where to start.","2026-10-29",2,[16,19,22,26,30,34,38],{"id":17,"title":17,"text":18},"","VIABLE sits between AI models and learners. It turns what a teacher or researcher intends into what the AI does with each learner, and keeps the evidence, for K-12 classes, university courses, adult learning, and libraries, museums and websites.",{"id":20,"title":21,"text":17},"the-four-parts","The four parts",{"id":23,"title":24,"text":25},"1-agent-how-the-ai-works","1. Agent: how the AI works","An **agent** is an AI made of steps: it can search a knowledge base, check its reply with a **VETTING** step, then answer. Each publish is a numbered version, and learners always meet the published one. [Your first agent](\u002Fdocs\u002Fbuild\u002Ffirst-agent)",{"id":27,"title":28,"text":29},"2-activity-what-learners-do","2. Activity: what learners do","A **course** is one link a class opens all term. Each **activity** in it puts the work, such as **Writing** or **Questions**, beside the AI, and **How the AI helps** says what it is for and how far the AI may go. A library can put an agent on a **chat page** instead, with no sign-in. [Your first class](\u002Fdocs\u002Fteach\u002Ffirst-class)",{"id":31,"title":32,"text":33},"3-study-what-a-study-decides","3. Study: what a study decides","A **study** sits over courses or a chat page. It asks for consent, decides who gets which version, and pins each agent's version while it runs. [Your first study](\u002Fdocs\u002Fresearch\u002Ffirst-study)",{"id":35,"title":36,"text":37},"4-evidence-what-is-recorded","4. Evidence: what is recorded","Every **run** keeps each step and VETTING round. Learners' messages and the replies are **turns**, kept beside their **work**. Researchers code them and download one documented export, by learner code. [The research export](\u002Fdocs\u002Fresearch\u002Fexport)",{"id":39,"title":40,"text":41},"who-does-what","Who does what","Who What they do Where they work Teacher, librarian, workshop lead Runs classes, follows progress **Teach**: Courses, Question sets, Learners Researcher Runs studies and their data **Research**: Studies, Coding, Export Builder, learning designer Makes and tests agents **Build**: Agents, Knowledge App developer Connects an app **Build → Apps**, and the API Owner Members, keys and costs **Operate**, **Account** Learners need no account: they open one link. These are jobs, not permissions. A member's project role decides what they can change, and a course can be shared with one teacher. See [Memb",{"path":43,"title":44,"description":45,"updated":13,"minutes":46,"sections":47},"start\u002Fglossary","Glossary","Look up the words VIABLE uses on screen and in these docs, each in one line, with a link to where it is explained.",3,[48,50,54,58,62,66,70,74,78,82,86,90,94,98],{"id":17,"title":17,"text":49},"The words VIABLE uses on screen and in these docs, one line each. Use it when a term is new to you.",{"id":51,"title":52,"text":53},"a","A","**Activity**: One thing to do in a course: a [lesson, pre-test, post-test or survey](\u002Fdocs\u002Fteach\u002Factivities). **Agent**: An [AI workflow made of steps](\u002Fdocs\u002Fbuild\u002Ffirst-agent). Learners and apps meet its published version. **Agent test**: A [case](\u002Fdocs\u002Fbuild\u002Fagent-tests) (what a learner says, what a good reply does) run against a version of an agent, its reply rated pass or fail by a judge model. **Agent profile**: An agent's name, avatar, greeting, suggested questions and notice, shown on its [chat page](\u002Fdocs\u002Fbuild\u002Fchat-pages) and in activities. **AI key**: The [API key](\u002Fdocs\u002Fproject\u002Fkeys",{"id":55,"title":56,"text":57},"c","C","**Chat page**: An agent published for [open use on websites](\u002Fdocs\u002Fbuild\u002Fchat-pages). Visitors need no account. **Codebook**: [Codes](\u002Fdocs\u002Fresearch\u002Fcoding) with definitions and examples, for coding messages, turns or AI replies. **Comparative study**: A study that sets what learners get, [comparing groups or units](\u002Fdocs\u002Fresearch\u002Fdesigns). Courses only. **Condition**: What one group gets in a comparative study, such as [no AI or another agent](\u002Fdocs\u002Fresearch\u002Fconditions). **Consent**: A learner's decision on a study's [versioned form](\u002Fdocs\u002Fresearch\u002Fconsent). It decides whose data counts. **Co",{"id":59,"title":60,"text":61},"f","F","**Durable skill**: Collaboration, communication or critical thinking at one of four levels, from the Carnegie Skills Progressions, for an [activity to aim at](\u002Fdocs\u002Fteach\u002Fstandards-and-skills). **Final codes**: The codes the team [decides](\u002Fdocs\u002Fresearch\u002Fcoding) where coders differ. **Flag**: A moment a teacher should see, such as a safety reply, under **To look at** in [Progress](\u002Fdocs\u002Fteach\u002Fprogress).",{"id":63,"title":64,"text":65},"h","H","**How the AI helps**: An activity's [goal, standard and how far the AI may go](\u002Fdocs\u002Fteach\u002Fai-helps).",{"id":67,"title":68,"text":69},"l","L","**Learner**: A person known to the project by a learner code, the same on every device. **Learner code**: A learner's ID in data and exports, like `L-7F3KQ2`. Names never leave VIABLE. **Learning component**: A smaller piece a [standard](\u002Fdocs\u002Fteach\u002Fstandards-and-skills) breaks into.",{"id":71,"title":72,"text":73},"m","M","**Member**: A person in a project, with a [role](\u002Fdocs\u002Fproject\u002Fmembers-and-roles). **Misconception**: A common mistake that hinders a math skill, from Eedi's graph, that an activity's AI can [listen for](\u002Fdocs\u002Fteach\u002Fstandards-and-skills). **Model coder**: A model that [codes a sample](\u002Fdocs\u002Fresearch\u002Fcoding) as one more coder, with a confidence and a reason per item.",{"id":75,"title":76,"text":77},"o","O","**Observational study**: A study that [follows how](\u002Fdocs\u002Fresearch\u002Fdesigns) courses or a chat page are used, with no conditions.",{"id":79,"title":80,"text":81},"p","P","**Panel**: What learners work in: [Questions, Writing, Reading or Embedded page](\u002Fdocs\u002Fteach\u002Factivities). **Personal code**: A learner's [code](\u002Fdocs\u002Fteach\u002Fsign-in) on a printed card, like `K7Q2-M9XC`. A personal link skips typing it. **Project**: A team's space for agents, courses, studies, keys and logs, paid for by its [owner](\u002Fdocs\u002Fproject\u002Fmembers-and-roles). **Provider key**: Your own model provider's key, billed there instead of [VIABLE credits](\u002Fdocs\u002Fproject\u002Fkeys-and-costs).",{"id":83,"title":84,"text":85},"r","R","**Research notice**: A study's text people read [before taking part](\u002Fdocs\u002Fresearch\u002Fconsent). Not the agent's notice. **Role**: Owner, editor or viewer: what a [member](\u002Fdocs\u002Fproject\u002Fmembers-and-roles) can change. Viewers see codes, not names. **Run**: One execution of an agent, step by step, listed in its [Run history](\u002Fdocs\u002Fbuild\u002Ftesting).",{"id":87,"title":88,"text":89},"s","S","**Section**: A class period or group, with [its own link](\u002Fdocs\u002Fteach\u002Fsign-in) and opening times. **Section link**: A course link for one section, like `…?section=p2`. **Standard**: A learning standard an [activity aims at](\u002Fdocs\u002Fteach\u002Fstandards-and-skills), kept as it was when chosen. **Study**: A [protocol](\u002Fdocs\u002Fresearch\u002Ffirst-study) over courses or a chat page: consent, design and data.",{"id":91,"title":92,"text":93},"t","T","**Trace**: A [run's record](\u002Fdocs\u002Fconnect\u002Flearners-and-traces) of what each step received and returned, and each VETTING round. **Turn**: A learner's message and the reply, kept in the [export](\u002Fdocs\u002Fresearch\u002Fexport).",{"id":95,"title":96,"text":97},"u","U","**Unit**: A week or topic grouping a course's [activities](\u002Fdocs\u002Fteach\u002Factivities), with optional dates.",{"id":99,"title":100,"text":101},"v","V","**VETTING**: A step where a [reviewer model](\u002Fdocs\u002Fbuild\u002Fvetting) checks each reply against your rules and sends failed ones back to be rewritten. **Visitor**: An anonymous chat page user: one browser on one device, shown in data by a visitor code (`V-…`). [Key ideas](\u002Fdocs\u002Fstart\u002Fkey-ideas): what VIABLE is made of, and who does what. [Your first class](\u002Fdocs\u002Fteach\u002Ffirst-class): make a course and share its link.",{"id":103,"title":104,"lead":105,"pages":106},"teach","Teach","Run a class, a workshop or a seminar with an AI beside the work.",[107,139,166,193,212,243,266,289,316],{"path":108,"title":109,"description":110,"updated":111,"minutes":46,"sections":112},"teach\u002Ffirst-class","Your first class","Make a course, add one activity with an AI, share its link or QR code, and see your first learner in Progress.","2026-10-30",[113,115,119,123,127,131,135],{"id":17,"title":17,"text":114},"This page takes you from nothing to a working class in about ten minutes. Use it the first time you teach with VIABLE.",{"id":116,"title":117,"text":118},"before-you-start","Before you start","You need a project where you are an **owner** or **editor**, and a **published agent** in it: the AI your learners talk with. If you have none yet, start with [Your first agent](\u002Fdocs\u002Fbuild\u002Ffirst-agent).",{"id":120,"title":121,"text":122},"make-the-course","Make the course","**Start a course.** Open [Teach → Courses](\u002Fdashboard\u002Fcourses) and press **New course**. **Name it.** Type a **Name**, such as \"Biology 101 · Period 2 and 3\". **Choose what kind.** Under **What kind of course**, pick **A class over weeks**, **A one-off session** or **A course for research**. **Say who it is for.** Choose **Adults**, **Teenagers** (13 to 17) or **Children** (under 13). **Create it.** Press **Create course**. It starts as a **Draft**, so its link doesn't open for learners yet. **Who it is for** decides how learners get in. Children always get personal codes on printed cards. In ",{"id":124,"title":125,"text":126},"add-an-activity-with-the-ai","Add an activity with the AI","**Pick a kind.** On the **Activities** tab, choose **Writing task**. **Check the AI.** **Learners talk with** is already set to your most recently changed published agent. Pick another if you like. **Write the task.** Under **Content**, type **The task**, for example \"Should school start later? Take a side and give two reasons.\" **Add it.** Leave **Opens** on **Open** and press **Add activity**. A preview appears beside the form: \"As a learner sees it · nothing here counts\". It shows the Writing panel with your agent beside it, on **Desktop** or **Phone**.",{"id":128,"title":129,"text":130},"choose-how-it-looks","Choose how it looks","In the course's **Settings → Appearance**, pick a look for its home and activities, and for the study's consent step if it has one. **Clear** is the default; **Playground** suits young learners. Under **Color**, keep the look's own or choose another; text on it turns dark or light so it stays readable. Press **Preview** to see it at full size, on a computer or a phone, in light and dark.",{"id":132,"title":133,"text":134},"open-and-share-it","Open and share it","**Clear what's missing.** **Before it opens** lists anything left. If it asks you to **Choose the AI key that pays for its AI**, pick one in **Settings → The AI** and press **Save settings**. **Try it.** Press **Preview** to go through the course as a new learner. Previews stay out of Progress. **Open it.** Press **Open course**. **Share it.** On the **Link & QR** tab, copy **The course's link**, or press **Show to the class** for a full-screen QR code that phones can scan. In an LMS, add the course as a link that opens in a new tab. Inside a frame, some browsers forget who a learner is betwee",{"id":136,"title":137,"text":138},"see-your-first-learner","See your first learner","A learner opens the link, types their name and starts. On the **Progress** tab, they appear with a dot under the activity once they start, and a check once they're done. That's a working class. [Activities and panels](\u002Fdocs\u002Fteach\u002Factivities): lessons, tests, surveys, and the panels learners work in. [How the AI helps](\u002Fdocs\u002Fteach\u002Fai-helps): tell the AI the goal and how far it may go. [Learners and sign-in](\u002Fdocs\u002Fteach\u002Fsign-in): sections, your class list, code cards and shared computers.",{"path":140,"title":141,"description":142,"updated":13,"minutes":14,"sections":143},"teach\u002Factivities","Activities and panels","Choose an activity's kind, give learners panels to work in, show them in steps, and set what the AI sees.",[144,146,150,154,158,162],{"id":17,"title":17,"text":145},"An activity is one thing learners do in a course, with an AI beside it or none. Use this page when you add a lesson, a test or a survey.",{"id":147,"title":148,"text":149},"kinds-of-activity","Kinds of activity","On the course's **Activities** tab, press **Add an activity** and choose a kind: **Lesson**: panels, a chat, or both. Start from **Chat with an AI**, **Practice questions**, **Writing task**, **Reading** or **Embedded page**. **Pre-test** and **Post-test**: no AI, one try, no hints, results at the end or none. A pre-test stays open to learners who join after it closes. **Survey**: your form's **Survey address**. The form receives the learner's ID or learner code under **The ID goes in** (`pid` by default).",{"id":151,"title":152,"text":153},"panels","Panels","Panels are what learners work in. An activity has up to six; with none, it is a chat. **Questions**: a **Question set**, with your choice of feedback, tries and hints. **Writing**: **The task**, an optional plan, a **Rubric** of up to 12 criteria, word limits and **A Hand in button**. Drafts save as learners write. **Reading**: a PDF from your knowledge bases, or **Upload a PDF**. Learners can highlight and add notes. **Embedded page**: **The page's address**, such as a simulation. It must allow `https:\u002F\u002Fpage.viablelearning.org` to frame it.",{"id":155,"title":156,"text":157},"showing-panels-in-steps","Showing panels in steps","With two or more panels, set **How the panels are shown** to **In steps** (up to four). Two ready patterns: **Read, then answer** and **Read with the AI, then answer alone**. For each step, choose what it **Shows**, whether **The AI** is **There** or **Not in this step**, and how it **Opens**: **When they're ready** or **On its own** after some minutes. A later step's questions don't reach learners' browsers early. A step without the AI is the sure way to keep it out of part of an activity, such as a final quiz.",{"id":159,"title":160,"text":161},"what-the-ai-sees","What the AI sees","Each panel has **What [agent] is shown of this panel**: Panel Choices Writing **All**, **Task only**, **Nothing**, **Custom** Questions **The question**, **Nothing**, **Custom** Reading **The page in view**, **The selection**, **The whole document**, **Nothing**, **Custom** Embedded page **Its events**, **Nothing**, **Custom** **Learners are told** shows what learners read about it. **Preview what [agent] reads** shows exactly what the AI gets. Answer keys are never in it.",{"id":163,"title":164,"text":165},"voice-and-photos","Voice and photos","Learners can speak if the agent's published version has a Transcribe step, and hear replies if it has a Speech step. Then turn on **Learners may speak** and choose **Read replies aloud**. Transcription is billed per audio minute. **Learners may attach photos** and **Learners may attach PDFs** allow up to 4 files a message, 8 MB each. If they aren't offered, the editor names the agent step to change. Every saved change makes a new version, which learners get the next time they open the activity. [How the AI helps](\u002Fdocs\u002Fteach\u002Fai-helps): tell the AI the goal and how far it may go. [Question sets",{"path":167,"title":168,"description":169,"updated":13,"minutes":14,"sections":170},"teach\u002Fai-helps","How the AI helps","Tell the AI what an activity is for in your own words, choose how far it may go, and give a section its own support.",[171,173,177,181,185,189],{"id":17,"title":17,"text":172},"**How the AI helps** tells the agent what one activity is for and how far it may go. It appears in the activity editor once you choose who **Learners talk with**. The agent reads it with every message. Learners don't see it.",{"id":174,"title":175,"text":176},"goal","Goal","Under **Goal**, write what learners should be able to do by the end, in your own words. For example: \"Explain each step of a two-step word problem in their own words.\" A goal alone is enough for any learners, from a university seminar to a library session. You don't need a standard.",{"id":178,"title":179,"text":180},"a-standard-a-skill-or-misconceptions","A standard, a skill or misconceptions","**Standard or skill** is optional: a K-12 standard, or a durable skill for any age. For math, **Misconceptions to listen for** suggests common misconceptions. See [Standards, skills and misconceptions](\u002Fdocs\u002Fteach\u002Fstandards-and-skills).",{"id":182,"title":183,"text":184},"how-far-the-ai-may-go","How far the AI may go","Choose one, or leave all four off: **Ask first**: it asks what they think or have tried, then builds on it. **Hints only**: hints and guiding questions, a step at a time, never the answer. **Explain when stuck**: it explains and shows a worked example, then they try one. **Only check**: it says what is right and what to look at again in their own work.",{"id":186,"title":187,"text":188},"different-for-a-section","Different for a section","Under **Different for a section**, give a section, such as an extra-support period, its own **How far** choice and a note (up to 500 characters) the agent reads only in that section's chats. Each message's record keeps which section's settings it used (`teaching_section` in the [research export](\u002Fdocs\u002Fresearch\u002Fexport)). It isn't offered on a study's design or while a course's study runs, where every section follows the design, nor for one learner: a note about a person would go to a model.",{"id":190,"title":191,"text":192},"check-what-the-ai-is-given","Check what the AI is given","Open **What [agent] reads with every message** to see the exact text the agent gets. With a section of its own, choose it under **As read by**. This is an instruction, not a lock. To keep the AI out of part of an activity, show the panels in steps with a step that has no AI. See [Activities and panels](\u002Fdocs\u002Fteach\u002Factivities). With a VETTING step, its reviewer checks each reply against this too, and replies that can't pass show up under **To look at**. A change here makes a new version of the activity, and each message's record says what the AI was asked to do. [Following progress](\u002Fdocs\u002Fteach",{"path":194,"title":195,"description":196,"updated":111,"minutes":14,"sections":197},"teach\u002Fstandards-and-skills","Standards, skills and misconceptions","Align an activity to a K-12 standard or a durable skill, and give its AI common math misconceptions to listen for.",[198,200,204,208],{"id":17,"title":17,"text":199},"In an activity's [How the AI helps](\u002Fdocs\u002Fteach\u002Fai-helps), you can say what it aims at beyond your own goal: a K-12 standard or a durable skill, and for math, the misconceptions its AI should listen for. All of it is optional and comes from [Learning Commons](\u002Fdocs\u002Fresources\u002Flearning-commons). Under **Standard or skill**, choose **K-12 standard** for US state standards and Common Core, or **Durable skill** for collaboration, communication and critical thinking at any age.",{"id":201,"title":202,"text":203},"a-k-12-standard","A K-12 standard","Standards cover math, English language arts, science and social studies. **Say where.** Choose your **State** (or **Common Core (Multi-State)**), a **Subject** and a **Grade**. **Search.** Type words, or a code such as `4.OA.A.3`, and press **Search**. **Pick one.** It comes with what **It breaks into** and the **Standards before it**, for the AI to go back to. **Untick what doesn't fit.** Untick what this activity doesn't reach.",{"id":205,"title":206,"text":207},"a-durable-skill","A durable skill","Durable skills come from the Carnegie Skills Progressions. Each indicator, such as \"Check in and circle back with group progress\", grows through four levels: **Exploring**, **Analyzing**, **Integrating** and **Extending**. Choose the **Level learners work toward**, then search with words like *evidence* or *feedback*. The AI reads what a learner does **At this level**, and **The level before** to go back to. Either way, what you choose is kept in the activity as it was, with its CC BY 4.0 attribution. Later changes at Learning Commons don't change what your learners' AI was given.",{"id":209,"title":210,"text":211},"misconceptions-to-listen-for","Misconceptions to listen for","For math, **Misconceptions to listen for** suggests misconceptions from Eedi's graph, through [Learning Commons](\u002Fdocs\u002Fresources\u002Flearning-commons): at once for a math standard, or, with only a goal, from **Teaching math? Find misconceptions to listen for**. Each suggestion is a math skill whose words match the standard or goal, with the misconceptions that hinder it; you can also search with your own words. Tick up to eight; nothing is ticked for you. The agent, and a VETTING reviewer, get them as a short list. [How the AI helps](\u002Fdocs\u002Fteach\u002Fai-helps): the goal, how far the AI may go, and a se",{"path":213,"title":214,"description":215,"updated":13,"minutes":14,"sections":216},"teach\u002Fsign-in","Learners and sign-in","Choose how learners sign in, set up sections and a class list, print code cards, and give a section its own times.",[217,219,223,227,231,235,239],{"id":17,"title":17,"text":218},"Set up who is in a course and how they get in, before your first class or a new term.",{"id":220,"title":221,"text":222},"how-learners-sign-in","How learners sign in","Choose in **Settings → How learners sign in**. It's the same in every activity, so a learner's work follows them across devices. Option Best for **Personal codes on cards** Young learners and shared devices **They type their name** Quick starts with no list **They type an ID they already have** Matching your records **Their ID comes in the link** Arrivals from a survey or online panel **Each device** One sitting: each browser is one learner With typed names, the same name is the same person, so ask for a last initial: two Sams would share a record. **Only names on the class list** turns away a",{"id":224,"title":225,"text":226},"sections","Sections","A section is a class period or group, with its own link. On **People**, type a name under **Sections**, press **Add section**, then **Save sections**. Section links appear on **Link & QR**. Then choose **How learners get into their section**: **By their section's link**, **They pick it themselves, once**, or **From your class list only**.",{"id":228,"title":229,"text":230},"your-class-list","Your class list","A class list is optional. It gives everyone a section and a personal code at once, and shows them in Progress before their first visit. **Open the list.** On **People**, press **Add people**. **Paste your names.** Type one person per row, or paste rows from a spreadsheet. **Import a CSV file** works too. **Fill the gaps.** **Student ID or email** and **Section** are optional; **Section for rows that leave it empty** fills them. **Add them.** Check the summary and press **Add**. Add up to 1,000 people at a time. Anyone already in the course keeps their work and code.",{"id":232,"title":233,"text":234},"code-cards","Code cards","Everyone on the list gets a **personal code**, like `K7Q2-M9XC`. **Print cards** on **People** prints each learner's name, section, code and a QR code for their section's link. Allow pop-ups if they don't open. For a lost card, press **New code** on the learner's page in [Teach → Learners](\u002Fdashboard\u002Flearners).",{"id":236,"title":237,"text":238},"shared-computers","Shared computers","For a laptop cart or a lab, turn on **Shared computers** in **Settings → How learners sign in** (on by default for children). Each visit, and any return after 20 minutes idle, asks \"Are you Sam?\". Learners also get **Sign out**. Don't use **Each device** on shared computers: everyone on that browser becomes one learner.",{"id":240,"title":241,"text":242},"opening-times-and-extra-time","Opening times and extra time","An activity's **Opens** is **Open**, **At a time** or **When I open it**; **Closes** is optional. Once it's saved, each section gets its own row, so Period 2 can start Monday and Period 3 Tuesday. In class, **Open now** asks **Everyone** or one section **only**. For extra time, open the learner's cell in **Progress**, set **Open for them until** under **More time**, and press **Give more time**. It only moves a close later. [Following progress](\u002Fdocs\u002Fteach\u002Fprogress): see who has done what, and what to look at. [Sharing a course](\u002Fdocs\u002Fteach\u002Fsharing): run it with other teachers and assistants.",{"path":244,"title":245,"description":246,"updated":13,"minutes":14,"sections":247},"teach\u002Fsharing","Sharing a course","Share one course by email with a teacher who runs it or an assistant who follows it, without giving them the rest of the project.",[248,250,254,258,262],{"id":17,"title":17,"text":249},"Share one course with a co-teacher or an assistant, like sharing a document. They get that course, not the rest of your project.",{"id":251,"title":252,"text":253},"share-it","Share it","**Open the course.** In **Teach → Courses**, open it and press **Share** at the top. **Add them.** Type their email, choose **Teacher** or **Assistant**, and press **Add**. **That's it.** We email them the link. They have the course as soon as they sign in with that email, with or without an account today. There is nothing to accept. Under **People with access**, the dialog lists everyone in the project first, then each person you shared it with.",{"id":255,"title":256,"text":257},"who-can-do-what","Who can do what","Teacher and assistant are roles on this course; editor and viewer are roles in the whole project. Teacher Assistant Editor Viewer Progress, flags and learners' work, with names Yes Yes Yes Codes only Mark what to look at as seen Yes Yes Yes No Class list, sections, opening times, extra time Yes No Yes No The course's settings (not its AI key) Yes No Yes No Share the course Yes No Yes No Activities, the AI key, deleting the course No No Yes No A teacher or assistant from outside the project sees only the courses shared with them: the project switcher shows the project as **Shared course**, and ",{"id":259,"title":260,"text":261},"a-study-in-several-schools","A study in several schools","A study's courses can sit in one project, one per school. Share each school's course with its own teachers: each sees only their course and its learners. The activities stay the study's design, the same at every school. Project editors can change every course in the project. Make someone an editor only if they build activities or the study; share a course with a teacher who runs one class.",{"id":263,"title":264,"text":265},"stop-sharing","Stop sharing","In **Share**, choose another role from a person's role menu, or press **×** to remove them. They lose the course at once; what their learners did stays. A teacher can remove themselves, which the dialog calls leaving the course. [Learners and sign-in](\u002Fdocs\u002Fteach\u002Fsign-in): sections, code cards and extra time. [Following progress](\u002Fdocs\u002Fteach\u002Fprogress): see who has done what, and what to look at. [Members and roles](\u002Fdocs\u002Fproject\u002Fmembers-and-roles): roles that cover the whole project.",{"path":267,"title":268,"description":269,"updated":13,"minutes":14,"sections":270},"teach\u002Fprogress","Following progress","See who has done what, act on what the AI flags, open a learner's work, and download progress with names.",[271,273,277,281,285],{"id":17,"title":17,"text":272},"**Progress** shows who has done what in a course, and what you may want to look at. Open it during class, or after, before you plan the next lesson.",{"id":274,"title":275,"text":276},"the-grid","The grid","Progress has a row for each learner and a column for each activity, with how many are done. Everyone on the class list has a row, joined or not. Each cell is **done**, **started** or **not opened**. Search names and codes, filter by section, and press **Refresh** to catch up.",{"id":278,"title":279,"text":280},"to-look-at","To look at","Above the grid, **To look at** lists moments from the last 30 days of your learners' work with the AI. Safety replies and calls for a person come first, then the newest. **Safety reply**: the agent's VETTING step stopped a reply for safety. **Needs a person**: the VETTING step asked for a person. **No reply passed review**: no reply passed VETTING in the attempts allowed, so the learner got the last one unapproved. **The AI couldn't answer**: the agent itself said it couldn't answer, or wanted a person. **Rated not helpful**: the learner rated a reply not helpful. **The reply failed**: the lea",{"id":282,"title":283,"text":284},"a-learner-s-work","A learner's work","Open a cell to see one learner's work in that activity: when they started and finished, and how long they were active their plan, draft and hand-in each answer, **Right** or **Not right**, with tries; **Listen** plays a spoken answer when recordings are kept their highlights and notes their last 20 **Messages with** the agent, typed or spoken, and whether they rated each reply helpful The cell is also where you give extra time. See [Learners and sign-in](\u002Fdocs\u002Fteach\u002Fsign-in).",{"id":286,"title":287,"text":288},"the-download-with-names","The download with names","**Download with names (CSV)** lists each person's name, student ID, section and visits, and each activity done, started or not yet. Use it for your records or gradebook. The file has learners' names and IDs. Keep it somewhere safe. Viewers get **Download (CSV)** instead, by learner code only. The research export also uses learner codes, never names. [How the AI helps](\u002Fdocs\u002Fteach\u002Fai-helps): set the goal and how far the AI may go. [Learners and sign-in](\u002Fdocs\u002Fteach\u002Fsign-in): sections, code cards and extra time. [Export](\u002Fdocs\u002Fresearch\u002Fexport): download your course's data for research, by learne",{"path":290,"title":291,"description":292,"updated":13,"minutes":14,"sections":293},"teach\u002Fquestion-sets","Question sets","Write, import or draft questions with AI, then use one set as practice in one activity and a quiz in another.",[294,296,300,304,308,312],{"id":17,"title":17,"text":295},"A question set is a list of questions any activity's Questions panel can ask. Build one here, or reuse one across activities. Sets live in [Teach → Question sets](\u002Fdashboard\u002Fquestions), listed by the course and unit that ask them. You can also press **New set** on an activity's Questions panel. Learners never see the answers.",{"id":297,"title":298,"text":299},"write-questions","Write questions","**Start a set.** Press **New question set** and give it a **Title**. **Add a question.** Press **Add a question** and choose its type. **Add help.** Give it up to five **Hints**, an **Explanation**, a **Skill** and **Points**. **Check it.** **Preview** shows the question with its key marked. The types are **Multiple choice**, **Select all that apply**, **Fill in**, **Fill the blanks**, **Put in order**, **Short answer**, **Open answer**, **Program** and **Spoken answer**. Open answers and programs aren't graded automatically. Short and open answers can **Show the model answer after they answer",{"id":301,"title":302,"text":303},"import-questions","Import questions","Press **Import questions**, then paste them or choose a PDF, Word, PowerPoint, Excel or CSV file. Spreadsheets with a header row, lettered choices (Moodle's Aiken format) and JSON are read without AI; **Formats read without AI** has templates. Anything else can be **Read with AI**, which keeps your questions and answers as they are. Untick what you don't want and press **Add**.",{"id":305,"title":306,"text":307},"draft-with-ai","Draft with AI","**Draft with AI** writes questions from your material: **Pick the material.** In **What to draw on**, choose **Your documents** (up to 10, whole or by sections or pages), **A file**, or **Text**, with an optional focus. **Say what to write.** In **What to write**, set how many (up to 30), a level and the types. **Choose who writes.** In **Who writes them**, pick a key, which is billed, and a model. Each question comes with a skill, hints and an explanation, drawn from your material only. Nothing joins the set until you press **Add**. Spoken answers and programs aren't drafted.",{"id":309,"title":310,"text":311},"feedback-and-tries","Feedback and tries","Feedback, tries and hints are set on each activity's Questions panel, so one set can be practice in one activity and a quiz in another: **Right or wrong is shown**: **After each answer** for practice, **At the end** for a quiz, **Never** for a test. **Tries per question**: 0 for any number, up to 10. **Hints**: learners open them one at a time, and each is recorded. Pre-tests and post-tests always get one try and no hints.",{"id":313,"title":314,"text":315},"changing-and-archiving","Changing and archiving","**Asked in** lists every activity that uses the set. A saved change shows in all of them and makes a new version; answers already given keep theirs. To change one activity only, use **Make a copy** on the Question sets page. **Archive** removes a set from the list and from new panels. Activities already using it keep working. [Activities and panels](\u002Fdocs\u002Fteach\u002Factivities): put a set in a Questions panel, alone or in steps. [Following progress](\u002Fdocs\u002Fteach\u002Fprogress): see each answer, and who is stuck on a question.",{"path":317,"title":318,"description":319,"updated":111,"minutes":46,"sections":320},"teach\u002Fexamples-and-packages","Examples and packages","Start from a working example, download any course with or without its files, and move it to another project. Learners and keys never travel with it.",[321,323,327,331,335,339],{"id":17,"title":17,"text":322},"An example is a whole course to start from: its activities, the AI beside the work and how far it may go, the questions and rubrics it uses, and the files it reads. A package is the file any course travels as, and each example is one.",{"id":324,"title":325,"text":326},"start-from-an-example","Start from an example","[Docs → Examples](\u002Fdocs\u002Fexamples) has six, each arranged differently: fractions practice with a checked tutor, a PDF reading with a Socratic tutor, an argument essay, English speaking practice by voice, a density lab on an embedded page, and a library research desk that answers from its guides. **Choose one.** Press **Use in my project** on an example, or press **From an example or a file** on [Teach → Courses](\u002Fdashboard\u002Fcourses) and **Use** one. **Choose the AI key.** Pick the key that pays for the course's AI. You can change it later in the course's **Settings**. **Create it.** Press **Crea",{"id":328,"title":329,"text":330},"download-a-course-as-a-package","Download a course as a package","On a course, press **Download as package**, then choose: **The course (.json)**: one file with the course's settings, units and activities, the agents they use (each one's published version) and the question sets their Questions panels ask. Reading panels and knowledge bases stay behind. **With its files (.zip)**: the same, plus each Reading panel's PDF and the knowledge bases its agents search: their uploaded files, and the addresses of their websites, which are read again where it's imported. Up to 25 MB. The project's owners and editors can download it, since it carries the agents' workflow",{"id":332,"title":333,"text":334},"duplicate-a-course","Duplicate a course","On a course, press **Duplicate** and choose **Into the project**: this one, or another where you're an owner or editor. You get a new draft with the course's settings, look, units and activities, and none of its learners: no class list, sections or anyone's work, and activities with dates start hidden. **In the same project**, the copy is called \"… (copy)\" and uses the same agents, question sets and readings, with the course's AI key. **In another project**, that project gets its own copies of the agents, question sets and knowledge bases, and you choose one of its keys. An agent whose name it",{"id":336,"title":337,"text":338},"bring-a-file-into-a-project","Bring a file into a project","In the project, open **Teach → Courses**, press **From an example or a file**, then **Choose file** under **Upload a package** and pick the `.viable.json` or `.viable.zip`. If you own or edit more than one project, choose **Into the project**. The course arrives as a new draft, with new knowledge bases for its files. An agent whose name the project already uses gets \"(imported)\" after it. If something can't be made, nothing half-made is left open.",{"id":340,"title":341,"text":342},"what-a-package-never-carries","What a package never carries","Learners, the class list, sections, or anyone's work. The course's key, or the first project's IDs. In a `.json` without files: knowledge bases. A Reading panel comes without its PDF and is left out, so add it again, and an agent comes without the knowledge bases it searches. Download it with its files to keep them. The headers of an agent's Fetch URL steps, and email addresses in the course information. Opening dates. Each activity is open, or hidden until you open it. A `.viable.json` can be up to 2 MB and a `.viable.zip` up to 25 MB, with up to 20 agents, 50 question sets and 100 activities",{"id":344,"title":345,"lead":346,"pages":347},"research","Research","Study learning with AI, from consent to a documented dataset.",[348,367,386,409,440,463],{"path":349,"title":350,"description":351,"updated":13,"minutes":14,"sections":352},"research\u002Ffirst-study","Your first study","Start a study from your situation and work through its checks until it is ready to open.",[353,355,359,363],{"id":17,"title":17,"text":354},"Start here the first time you run research on VIABLE. You go from your situation to a study whose checks are all done, ready to open.",{"id":356,"title":357,"text":358},"start-from-your-situation","Start from your situation","Open [Research → Overview](\u002Fdashboard\u002Fresearch). Under **What are you studying?** (or **Start another study**), pick a card. Card What it sets up Button A study in your own course A study on a course you have: follow use, compare units or compare groups **Start with your course** A study in schools Comparing groups on a new course for children, with personal codes and parental permission for minors **Start a study in schools** An online study Comparing groups on a new course for adults, who sign in by the ID in their link (`PROLIFIC_PID`) **Start an online study** Open learning on a chat page ",{"id":360,"title":361,"text":362},"create-the-study","Create the study","**Say what you want to find out.** In **New study**, the card chooses step 1, except for your own course. When comparing units, also choose **The same for everyone** or **Two orders, half the learners each**. **Name it.** Give the study a name your team will recognize. **Choose where learners take part.** Pick **A course you have**, **A new course** (with **Who it is for**: Adults, Teenagers or Children) or, for an observational study, **A chat page**. **It starts with** lists the defaults. **Create it.** Select **Create study**. If you haven't chosen where, the button reads **Create, and add ",{"id":364,"title":365,"text":366},"the-checks","The checks","**Every study:** add the courses it runs in (or where it runs). None of them may be in another open study. **A study that tells or asks people:** add the consent form (or the research notice). **A comparative study:** define at least two conditions, add the activities and make the conditions differ. Have learners sign in the same way every visit, publish an agent, and choose the key that pays for the AI. **Depending on how it assigns:** add the pre-test, make consent about the use of data, add sections to each course, and give each section its condition. **On a chat page:** turn on an agent's ",{"path":368,"title":369,"description":370,"updated":13,"minutes":14,"sections":371},"research\u002Fdesigns","Choosing a study design","Choose whether a study follows use, compares units or compares groups, and where it runs.",[372,374,378,382],{"id":17,"title":17,"text":373},"Choose the kind of study by what changes for learners. What changes for learners Choose The study is Nothing: you follow how a class uses a course, or how visitors use a chat page **Follow how it is used** Observational, with no conditions The same learners have the AI in some units and not others, or one agent and then another **Compare units, with the same learners** Comparative, comparing units: one plan, or two orders drawn at random Learners or whole classes get different versions **Compare groups of learners** Comparative, comparing groups: each learner or section gets one condition Two ",{"id":375,"title":376,"text":377},"common-designs","Common designs","RCT: comparing groups, **With AI** and **Without AI**, each person at random. Cluster randomized: comparing groups, each section at random, with consent about the use of data. Existing classes, not randomized: comparing groups, each section given its condition by you. Two AIs: comparing groups, one condition using another agent, such as one with VETTING. Units with and without AI: comparing units, one plan. Crossover (AB\u002FBA): comparing units, two orders, the second the reverse of the first. Waitlist: comparing groups, the later group without AI until a given unit.",{"id":379,"title":380,"text":381},"where-it-runs","Where it runs","**Where it runs** holds the study's courses and chat pages, up to 40. Courses have known learners, each with its own link, class list and sections: one per school, class or online sample. A chat page can host an observational study. Each device is an anonymous visitor, shown by visitor code (`V-…`). To know who learners are, or to compare, use a course. A comparative study runs on courses only. A course or chat page is in one study at a time, until that study closes. You can remove one only while nobody has taken part through it. **How learners sign in** sets one way for every course while the",{"id":383,"title":384,"text":385},"who-changes-activities","Who changes activities","**Observational:** the activities stay the course's. Teachers keep changing them, and every record carries its activity version. **Comparative:** the first course you add with activities gives the study its design. Its activities move into the study and are changed on **Design**, for every course at once. Other courses must have no activities of their own. A teacher studying their own course changes its activities in the study too. Teachers still set opening times and extra time. Teachers who run a course join the project as editors. [Your first study](\u002Fdocs\u002Fresearch\u002Ffirst-study): start from y",{"path":387,"title":388,"description":389,"updated":13,"minutes":14,"sections":390},"research\u002Fconsent","Consent and taking part","Choose what people are told or asked, handle minors and paper forms, and withdraw someone who asks.",[391,393,397,401,405],{"id":17,"title":17,"text":392},"A study's **Consent** tab decides what people are told or asked before they start, and so whose data the study uses. People who decline or opt out still use the course or chat. Option What people see In the data **Include everyone, without asking** Nothing Everyone **Show a research notice** A notice; on a chat page, a line above the chat opens it Everyone **A notice they can opt out of** The notice, with a way to keep their work out (**Don't use my chats** on a chat page) All but those who opted out **Ask for consent on a form** A form to decide on first Only those who agree Observational stu",{"id":394,"title":395,"text":396},"the-form","The form","Choose **Write it here** (up to 20,000 characters, or **Start from a template**) or **Use your approved PDF** (up to 10 MB). After the study opens, a changed form is an amendment and a new version, listed under **Versions of the form**. With consent, people who decided on an earlier version are asked again on their next visit. With a notice, new arrivals read the new one. Pause the study while an amendment is reviewed. Agreeing covers any recordings the study keeps, so say so in the form.",{"id":398,"title":399,"text":400},"minors-and-paper-forms","Minors and paper forms","**An assent form for minors:** the form asks people their age, and minors agree on the assent form too. A children's course takes everyone as under 18. **Parental permission for minors:** a minor counts in the data once permission is recorded. Upload **The form parents sign** to print. **Paper forms:** as signed forms come back, select **Record** in the **Parental permission** column on **Participants**. **Show them** lists minors who are waiting.",{"id":402,"title":403,"text":404},"withdrawal","Withdrawal","Learners reread the study under **About the study**. With consent, **Leave the study** is final and keeps their earlier work out too. With an opt-out, they can opt out and back in. When someone asks you, select **Withdraw** beside them on **Participants**. Their records, earlier ones too, leave the study's data and coding samples. It is final.",{"id":406,"title":407,"text":408},"what-teachers-see","What teachers see","A course's **Research** tab shows its teachers how many learners take part, by condition. Owners and editors see names beside decisions; viewers see codes. No setting hides decisions from owners and editors. If an instructor must not know who agreed, don't make them one while it matters. How people take part, what consent covers and parental permission are fixed once the study opens. [Conditions and assignment](\u002Fdocs\u002Fresearch\u002Fconditions): set what differs and who gets which. [The research export](\u002Fdocs\u002Fresearch\u002Fexport): see how consent marks every record.",{"path":410,"title":411,"description":412,"updated":13,"minutes":14,"sections":413},"research\u002Fconditions","Conditions and assignment","Set what differs between conditions and who gets which, then open, pause and close a comparative study.",[414,416,420,424,428,432,436],{"id":17,"title":17,"text":415},"Set up a comparative study's **Design** tab, then run the study. For example, half of a Grade 4 math class gets an AI tutor and half doesn't.",{"id":417,"title":418,"text":419},"the-design","The design","**Design** starts with **What this study compares**, then four steps that apply to every course at once. **The activities.** Edit them with the course's own editor. Pre-tests, post-tests and surveys are the same for everyone. **What differs.** Give each condition rules: the AI off, the AI sees nothing of the panels, typed only, replies not read aloud, or another agent. **Who gets which, and when.** Choose who is assigned, how, how it is balanced, and when. **Agent versions.** Opening the study pins each agent at its published version. A new activity starts hidden at every course until its teac",{"id":421,"title":422,"text":423},"conditions-as-rules","Conditions as rules","A study has two to eight conditions, labelled A to H, each with a share from 1 to 10. **Only in some units or activities** adds exceptions, including **Hidden for this condition**. Check **Side by side: what learners get in each condition** before you open. When comparing units, **The plan, unit by unit** (or **The orders**) says whether each unit keeps its AI, has none, or uses another agent.",{"id":425,"title":426,"text":427},"assignment","Assignment","**Who is assigned:** **Each person** or **Each section**. **How:** **At random**, in shuffled blocks balanced by the shares, or for sections, **By you**. **Balanced:** **Across the study**, **Within each section** or **Within each course**. **When:** **When they take part**, **After the pre-test**, or **At first use** (not when comparing units). A condition never changes once given, on any activity or device.",{"id":429,"title":430,"text":431},"pinned-and-protocol-versions","Pinned and protocol versions","Learners keep meeting the pinned agent version as the agent changes. **Use the latest published versions** moves every course on. Once open, every design change and version move makes a new protocol version, shown in the study's header.",{"id":433,"title":434,"text":435},"open-pause-and-close","Open, pause and close","The header's status control runs **Draft → Open ⇄ Paused → Closed**. Each move explains itself first. Move What it does **Open study** People start taking part; assignment starts; agent versions are pinned. **Pause** Learners keep their condition. Nobody new joins the study, and nothing is recorded for it. **Resume** Takes people in and records again. **Close study** Conditions stop; courses return to their own settings; the data stays. **Open again** Reopens with the same conditions and pinned versions. **Delete draft** works only if the study never opened. Once open, how people take part, si",{"id":437,"title":438,"text":439},"participants","Participants","**Participants** shows **Flow**, as a CONSORT diagram counts it; **Balance on the pre-test**, as Hedges' g; **People**, each learner code with decision and condition; and **The study's record** of every decision, assignment and change. [Consent and taking part](\u002Fdocs\u002Fresearch\u002Fconsent): withdrawal and paper forms. [The research export](\u002Fdocs\u002Fresearch\u002Fexport): conditions and versions in your data.",{"path":441,"title":442,"description":443,"updated":13,"minutes":14,"sections":444},"research\u002Fcoding","Coding conversations","Code a sample of messages with a codebook, add model coders, check agreement and decide the final codes.",[445,447,451,455,459],{"id":17,"title":17,"text":446},"Code what people wrote, such as what patrons ask a library's chat page. [Research → Coding](\u002Fdashboard\u002Fcoding) runs in four steps: codebook, sample, code, compare.",{"id":448,"title":449,"text":450},"codebooks","Codebooks","Pick a codebook: **Help-seeking**: executive or instrumental requests (Nelson-Le Gall). **ICAP engagement**: passive, active, constructive, interactive (Chi and Wylie); applying it to chat is an interpretation to state. **Question depth**: shallow, intermediate, deep (Graesser and Person). **Accuracy of replies**: accurate, partly accurate, inaccurate, didn't answer. **What patrons ask**: a library's request categories. **Your own codebook**: 2 to 20 codes. Each code has a label, a definition, examples and near misses. Changing codes after coding makes a new version, with a note on why; each s",{"id":452,"title":453,"text":454},"draw-a-sample","Draw a sample","**Choose the codebook.** Select **New sample** and pick it. **Set where it is drawn from.** Under **Drawn from**, choose the period, study, chat pages or courses, and agents. **Only people included in the study** is on by default. **Draw it.** Enter **Items to sample** (up to 2,000) and, optionally, a **Seed**, then select **Draw the sample**. The same seed and choices over a finished period draw the same items. People who leave the study leave its samples.",{"id":456,"title":457,"text":458},"code-alone-and-with-model-coders","Code, alone and with model coders","On **Code**, code one item at a time with keys 1 to 9. Coding is blind: you see only your own codes until you open **Review & decide**. Any member, viewers included, can code. **Model coders → Add a model coder** adds a model as one more coder, billed to a key you choose. Under **How strictly**, **Only these codes** gives no code when nothing fits, never the closest. **These codes, and suggest new ones** may also propose codes. **About your study** adds context to its prompt. For each item it returns codes, a confidence, a quote kept only if it appears word for word, and a reason. You can read",{"id":460,"title":461,"text":462},"agreement-then-final-codes","Agreement, then final codes","**Agreement** compares every two coders on items both coded: percent agreement, Cohen's κ and a confusion table. **For your methods section** drafts a paragraph to copy. In **Review & decide**, select **Show everyone's codes**, which ends blind coding for you. Pick the final codes or **No code fits**, add a note, and **Decide**. **Use the agreed codes for N** settles items where coders agree. Owners and editors decide. Final codes feed an observational study's **Summary** and `coding_final.csv`. [The research export](\u002Fdocs\u002Fresearch\u002Fexport): codes, codebooks and prompts in your data. [Consent a",{"path":464,"title":465,"description":466,"updated":13,"minutes":14,"sections":467},"research\u002Fexport","The research export","Download a study's documented ZIP, read its consent marks, cite what learners saw, and delete a learner's data.",[468,470,474,478,482,486],{"id":17,"title":17,"text":469},"Get your data out as one documented ZIP, ready to analyze and cite. A study's **Export** tab opens [Research → Export](\u002Fdashboard\u002Fresearch\u002Fexport) with the study chosen. **Choose whose data.** Pick a study, a course, or where (courses, chat pages, your apps on the API). Turn off **Only people included in the study** to get everyone, each record marked. **Choose when and which agents.** Choosing agents leaves out activities without AI. **Choose what goes in.** Turn on **What was written**, **IDs from your systems**, **Recordings** or **Mask condition names** as needed. **Download.** **What's in",{"id":471,"title":472,"text":473},"what-s-in-the-zip","What's in the ZIP","**People and conversations:** `learners.csv`; `turns.csv`, every message and reply with agent version, sources and rating; `agents.csv`. **Work and measures:** `sessions.csv`, `attempts.csv` (pyBKT format), `outcomes.csv`, `writing.csv`, `responses.csv`, `activity_progress.csv` and more. **The study:** `enrollments.csv` (decisions), `assignments.csv`, `flow.csv` (CONSORT counts), `study_events.csv` and `study_documents.csv`. **Coding:** `coding_labels.csv`, `coding_final.csv` and `codebooks.json`. **The dictionary:** `data_dictionary.csv` defines every column and its sources. `manifest.json` r",{"id":475,"title":476,"text":477},"consent-marks","Consent marks","Records from a study carry `study`, `condition` and `participation`. The `participation` mark is `included`, `opted_out`, `declined`, `withdrawn`, `awaiting_permission` or `not_in_study`. Inclusion is decided at export, never by deleting records.",{"id":479,"title":480,"text":481},"masked-conditions-and-recordings","Masked conditions and recordings","Masked conditions appear as A, B and so on, without their names, rules or agents' names. The study's **Data** tab sets the default. Recordings exist only when **Keep recordings of what people say** is on in **Data**. Once the study opens, you can turn it off but not on. `recordings\u002F` holds them only for people whose data counts. `turns.csv` and `responses.csv` name each file.",{"id":483,"title":484,"text":485},"citing-what-learners-saw","Citing what learners saw","**Activities:** records carry `activity_version`, and `manifest.json` lists each version's settings SHA-256. **Agents:** turns carry `agent_version`, and `agents.csv` gives each workflow's SHA-256. For a comparative study, the manifest gives pinned versions and the protocol version. **Forms:** decisions carry their form version, and `study_documents.csv` gives each PDF's SHA-256. **Coding:** `codebooks.json` gives codebook versions, seeds, and each model coder's settings and prompt.",{"id":487,"title":488,"text":489},"deleting-a-learner-s-data","Deleting a learner's data","**Find the person.** Open them in [Teach → Learners](\u002Fdashboard\u002Flearners), or under **Chat page visitors**. **Delete.** Select **Delete data…**, then **Delete their data**. This can't be undone. Their messages, answers, drafts, scores, coding labels, recordings and what agents remembered are deleted, and so is a learner's name. Their study decisions and code stay, as review boards require, and `learners.csv` marks `data_deleted_at`. Owners and editors delete. [Coding conversations](\u002Fdocs\u002Fresearch\u002Fcoding): code a sample before you export. [Consent and taking part](\u002Fdocs\u002Fresearch\u002Fconsent): what ",{"id":491,"title":492,"lead":493,"pages":494},"build","Build agents","Make the AI: its steps, knowledge, checks and chat page.",[495,518,545,572,599,628,640],{"path":496,"title":497,"description":498,"updated":13,"minutes":14,"sections":499},"build\u002Ffirst-agent","Your first agent","Make an agent from a template, try it on your own key, publish it and read one run step by step.",[500,502,506,510,514],{"id":17,"title":17,"text":501},"This page takes you from nothing to a published agent in about ten minutes. Start here before you build anything for learners. An agent is a workflow of steps. It reads a message, can search your documents and check its own reply, then answers. Learners meet the published version in course activities or on its chat page. You need to be an owner or editor of the project. Viewers can look, but not try or change an agent. Trying an agent runs it for real on a project API key with the **Run agents** permission, billed like any request. New keys include it.",{"id":503,"title":504,"text":505},"make-it-from-a-template","Make it from a template","**Open the templates.** In [Build → Agents](\u002Fdashboard\u002Fagents), click **New from template**. **Pick a tutor.** Choose **Safety & review → Tutor with guardrails**. **Before you run** says what a template needs; this one needs nothing. **Name it.** Names are unique in the project. Click **Create & open**. The canvas shows four steps. `input` goes to `screen`, a Guardrail step that checks each message for personal data, jailbreaks and harmful content. A message that passes goes to `tutor`, an LLM step. One that fails goes to `blocked`, a Reply step. You can also describe the agent in the box on t",{"id":507,"title":508,"text":509},"try-it","Try it","**Open the test chat.** In the right panel, click **Test**, then **Try it**. **Choose who pays.** Click **Options**, choose a key under **Who pays**, and click **Done**. The key is remembered for this project. **Send the example.** Click the example message to put it in the box, then press Enter. Under the reply you see its cost, its steps and how long it took. **Test the guardrail.** Send \"My email is sam@example.com, can you check my essay?\" The guardrail fails it, and `blocked` answers instead.",{"id":511,"title":512,"text":513},"publish","Publish","Click **Publish**, look over the review, and click **Publish version 1**. The badge now says **Published**, and the agent list shows **Live · v1**. Later edits stay in the draft until you publish again.",{"id":515,"title":516,"text":517},"read-one-run","Read one run","**Open the runs.** Click **Test → Run history**. Your tries are at the top, marked **Dashboard test**. **Open one.** You see its reply, duration, model calls, tokens and cost. **Follow a step.** Under **Run trace**, click `tutor`. **Input** shows its instructions, the message and how many earlier messages went with it. **Output** shows its reply. **Check the guardrail.** Click `screen` to see what it checked and its verdict. That is the loop: change the draft, try it, publish, read what happened. [Steps](\u002Fdocs\u002Fbuild\u002Fsteps): what each step does, and when to use it. [Testing and run history](\u002Fdo",{"path":519,"title":520,"description":521,"updated":13,"minutes":14,"sections":522},"build\u002Fsteps","Steps","Choose the right step for each job, and edit, share and version an agent's workflow in the editor.",[523,525,529,533,537,541],{"id":17,"title":17,"text":524},"Every agent is a workflow of steps on a canvas. This page says which step to reach for, and how to edit, share and version the workflow.",{"id":526,"title":527,"text":528},"which-step-to-use","Which step to use","**Add step** (or `\u002F`) opens the step library. **Start & reply.** **Input** starts a run with the message and conversation. **Reply** ends a path with the text the reader sees. **Ask user** asks a question and waits for the answer. **AI.** **LLM** makes one model call to write or judge. **Agent** lets a model use tools, such as **Use knowledge**, until it can answer. **Image**, **Speech** and **Transcribe** handle pictures and sound. **Checks & review.** **VETTING** has a reviewer check each reply against your rules. **Guardrail** checks text once and goes to `pass` or `fail`. **Routing & logic",{"id":530,"title":531,"text":532},"edit-on-the-canvas","Edit on the canvas","Drag from an output dot (`next`, `pass`…) onto the next step. Every run starts at the step marked **Entry**. A step's menu has **Make this the entry step**. Click a step to open **Build → Step settings**. In text, **Insert a field…** adds an earlier step's output, such as `{{tutor.content}}`. The chip beside **Tools** says **Ready**, or how many issues to fix. Never put a password, API key or token in a step. Every project member can read it, and **Export JSON** copies it into the agent file.",{"id":534,"title":535,"text":536},"code-view-and-the-assistant","Code view and the assistant","**Build → Code** shows the workflow as JSON. Edit it or paste JSON from an AI tool, then click **Apply JSON**; until then you can't publish. **AI prompt + JSON** writes a prompt for your own AI tool. **Build → Assistant** answers questions about the agent and proposes changes, each waiting for **Apply to draft** or **Discard**.",{"id":538,"title":539,"text":540},"work-together","Work together","An agent has one shared draft that saves as you go. Edits from teammates, the API and the VIABLE CLI land in it too. **Share & invite** invites people to the whole project as **Editor** or **Viewer**. **Undo** undoes only your own edits.",{"id":542,"title":543,"text":544},"versions","Versions","**History → Save a version** marks a point to return to. **View & restore versions** lets you **Preview** one or **Restore** it into the draft. **Publish** makes the draft a new numbered version, the one learners, chat pages and apps use. **Tools → Discard changes** puts the draft back to the live version. **Tools → Unpublish agent** stops new runs and keeps the draft. [VETTING](\u002Fdocs\u002Fbuild\u002Fvetting): check every reply against rules you state. [Knowledge bases](\u002Fdocs\u002Fbuild\u002Fknowledge): give an agent documents to search and cite. [Testing and run history](\u002Fdocs\u002Fbuild\u002Ftesting): try the draft and r",{"path":546,"title":547,"description":548,"updated":13,"minutes":14,"sections":549},"build\u002Fvetting","VETTING","Have an independent reviewer check each reply against your rules, and decide what learners see when none passes.",[550,552,556,560,564,568],{"id":17,"title":17,"text":551},"A VETTING step has an independent reviewer check each reply against your rules. Use it when replies must follow rules you can state. VETTING (Verification and Evaluation Tool for Targeting Invalid Narrative Generation) comes from classroom research ([a middle school study](https:\u002F\u002Fdoi.org\u002F10.1016\u002Fj.caeai.2026.100646)). Use it for a tutor that never gives the answer away, or an assistant that says only what its sources say.",{"id":553,"title":554,"text":555},"how-it-works","How it works","The **reply model** writes a reply. The **reviewer model** checks it in a separate call and gives a verdict and a reason. A failed reply goes back with that reason, until one passes or the **Attempts** run out. The reviewer's rules live in the step, apart from the reply model's instructions, so a learner can't talk the reviewer out of them. Each reply and each review is a model call. A review is a judgment, not a guarantee.",{"id":557,"title":558,"text":559},"set-it-up","Set it up","**Choose what it checks against.** Under **Checks against**, pick **A guideline** or **A question and its answer key**. The **Answer key** is seen only by the reviewer. **Set the reply model.** Choose a **Reply model** and, if you like, **Reply instructions**. Safety rules are always added. **Choose the first answer.** Under **Answer to review**, pick **The reply model writes it** or **An earlier step's answer**. **Set the reviewer.** Choose a **Reviewer model**. Left empty, it uses `gpt-6-luna`. **Set the limits.** Choose **Attempts** (1–10, default 3) and **End every reply with a question** ",{"id":561,"title":562,"text":563},"outcomes","Outcomes","**Passed**: the reviewer approved the reply. **Unverified**: no reply passed, or a review couldn't run. Later steps get the last reply, not approved. **Needs attention**: the reply model found the conversation unsafe, such as self-harm. It wrote a caring reply instead, which isn't reviewed.",{"id":565,"title":566,"text":567},"what-learners-see","What learners see","Learners see only what the Reply step on each path says. They never see drafts, the reviewer's reasons or the answer key. Decide what the **Unverified** path says. The VETTING templates give a fixed message instead of the unapproved reply. **Insights** lists replies that didn't pass.",{"id":569,"title":570,"text":571},"when-a-teacher-sets-how-the-ai-helps","When a teacher sets How the AI helps","In a course activity, a teacher uses **How the AI helps** to say how far the AI may go. Say a Grade 6 teacher writes \"hints only\". The reply model gets it as instructions, headed \"From the teacher of this activity\". The reviewer checks each reply against it too. The agent profile's **What it reads** decides which steps get it. With **Only as template variables**, nothing is added; use `{{context.workspace.teaching}}` yourself. [How the AI helps](\u002Fdocs\u002Fteach\u002Fai-helps): what a teacher tells the AI in an activity. [Testing and run history](\u002Fdocs\u002Fbuild\u002Ftesting): read each VETTING round in a run's ",{"path":573,"title":574,"description":575,"updated":13,"minutes":14,"sections":576},"build\u002Fknowledge","Knowledge bases","Add documents and websites to a knowledge base, and have agents search them and cite their sources.",[577,579,583,587,591,595],{"id":17,"title":17,"text":578},"A knowledge base holds documents and websites your agents search and cite. Use one when answers must come from your own material, such as a syllabus or a library's guides. Knowledge bases live in [Build → Knowledge](\u002Fdashboard\u002Fknowledge). Agents search only knowledge bases in their own project.",{"id":580,"title":581,"text":582},"add-documents-and-websites","Add documents and websites","**Make it.** Click **New knowledge base**, name it, and choose how it searches (below). **Add files.** On **Files**, drop files or a folder, up to 15 MB each. **Paste text** adds notes or an FAQ. **Add websites.** On **Websites**, choose **Specific pages**, **A whole website** or **Pages linked from one page**. **Choose how often to re-check.** **Check for changes** runs from **Daily** to **Yearly**, or **Only when I sync**. The default is **Monthly**. Files can be PDF, Word, PowerPoint, Excel, Markdown, text, CSV, HTML, JSON or images. **Specific pages** and **A whole website** take up to 20,",{"id":584,"title":585,"text":586},"choose-how-it-searches","Choose how it searches","Search How it works Best for **Hybrid** Keywords plus meaning, reranked Paraphrased questions, and questions in other languages **Keyword only** Keywords, with no AI calls Predictable results on consistent terms",{"id":588,"title":589,"text":590},"settings-that-change-answers","Settings that change answers","In the knowledge base's **Settings**: **Passage size**: Short, Standard or Long (about 600, 1,200 or 2,400 characters). **Leave out text a website repeats on its pages**: drops navigation and footers from passages. **Let readers open cited files**: cited uploaded files link to the file for 7 days. Leave it off for internal or licensed files, and readers see only their names. Web pages always link.",{"id":592,"title":593,"text":594},"how-agents-search","How agents search","Two steps search, and they suit different questions. A **Knowledge** step searches once and passes on numbered passages, 5 by default and up to 20. Put `{{search.context}}` in an LLM step's instructions. Tell it to answer only from those sources and cite them as [n]. Branch on `{{search.count}}`, which is 0 when nothing matched. The **Answer from my documents** template works this way. An **Agent** step with **Use knowledge** searches as often as it needs and reads whole sections. Use it for lists, comparisons and questions that span several sources.",{"id":596,"title":597,"text":598},"citations","Citations","Citations are numbered in the order a reply mentions them, one per page or file. On a chat page, each reply shows its sources. **Test search** shows exactly which passages an agent would receive for a question. **Build an agent with it** starts the agent designer with this knowledge base chosen. [Steps](\u002Fdocs\u002Fbuild\u002Fsteps): the Knowledge, LLM and Agent steps in context. [VETTING](\u002Fdocs\u002Fbuild\u002Fvetting): have a reviewer check replies against your sources. [Chat pages for websites](\u002Fdocs\u002Fbuild\u002Fchat-pages): what visitors see of your sources.",{"path":600,"title":601,"description":602,"updated":13,"minutes":14,"sections":603},"build\u002Ftesting","Testing and run history","Try your draft on a key you choose, read every step of any run, and see what people ask the published agent.",[604,606,608,612,616,620,624],{"id":17,"title":17,"text":605},"Try your draft before learners meet it, check it against tests, then read what happened in any run.",{"id":507,"title":508,"text":607},"**Test → Try it** runs the unpublished draft, so you don't need to publish to test. **Who pays.** Every message is a real run on the key under **Options → Who pays**. It needs the **Run agents** permission and must allow your steps' models. A stopped run still bills the model calls it started. **Memory.** **Options → Memory** chooses **Continue a conversation** (recommended), **Independent messages** or **Send history from this browser**. **Test as.** **Options → Test as** sends a person's identifier, such as `student-042`, as your app would. **Reference data.** Material sent with each message",{"id":609,"title":610,"text":611},"run-history","Run history","A run is one execution of an agent. **Test → Run history** lists runs newest first. Filter by **Where runs came from**, such as **Chat page**, **Course** or **Dashboard test**, and by **How runs ended**. You can also filter by result data, for example `needs_human: true`. **Export** downloads the latest 200 as CSV or JSONL.",{"id":613,"title":614,"text":615},"a-run-s-trace","A run's trace","A run shows its reply, duration, model calls, tokens and cost. **Run trace** lists the steps in order. A step's **Input** is what it acted on; its **Output** shows the result (**Pretty** or **Raw JSON**) with the **Provider calls**. A VETTING step lists each round's verdict and the **Reviewer**'s reason.",{"id":617,"title":618,"text":619},"tests","Tests","To check a change against what learners might say before you publish, keep tests and run them: see [Agent tests](\u002Fdocs\u002Fbuild\u002Fagent-tests).",{"id":621,"title":622,"text":623},"insights","Insights","**Test → Insights** shows what people ask the published agent over 7, 30 or 90 days, without your tests, and flags answers that **need a look**: **Failed**, **Not answered**, **Needs a person** and **Review didn't pass**. **Topics** groups recent questions, with **What the sources seem to miss**. For the middle two, have your Reply step return `\"status\": \"not_found\"` or `\"needs_human\": true` in **Result data for your app**.",{"id":625,"title":626,"text":627},"memory","Memory","Memory is what an agent keeps about a person between conversations, up to 200 facts each, from a **Memory** step or **Remember the user** in an Agent step. A person is the `user` your app sends, or a chat page's visitor. **Test → Memory** lists who the agent remembers and what. Deleting a fact, or using **Forget everything about** a person, is permanent. [VETTING](\u002Fdocs\u002Fbuild\u002Fvetting): what each outcome of a VETTING step means. [Learners and traces](\u002Fdocs\u002Fconnect\u002Flearners-and-traces): name your app's users and keep each run's trace.",{"path":629,"title":630,"description":631,"updated":111,"minutes":632,"sections":633},"build\u002Fagent-tests","Agent tests","Keep cases of what learners might say and what a good reply does, and run them on a version before you publish.",1,[634,636],{"id":17,"title":17,"text":635},"Before learners meet a change, run your agent on cases you keep and let a judge model say whether each reply does what it should. Use it after editing a prompt, adding a step, or switching a model. A test is a moment a learner might bring and what a good reply does. **Test → Tests**, beside Run history, keeps up to 25 per agent; editors write and run them, and the project reads them. **A test.** The learner's message, or a short conversation ending with it, and what a good reply does. Optionally, what it must not do (such as \"give the final answer\"), a name, and reference data. **Save as a tes",{"id":637,"title":638,"text":639},"from-the-cli","From the CLI","Your own AI can run them too: `viable developer agents tests list|set|run-case|runs`, naming the key that pays and confirming each run, like a test run. See [The CLI and Agent Skills](\u002Fdocs\u002Fproject\u002Fcli). [Testing and run history](\u002Fdocs\u002Fbuild\u002Ftesting): try a draft and read any run's steps. [VETTING](\u002Fdocs\u002Fbuild\u002Fvetting): a reviewer that checks each reply before learners see it.",{"path":641,"title":642,"description":643,"updated":111,"minutes":46,"sections":644},"build\u002Fchat-pages","Chat pages for websites","Put a published agent on a website as a link, a QR code or a chat button, within limits you set.",[645,647,651,655,659,663,667],{"id":17,"title":17,"text":646},"A chat page puts a published agent on any website as a link, a QR code and a chat button. Visitors need no account, so it suits a library's help desk. It always runs the published version. To know who learners are, use a course instead. Librarians can start from **Overview → Open learning on a website**.",{"id":648,"title":649,"text":650},"turn-it-on","Turn it on","**Open the tab.** Publish the agent, open **Connect → Chat page**, and click **Set up chat page**. **Choose the key.** Under **Key & limits**, pick the key it **Runs on**. Every message is a run on this key. **Turn it on.** Set limits and websites (below), then click **Turn on chat page**.",{"id":652,"title":653,"text":654},"share-it-or-add-it-to-a-site","Share it or add it to a site","**Share** gives the link and QR code. **Add it to a site** asks **Where will people chat?** and gives the steps for each place. On any website, paste the script before `\u003C\u002Fbody>`. Copy yours from the tab: In LibGuides, add a Media \u002F Widget asset to one guide, or use Admin → Look & Feel → Custom JS\u002FCSS for every guide. Canvas removes scripts, so it gets a frame. Your page can open the chat with a question already asked, for example from its own search box when nothing matches: The question is sent once the chat has loaded, as if the visitor picked it. This site's docs search does the same with i",{"id":656,"title":657,"text":658},"limits-and-allowed-sites","Limits and allowed sites","**All visitors, per day**: 10–5,000 messages, default 300. **Daily cap** sets what it may spend a day. **Each visitor, per minute**: 1–30, default 8. **Each visitor, per day**: 0 for no limit. **Longest message**: 200–4,000 characters. Daily counts reset at midnight UTC. A school behind one address can send 400 messages a minute, and each visitor keeps their own limit. For 30 learners, 300 a day is ten messages each. **Only these websites** (up to 20) limits where the button and frame appear, not the link.",{"id":660,"title":661,"text":662},"recordings-and-attachments","Recordings and attachments","**What it records**: each device is an anonymous visitor with a visitor code (V-…), listed in [Teach → Learners](\u002Fdashboard\u002Flearners). **Keep recordings** saves spoken messages privately. **Voice**: with a Transcribe step, **Visitors can speak** appears. With a Speech step, so does **Play answers aloud**. **Photos & files**: up to 4 files of 8 MiB each, when every step that reads the message can read them.",{"id":664,"title":665,"text":666},"what-it-makes-public","What it makes public","Anyone with the link, or on an allowed site, can chat with your agent on your key. The profile is public. Replies show their sources, but uploaded files show only their names unless the knowledge base allows opening them. The page hides your workflow, but a model can repeat its instructions. Write nothing there you wouldn't show a visitor. Visitors can't see each other's conversations. People sharing one computer and browser are one visitor. **Pause** takes the link and embeds offline. **Turn off chat page** also clears the settings.",{"id":668,"title":669,"text":670},"the-agent-profile","The agent profile","The profile is how the agent presents itself, on its chat page and in courses. In **Connect → Profile → Edit profile**, set the **Greeting**, up to four **Suggested questions** and the **Notice** saying what the AI is. Changes show without publishing. [Knowledge bases](\u002Fdocs\u002Fbuild\u002Fknowledge): choose whether readers can open cited files. [Keys and costs](\u002Fdocs\u002Fproject\u002Fkeys-and-costs): give the page its own key and budget.",{"id":672,"title":673,"lead":674,"pages":675},"connect","Connect an app","Run agents from your own software, with learners and traces.",[676,695,726,759,782,803],{"path":677,"title":678,"description":679,"updated":13,"minutes":14,"sections":680},"connect\u002Ffirst-run","Your first run","Create an API key, run a published agent from your server for one of your users, and find that run in VIABLE.",[681,683,687,691],{"id":17,"title":17,"text":682},"In fifteen minutes you create an API key, run a published agent from your own server for one of your users, and find that run in VIABLE with its learner and its trace. Start here when your app has its own sign-in and screens and uses VIABLE agents behind them. You need a VIABLE Developer account, a project, and a published agent in it. To make one, see [Your first agent](\u002Fdocs\u002Fbuild\u002Ffirst-agent). For a first call to a model from your code, with no agent yet, the [Developer quickstart](\u002Fquickstart) takes five minutes.",{"id":684,"title":685,"text":686},"create-a-key-and-find-the-agent","Create a key and find the agent","**Create an API key.** On **Overview**, choose **Connect your app → Create an API key**, or open [Operate → API keys](\u002Fdashboard\u002Fkeys) and choose **Create key**. **Choose a service key.** In a shared project, pick **Service key**: it belongs to the project and keeps working when members change. The owner creates these. **Name it and keep its scope.** Name it after the app and environment, such as \"Writing App · production\". Under **Scopes**, keep **Run agents** (`agents:execute`). **Store the secret.** Copy it from the dialog and store it on your server as `VIABLE_API_KEY`. **Find the agent's ",{"id":688,"title":689,"text":690},"run-the-agent-for-one-user","Run the agent for one user","`user` is your app's ID for the person. The `X-Platform-*` headers name your app. The same call in Node.js 18 or newer: A successful run returns `200` with `object: \"agent.run.result\"`, a `conversation_id` (`agtc_…`), a `run_id` (`agtr_…`), `output`, `usage` and `cost`. The reply is `output.text`. An error returns an `error` object with `message`, `type` and `code`. Branch on `code`. The key stays on your server. Never put it in browser JavaScript, an app bundle or a repository. Your web or mobile code calls your server, and only your server calls VIABLE.",{"id":692,"title":693,"text":694},"see-the-run-in-viable","See the run in VIABLE","**Open the run.** Open the agent and choose **Test → Run history**. Your run is at the top, marked **API · runs**, with a learner code (`L-…`). Open it to see each step, what it received and returned, and every VETTING round. **Meet the learner.** Follow the learner code to [Teach → Learners](\u002Fdashboard\u002Flearners). The learner shows \"Known by My App (my-app:student-0001)\", and the turn carries your app's name. **Find the request.** In [Operate → Request logs](\u002Fdashboard\u002Flogs), open **More filters** and set **Platform ID** to `my-app`. You see the run and each model call inside it. Within second",{"path":696,"title":697,"description":698,"updated":13,"minutes":14,"sections":699},"connect\u002Flearners-and-traces","Learners and traces","Name your app's users as learners, keep their conversations, and store a trace of what each run did.",[700,702,706,710,714,718,722],{"id":17,"title":17,"text":701},"Name the person behind each run so VIABLE keeps them as a learner, and record what each run did. Set this up before real people use your app.",{"id":703,"title":704,"text":705},"name-your-users-with-user","Name your users with user","Send `user` on every run: a stable, opaque ID your server derives from the account it verified, up to 128 characters. Namespace it (`my-app:7f3a9c21`) or hash it. Never use a name, an email, a shared account or an unchecked ID. The first run with a new `user` creates a learner in the project, with a learner code (`L-…`). Later runs, on any agent in the project, add turns to it. [Teach → Learners](\u002Fdashboard\u002Flearners) lists them with your app's name and your ID. Viewers see that ID too. **Research → Export**, with **Your apps (API)**, exports their turns, and what you [send as learning data](\u002Fd",{"id":707,"title":708,"text":709},"label-task-groups-with-learner-group","Label task groups with learner_group","Send `learner_group` with `user` to label a turn's task group, such as `\"Grade 8\"`. It is kept on the turn, never in the prompt. **Teach → Learners → Group** filters by it, and `turns.csv` includes it. It never changes a course section or study condition. Without `user`, it returns 400.",{"id":711,"title":712,"text":713},"keep-the-conversation","Keep the conversation","By default VIABLE keeps the conversation. The first run returns a `conversation_id`. Store it per person, thread and agent, and send it with each new `input`. Never share one among people. Only the key that started it can continue it. To move a thread your app already has, seed it: send `messages` with two or more entries, the last from the user, and no `conversation_id`. The response carries the new `conversation_id`. To keep history yourself, send `history_mode: \"client\"` with the full `messages`.",{"id":715,"title":716,"text":717},"ask-for-the-trace","Ask for the trace","Add `\"include\": [\"trace\"]` to `\u002Fruns` or `\u002Fjobs`. The result then has `trace`. `duration_ms` is wall-clock time. Don't add up steps: parallel branches overlap. `steps[]` lists each step's `node_type`, `status`, `model`, `tokens`, `cost` and `error`. `vetting[]` has one entry per VETTING step: `outcome` (`passed`, `unverified`, `attention`), `attempts` (more than one means a rewrite) and each round's `verdict` and `feedback`.",{"id":719,"title":720,"text":721},"read-a-run-back","Read a run back","`GET \u002Fv1\u002Fagents\u002F{slug}\u002Fruns\u002F{run_id}`, with the key that made the run, returns it with its `trace`. Runs from another key, a course or a chat page return 404 `run_not_found`.",{"id":723,"title":724,"text":725},"what-to-store","What to store","Keep one record per turn on your server: For failed requests, also keep the HTTP status, `error.code` and `error.request_id`. A trace holds what learners wrote. Keep it on your server, never in the learner's browser, and never show it to learners. [Send learning data](\u002Fdocs\u002Fconnect\u002Flearning-data): add what learners do, write and score in your app. [Background jobs and retries](\u002Fdocs\u002Fconnect\u002Fjobs-and-retries): retry a turn without running it twice. [Export](\u002Fdocs\u002Fresearch\u002Fexport): download your app's turns for analysis.",{"path":727,"title":728,"description":729,"updated":13,"minutes":14,"sections":730},"connect\u002Flearning-data","Send learning data","Record what learners do in your app (events, drafts, ratings and scores) so it joins their learner record and the research export.",[731,733,737,739,743,747,751,755],{"id":17,"title":17,"text":732},"VIABLE sees only your app's agent runs. Send the rest from your server: what learners did and wrote, how they rated replies and how they scored. It joins the learners your runs already name.",{"id":734,"title":735,"text":736},"what-you-get","What you get","**Insights** in [Build → Apps](\u002Fdashboard\u002Fapps): active learners, time writing, pauses, pastes, drafts handed in, ratings and learner groups, day by day. **A timeline per learner** in [Teach → Learners](\u002Fdashboard\u002Flearners): their work in your app by activity, and their scores. **The research export** with your app's data (`writing.csv` measures how each draft was written), ready for [Coding](\u002Fdocs\u002Fresearch\u002Fcoding). To have your coding AI wire it up, paste this message in your app's code:",{"id":116,"title":117,"text":738},"**Give the key the scope.** In [Operate → API keys](\u002Fdashboard\u002Fkeys), choose **Edit key** on your app's key and turn on **Record learning data** (`learning:write`). **Tag every call.** Send `X-Platform-ID`, such as `writing-app`. Events and drafts are filed under your app's ID and the activity, so they need it. **Reuse your `user`.** The `user` you send on runs is the same learner here. A new `user` creates a learner.",{"id":740,"title":741,"text":742},"send-events","Send events","`POST \u002Fv1\u002Flearning\u002Fevents` takes one learner's events in one activity, up to 200 per call. Use VIABLE's event kinds, such as `writing.progress` (keys, pastes, pauses, active time), `writing.snapshot` (the text at a pause), `writing.submit` and `panel.view`, or `app.event` for your own, with a flat `data` object. Each kind keeps only its own fields. The response lists any event it skipped, by index.",{"id":744,"title":745,"text":746},"save-drafts","Save drafts","`POST \u002Fv1\u002Flearning\u002Fdrafts` saves the `draft`, and the `plan` if your app has one, as they are now: send the whole text each time. Add `submit: true` when the learner hands it in.",{"id":748,"title":749,"text":750},"rate-replies","Rate replies","When a learner marks a reply helpful or not, send `POST \u002Fv1\u002Fagents\u002F{slug}\u002Fruns\u002F{run_id}\u002Frating` with `rating` set to `1`, `-1`, or `null` to take it back. It uses **Run agents** and works only for runs this key made.",{"id":752,"title":753,"text":754},"send-scores","Send scores","`POST \u002Fv1\u002Flearning\u002Foutcomes` records one `measure`, such as a rubric total, for up to 1,000 users. A user that no run, event or draft has named yet comes back in `unmatched`.",{"id":756,"title":757,"text":758},"where-it-lands","Where it lands","**Research → Export**, with **Your apps (API)**, or one app from its Insights: events in `workspace_events.csv`, drafts and how they were written in `writing.csv`, ratings in `turns.csv`, scores in `outcomes.csv`. A run with `user` also keeps its `context` as the turn's `workspace`. [Build → Apps](\u002Fdashboard\u002Fapps): the checklist marks each kind your app has sent, and **Insights** counts it. Consent is your app's to handle: tell learners what it records before you send anything. Keep `user` opaque, as on your runs: never a name or an email. [Learners and traces](\u002Fdocs\u002Fconnect\u002Flearners-and-trace",{"path":760,"title":761,"description":762,"updated":13,"minutes":14,"sections":763},"connect\u002Fjobs-and-retries","Background jobs and retries","Pick the right route for an agent call, run long work as a background job, and retry without running a turn twice.",[764,766,770,774,778],{"id":17,"title":17,"text":765},"Every published agent answers on three routes. Pick the one that fits the work, and retry an unanswered request safely.",{"id":767,"title":768,"text":769},"choose-a-route","Choose a route","All three run the same agent and share keys, `user` and `learner_group`. `\u002Fruns` `\u002Fjobs` `\u002Fchat\u002Fcompletions` You send `input`, optional `conversation_id` The same, plus `Idempotency-Key` `model` (the slug) and `messages` You get The result, or a stream `202` and a job to poll `choices[0].message.content` Time 60 s, or the agent's 10–120 5 minutes or more As `\u002Fruns` In the dashboard API · runs API · background job API · chat completions Start with `\u002Fruns` when someone is waiting; `\"stream\": true` streams the reply. Use `\u002Fjobs` for long research, image generation, or a host that cuts requests sh",{"id":771,"title":772,"text":773},"run-a-background-job","Run a background job","The `202` has an `id` (`agtj_…`), a `status_url` and a `Retry-After` header. Wait that long between polls. `queued` or `running`: poll again. `completed`: `result` is the body `\u002Fruns` returns. `failed`: `error` has the `code`. To try again, submit a new job with a new key. A job not started within 15 minutes fails with `agent_job_expired`, and one that stopped before its run began with `agent_job_interrupted`: nothing ran, so send the turn again. `recovery_required`: the run had started, and completion is uncertain: it may have drawn an image or called a web address. Check Run history; don't s",{"id":775,"title":776,"text":777},"retry-safely","Retry safely","Send an `Idempotency-Key` with every turn: 8–128 letters, digits, dots, underscores, colons or hyphens. Save the route, body and key on your server. If no answer arrives, resend the same body to the same route with the same key. **The run completed:** you get the same result. **Still going:** 409 `agent_request_pending`. Retry later with the same key. **The body differs:** 409 `idempotency_conflict`. **It started, then failed** (such as `provider_timeout`): the key keeps that error. Retry with a new key. **Rejected before it started** (validation, 401, 403, 404, 413, rate or spending limits): ",{"id":779,"title":780,"text":781},"limits-and-errors","Limits and errors","**Size:** 12 MiB per request, `context` up to 128 KiB, up to 400 `messages`. **Rate:** a key's per-minute limit covers all your users: thirty learners in one class share it. **429:** wait for `Retry-After`. For token, cost or credit limits, don't retry in a loop. Branch on `error.code`, and never show an error as the agent's reply. The [API reference](\u002Fdocs\u002Fapi) lists every code. [Learners and traces](\u002Fdocs\u002Fconnect\u002Flearners-and-traces): keep each turn's run ID and trace. [Keys, credit and costs](\u002Fdocs\u002Fproject\u002Fkeys-and-costs): set a key's limits and see who pays.",{"path":783,"title":784,"description":785,"updated":13,"minutes":14,"sections":786},"connect\u002Fembed","Your page in an activity","Put your own web page inside a course activity, record what learners do in it, and let the AI beside it know.",[787,789,793,797,799],{"id":17,"title":17,"text":788},"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.",{"id":790,"title":791,"text":792},"set-up-the-activity","Set up the activity","**Serve your page over https.** Let `https:\u002F\u002Fpage.viablelearning.org` frame it, for example with `Content-Security-Policy: frame-ancestors https:\u002F\u002Fpage.viablelearning.org`. **Add the panel.** In [Teach → Courses](\u002Fdashboard\u002Fcourses), 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 e",{"id":794,"title":795,"text":796},"add-the-bridge","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: `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 li",{"id":159,"title":160,"text":798},"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.",{"id":800,"title":801,"text":802},"what-gets-recorded","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](\u002Fdocs\u002Fteach\u002Factivities): build the activity around your page. [Export](\u002Fdocs\u002Fresearch\u002Fexport): download the events with the course's data.",{"path":804,"title":805,"description":806,"updated":13,"minutes":14,"sections":807},"connect\u002Fapps","Build → Apps","See what each app's learners did, what it still needs, and connect any app with one message to your coding AI.",[808,810,812,816,820,824],{"id":17,"title":17,"text":809},"Connect your app once and its learners get VIABLE's research tools. Check this page after your first run and before launch.",{"id":734,"title":735,"text":811},"**Insights**: learners, sessions, AI use and ratings, writing, events and learner groups, day by day. **A timeline per learner** in [Teach → Learners](\u002Fdashboard\u002Flearners): runs, work and scores. **The research export** of your app's data alone, documented for R, Python or SPSS. **[Coding](\u002Fdocs\u002Fresearch\u002Fcoding)** of what learners asked, by your team or a model. **[VETTING](\u002Fdocs\u002Fbuild\u002Fvetting)**: a reviewer checks each reply against your rules. **Studies**, once your page runs [in a course activity](\u002Fdocs\u002Fconnect\u002Fembed). Data your app sends alone is never in a study.",{"id":813,"title":814,"text":815},"connect-it-with-your-coding-ai","Connect it with your coding AI","**Paste the message** below into Claude Code, Codex or any agent with a terminal, in your app's code. **Review its changes.** It installs the VIABLE CLI and Skill if missing, then wires your server to send `user`, `X-Platform-ID`, traces and learning data. **Check it here.** Your app appears with its checklist and **Insights**.",{"id":817,"title":818,"text":819},"what-it-shows","What it shows","[Build → Apps](\u002Fdashboard\u002Fapps) lists every app that sent requests or learning data with the project's keys in the last 90 days. There is nothing to register. An app is its `X-Platform-ID`. Untagged requests are grouped by key. **Insights** counts 30 or 90 days as the research export does; hover a measure for its definition. **Download its data** exports that app alone. **Its requests** opens Request logs filtered to the app. Chat pages, courses and the Playground aren't apps.",{"id":821,"title":822,"text":823},"the-checklist","The checklist","A missing step links to its guide: **Calls with a project key**, **Runs an agent**, **Names its users** (`user`), **Tags its requests** (`X-Platform-ID`), **Labels task groups** (`learner_group`, if you need it), then the learning data rows of [Send learning data](\u002Fdocs\u002Fconnect\u002Flearning-data).",{"id":825,"title":826,"text":827},"tag-your-requests","Tag your requests","Send these optional headers from your server on every call. Choose them before launch: logs can't be re-tagged. Header Use it for `X-Platform-ID` A stable ID for your app, such as `writing-app`. `X-Platform-Name` Its readable name, such as `Writing App`. `X-Operation-Type` The feature, such as `give-feedback`, from a small, stable set. `X-Request-ID` Your own correlation ID, such as a session and turn. Values are cut at 240 characters (`X-Request-ID` at 200). Never put names or emails in them. [Request logs](\u002Fdashboard\u002Flogs) filter by **Platform ID**, **Operation** and your request ID; the res",{"id":829,"title":830,"lead":831,"pages":832},"project","Run a project","People, keys, costs and logs.",[833,856,879,906],{"path":834,"title":835,"description":836,"updated":13,"minutes":14,"sections":837},"project\u002Fmembers-and-roles","Members and roles","Make a shared project, invite people in the right roles, and hand the project to a new owner.",[838,840,844,848,852],{"id":17,"title":17,"text":839},"Decide who works in your project and what each person can do.",{"id":841,"title":842,"text":843},"make-a-shared-project","Make a shared project","A project is your team's space: its agents, courses, studies, keys and logs belong to it. Open [Account → Projects](\u002Fdashboard\u002Fprojects), choose **New project**, name it, and choose **Create project**. You become its owner. Your personal project, shown with a lock, is private and can't be shared.",{"id":845,"title":846,"text":847},"roles","Roles","Owner Editor Viewer See keys (no secrets), logs, usage, agents and members Yes Yes Yes See learners' names, student IDs and personal codes Yes Yes Codes only Change agents, courses, question sets and studies Yes Yes No Invite and manage members; manage shared provider keys Yes If the owner allows No Create service keys, transfer, archive; pays for usage Yes No No An editor can change every course in the project, not only their own. For a teacher who should run one course only, [share that course](\u002Fdocs\u002Fteach\u002Fsharing) instead. A research assistant who only codes in **Research → Coding** can be ",{"id":849,"title":850,"text":851},"invite-people","Invite people","In the project's **Members**, choose **Invite member**. Type a name or email address, pick **Viewer** or **Editor** as the **Role**, and choose **Invite member**. Someone with an account gets access at once. Others show as **Pending** until they sign in with that email. Each member's **…** menu can pause or remove them. Removing a member, or making an editor a viewer, revokes their personal API keys; if an app or course runs on one, make it a service key first.",{"id":853,"title":854,"text":855},"transfer-ownership","Transfer ownership","**Start the offer.** Open **Settings → Transfer ownership**, or the member's **…** menu. **Choose the new owner.** Pick an active member who has signed in as the **New owner**. **Send it.** Read **After they accept** and choose **Send offer**. They have 7 days to accept, under **Review offer** on the project's **Overview**. Until then you stay the owner, keep paying, and can **Cancel offer**. When they accept, you become an editor. Every API key moves to their account, so new requests use their credit and their personal provider keys. Past usage stays with you, and unused credit doesn't move. ",{"path":857,"title":858,"description":859,"updated":13,"minutes":14,"sections":860},"project\u002Fkeys-and-costs","Keys, credit and costs","Give each app, course and chat page a key paid the way you intend, and know who pays for every request.",[861,863,867,871,875],{"id":17,"title":17,"text":862},"Give each piece of work its own key, set its limits, and know who pays. The project's owner pays for every request.",{"id":864,"title":865,"text":866},"api-keys","API keys","An API key, made in [Operate → API keys](\u002Fdashboard\u002Fkeys), is how code calls VIABLE. A **service key** belongs to the project and keeps working when people leave. Only the owner makes one. Use it for apps, courses and chat pages. A **personal key** belongs to the member who made it. It stops if they are paused, leave or become a viewer. Choose **Create key** (editors see **Create personal key**), set its **Scopes**, **Limits** and **Model access**, and keep the secret on your server. Before someone leaves, the owner can choose **Make service key** on their key. **Scopes:** courses and chat pag",{"id":868,"title":869,"text":870},"a-course-s-or-chat-page-s-key","A course's or chat page's key","**A course:** its **Settings → The AI → The AI key: who pays for the course's AI**. **AI messages per learner per day** can cap each learner. **A chat page:** the agent's **Chat page → Key & limits → Runs on**. Use a service key, one per course or chat page, so **Usage** shows what each costs. A whole class shares the course's key. A low daily token limit can stop the AI for all 30 learners mid-lesson.",{"id":872,"title":873,"text":874},"provider-keys-and-key-pools","Provider keys and key pools","Under [Account → Billing → Provider keys](\u002Fdashboard\u002Fprovider-keys), add your own keys for OpenAI, Google Gemini, UF NaviGator or another OpenAI-compatible endpoint. Requests then bill your provider, not VIABLE credits, with no code changes. Keys for one provider form a **key pool**: when one runs out or is rejected, the next takes over. A lab can pool its grant keys.",{"id":876,"title":877,"text":878},"credit-and-who-pays","Credit and who pays","[Account → Billing → Credits](\u002Fdashboard\u002Fcredits) shows one balance. Every project you own draws from it, whichever member's key made the request. Request Paid by A catalog model whose provider has a pool set to **Every … model request** That pool A catalog model with no such pool The owner's VIABLE credits A model called as `@name\u002F\u003Cmodel>` That pool A pool with no key available An error, or credits if the pool chose **Use VIABLE credits** The project's **Overview** shows the result under **How this project is billed**. Costs are estimated from listed model prices; an agent run costs the sum o",{"path":880,"title":881,"description":882,"updated":13,"minutes":14,"sections":883},"project\u002Flogs-and-usage","Request logs and usage","Find any request your project made, see the model calls inside an agent run, export logs, and track what it all costs.",[884,886,890,894,898,902],{"id":17,"title":17,"text":885},"Find a request, see what an agent run called, and track what your project spends. Use it when a learner reports a strange reply, or to plan a budget.",{"id":887,"title":888,"text":889},"find-a-request","Find a request","[Operate → Request logs](\u002Fdashboard\u002Flogs) keeps every API call in the current project: time, status, endpoint, model, key, tokens, cost, latency, and what was sent and returned. Logs aren't deleted on a schedule. **Pick a range.** Choose when it happened. **Search.** Type a VIABLE request ID, a run ID, or your app's `X-Request-ID` in **Find a request, run, or client ID**. **Filter.** Narrow by **API key**, **Endpoint**, **Model**, **Status** or **Errors only**. **More filters** adds **Platform ID**, **Operation**, **Agent**, and Playground or agent test requests. **Open it.** Choose a row to s",{"id":891,"title":892,"text":893},"a-run-s-model-calls","A run's model calls","An agent run is one row. Expand it to see each model call's step, model, status and share of the time, and choose a call for its details. **Trace** opens the run step by step.",{"id":895,"title":896,"text":897},"paid-by","Paid by","Once the project has key pools, **Paid by** filters to **VIABLE credits**, **Any key pool**, or one pool. The summary line then separates credit cost from requests on your keys.",{"id":899,"title":900,"text":901},"export","Export","**Set the filters.** The export holds every request that matches, with its payloads. **Start it.** Choose **Export**, pick **CSV** or **JSONL**, and start it. **Download it.** It is prepared on the server, so you can leave the page. It stays under **Recent exports** for 24 hours. One export runs at a time. Viewers can export too. Request logs and their exports include what learners wrote to the AI, and every member can read them. A CLI log export can leave the text out with `--no-bodies`.",{"id":903,"title":904,"text":905},"usage","Usage","[Operate → Usage](\u002Fdashboard\u002Fusage) shows requests, errors, tokens and estimated cost for the current project. Set a **Date range**, from **7 days** to **All time** or **Custom**. Filter by **API key**, **Model** and, with key pools, **Paid by**. **Group by** **Day**, **API key**, **Model**, **Endpoint** or **Paid by**. Choose a total at the top to chart it. In **Breakdown**, choose a row to filter the page, or **Logs** to see its requests. Filter to one key to see how much of each limit it has used. **Who paid** splits requests and cost between credits and each pool. For **All time**, or more",{"path":907,"title":908,"description":909,"updated":111,"minutes":14,"sections":910},"project\u002Fcli","The CLI and Agent Skills","Let your own AI work in VIABLE as you: build a course, set up a study or connect an app, with one message to set it up.",[911,913,917,921,925],{"id":17,"title":17,"text":912},"Your own AI can do VIABLE work for you: build a course, set up a study, connect an app. The VIABLE CLI (`viable`) acts as you, with your access, and its Agent Skill teaches your AI to use it safely.",{"id":914,"title":915,"text":916},"let-your-ai-set-it-up","Let your AI set it up","Paste this one message into your AI: Where to paste it: **If you don't code**: Claude Cowork in the Claude desktop app, ChatGPT Work in the ChatGPT app, or Gemini with **Task** chosen under the prompt box. Start a new task and paste the message. **If you build software**: Claude Code, Codex, Google Antigravity, or any agent with a terminal. **It installs the CLI and the Skill.** The guide tells your AI what to install where it works, and how to check it. **You approve the sign-in.** It shows you a link and a code; you approve in your own browser. It never sees your password. **Then ask in your",{"id":918,"title":919,"text":920},"what-to-ask-it","What to ask it","You Ask, for example Teacher \"Make a course for Period 2 with a writing activity and a tutor that gives hints only, then send me the preview link.\" Researcher \"Set up an observational study on that course with consent, and upload our approved consent form.\" App developer \"Connect our server to VIABLE: name each user, tag our requests, send learning data, then check Build → Apps.\" Owner \"Show last week's cost by key and model.\" It can't do more than your role allows, since VIABLE checks every request. Every change needs an exact `--confirm` value, and the Skill tells your agent to show you what",{"id":922,"title":923,"text":924},"install-it-yourself","Install it yourself","Prefer the terminal? You need Node.js 22 or newer. On a remote machine or a cloud agent, sign in with `viable auth login --device`. `viable agent install --target` takes `codex`, `claude`, `kimi` or `qwen`. `viable help` lists the commands. `viable doctor` checks the setup, and `viable update --with-skill` keeps both current. Signing in never creates an account: register at https:\u002F\u002Fdevelopers.viablelab.org first. [Resources → CLI & Agent Skills](\u002Fdashboard\u002Fcli) has the same steps.",{"id":926,"title":927,"text":928},"agents-and-these-docs","Agents and these docs","The Skill reads the [API guide](https:\u002F\u002Fdevelopers.viablelab.org\u002Fagents\u002Fviablelab-api.md) for current routes, fields and errors. Any agent can start from [llms.txt](https:\u002F\u002Fdevelopers.viablelab.org\u002Fllms.txt), which lists every page here as Markdown. The CLI and its Skill are open source under the MIT License. [Members and roles](\u002Fdocs\u002Fproject\u002Fmembers-and-roles): what your role lets your AI do. [Send learning data](\u002Fdocs\u002Fconnect\u002Flearning-data): connect an app, or let your AI do it. [Your first class](\u002Fdocs\u002Fteach\u002Ffirst-class): what your AI builds, step by step.",{"id":930,"title":931,"lead":932,"pages":933},"resources","Open resources","The public learning-science resources VIABLE builds on, and their licenses.",[934,961],{"path":935,"title":936,"description":937,"updated":13,"minutes":46,"sections":938},"resources\u002Flearning-commons","Learning Commons","How VIABLE uses Learning Commons' Knowledge Graph for standards, skills and math misconceptions, what it keeps, and how to credit it.",[939,941,945,949,953,957],{"id":17,"title":17,"text":940},"VIABLE reads academic standards and durable skills from [Learning Commons](https:\u002F\u002Flearningcommons.org)' Knowledge Graph, an open dataset of standards, skills and what they break into. This page explains what VIABLE takes from it, when, and what you owe it when you share your work.",{"id":942,"title":943,"text":944},"what-viable-uses","What VIABLE uses","The Knowledge Graph connects standards and skills to smaller pieces of learning. VIABLE uses five parts of it, all in an activity's **How the AI helps**: In the Knowledge Graph In VIABLE Academic standards **K-12 standard**: every state, Washington, D.C. and Common Core, pre-K to grade 12 Learning components **It breaks into**: the skills inside a standard Prerequisite relations **Standards before it**: what the AI can go back to Carnegie Skills Progressions **Durable skill**: collaboration, communication and critical thinking, at four levels Eedi Misconceptions Graph **Misconceptions to liste",{"id":946,"title":947,"text":948},"when-viable-asks-and-what-it-keeps","When VIABLE asks, and what it keeps","**You choose a standard or a skill.** While you search for a standard, VIABLE asks Learning Commons, and keeps each answer for a day. Durable skills and misconceptions come from VIABLE's own copy. **VIABLE keeps a copy.** What you pick, with the pieces you leave ticked, is saved in the activity's version, with its source and license. **Learners never wait on it.** When a learner sends a message, the agent reads that saved copy. Learning Commons isn't asked again. So a change at Learning Commons never changes what an activity's AI was already given, and your research export says exactly what ea",{"id":950,"title":951,"text":952},"looked-up-or-copied","Looked up, or copied","Learning Commons publishes the graph two ways: an API, and release files of about a gigabyte. VIABLE uses each where it works best. **Standards are looked up.** The API finds a standard from a teacher's own words, and stays current without VIABLE storing it. The saved copy means learners' runs never depend on it. **Durable skills are copied.** The API doesn't search them yet, so VIABLE carries the Carnegie Skills Progressions from the release files: 31 indicators, each at four levels. **Misconceptions are copied, and matched by words.** The release files carry Eedi's 8,117 math misconceptions ",{"id":954,"title":955,"text":956},"crediting-it","Crediting it","The Knowledge Graph is licensed [CC BY 4.0](https:\u002F\u002Fcreativecommons.org\u002Flicenses\u002Fby\u002F4.0\u002F), and Carnegie and Eedi share their parts under the same license. VIABLE shows the attribution beside every standard, skill and misconception, and keeps it in the saved copy. When you publish materials or data that include their text, credit them, for example: \"Standards from the Learning Commons Knowledge Graph, CC BY 4.0.\" or \"Misconceptions from the Eedi Misconceptions Graph v1.0, (c) 2026 Eedi Ltd., via Learning Commons, CC BY 4.0.\"",{"id":958,"title":959,"text":960},"not-teaching-k-12","Not teaching K-12?","A durable skill fits learners of any age, and a goal in your own words fits anyone: a university seminar, an adult literacy class, a library workshop. See [How the AI helps](\u002Fdocs\u002Fteach\u002Fai-helps). [Standards, skills and misconceptions](\u002Fdocs\u002Fteach\u002Fstandards-and-skills): choose them for an activity. [The research export](\u002Fdocs\u002Fresearch\u002Fexport): what each activity version used, in one download.",{"path":962,"title":963,"description":964,"updated":13,"minutes":14,"sections":965},"resources\u002Flicenses","Licenses and credit","What VIABLE builds on, under which licenses, and how to credit it when you publish materials, papers or data.",[966,968,972,976,980],{"id":17,"title":17,"text":967},"VIABLE builds on open research and open data. This page lists what it uses, under which license, and what to credit when you share a course, a paper or a dataset made with it.",{"id":969,"title":970,"text":971},"what-viable-builds-on","What VIABLE builds on","Resource What VIABLE uses it for License [Learning Commons Knowledge Graph](\u002Fdocs\u002Fresources\u002Flearning-commons) Standards, what they break into, and the standards before them [CC BY 4.0](https:\u002F\u002Fcreativecommons.org\u002Flicenses\u002Fby\u002F4.0\u002F) [Eedi Misconceptions Graph v1.0](\u002Fdocs\u002Fresources\u002Flearning-commons), (c) 2026 Eedi Ltd., via Learning Commons Math misconceptions to listen for, and the skills they hinder [CC BY 4.0](https:\u002F\u002Fcreativecommons.org\u002Flicenses\u002Fby\u002F4.0\u002F) [VETTING](https:\u002F\u002Fgithub.com\u002Fhichipli\u002Fvetting-python) Checking each reply against rules and an answer key MIT (reference implementation) [Th",{"id":973,"title":974,"text":975},"where-the-credit-already-appears","Where the credit already appears","You don't have to add attribution inside VIABLE. It is already there: **In the activity editor**, beside every standard, with the date it was retrieved, and under the misconceptions. **In the activity's version**, which keeps each standard's and misconception's source, license and attribution. **In the research export.** `manifest.json` keeps each activity version's settings, standard and misconceptions included. When a version used them, `README.md` says how to credit them. **In the data dictionary**, measures name the papers they come from.",{"id":977,"title":978,"text":979},"when-you-publish","When you publish","**Materials with a standard's or a misconception's text.** Add a line such as: \"Standards from the Learning Commons Knowledge Graph, CC BY 4.0.\" or \"Misconceptions from the Eedi Misconceptions Graph v1.0, (c) 2026 Eedi Ltd., via Learning Commons, CC BY 4.0.\" **A paper about an agent that uses VETTING.** Cite the [VETTING study](https:\u002F\u002Fdoi.org\u002F10.1016\u002Fj.caeai.2026.100646). **A dataset from the research export.** Keep `README.md`, `manifest.json` and `data_dictionary.csv` with it, so others know what each column means and where it comes from. Learners' data isn't open data. Share an export only",{"id":981,"title":982,"text":983},"your-own-materials-and-the-models","Your own materials and the models","What you and your learners put into VIABLE is covered by VIABLE's [Terms of Service](https:\u002F\u002Fwww.viablelab.org\u002Fterms-of-service) and [Privacy Policy](https:\u002F\u002Fwww.viablelab.org\u002Fprivacy-policy). Replies come from the model you choose, and that model's provider sets its own usage terms. [Models](\u002Fmodels) lists each provider. When a question set or a knowledge base holds someone else's material, its license still applies. Keep its credit with it, for example in the question set's description or the document itself. [Learning Commons](\u002Fdocs\u002Fresources\u002Flearning-commons): what VIABLE takes from it, wh",{"meta":985,"blocks":986,"headings":990,"sections":995},{"path":783,"title":784,"description":785,"updated":13,"minutes":14},[987],{"type":988,"html":989},"html","\u003Cp>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.\u003C\u002Fp>\n\u003Cp>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.\u003C\u002Fp>\n\u003Ch2 id=\"set-up-the-activity\">Set up the activity\u003Ca class=\"doc-anchor\" href=\"#set-up-the-activity\" aria-label=\"Link to this section\">\u003C\u002Fa>\u003C\u002Fh2>\n\u003Cdiv class=\"doc-steps\">\u003Col>\n\u003Cli>\u003Cstrong>Serve your page over https.\u003C\u002Fstrong> Let \u003Ccode>https:\u002F\u002Fpage.viablelearning.org\u003C\u002Fcode> frame it, for example with \u003Ccode>Content-Security-Policy: frame-ancestors https:\u002F\u002Fpage.viablelearning.org\u003C\u002Fcode>.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Add the panel.\u003C\u002Fstrong> In \u003Ca href=\"\u002Fdashboard\u002Fcourses\">Teach → Courses\u003C\u002Fa>, open the course, add an activity, and add an \u003Cstrong>Embedded page\u003C\u002Fstrong> panel with your page's address.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Choose what the agent is shown.\u003C\u002Fstrong> If the activity has an agent, pick \u003Cstrong>Its events\u003C\u002Fstrong>, \u003Cstrong>Nothing\u003C\u002Fstrong> or \u003Cstrong>Custom\u003C\u002Fstrong>.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Say how it ends.\u003C\u002Fstrong> Turn on \u003Cstrong>It says when the learner is done\u003C\u002Fstrong> if your page reports completion. Otherwise learners press &quot;I'm done&quot;.\u003C\u002Fli>\n\u003C\u002Fol>\n\u003C\u002Fdiv>\u003Cp>Serve the page from exactly that address: a redirect to another origin cuts the connection. The frame is sandboxed (\u003Ccode>allow-scripts allow-same-origin allow-forms allow-popups allow-pointer-lock\u003C\u002Fcode>) and gets no referrer.\u003C\u002Fp>\n\u003Ch2 id=\"add-the-bridge\">Add the bridge\u003Ca class=\"doc-anchor\" href=\"#add-the-bridge\" aria-label=\"Link to this section\">\u003C\u002Fa>\u003C\u002Fh2>\n\u003Cp>Any page works as it is. To record what happens and tell the agent, add a few \u003Ccode>postMessage\u003C\u002Fcode> calls. The panel's \u003Cstrong>Connect your page (optional)\u003C\u002Fstrong> offers them to copy:\u003C\u002Fp>\n\u003Cdiv class=\"guide-code\">\u003Cdiv class=\"guide-code-head\">\u003Cspan>js\u003C\u002Fspan>\u003Cbutton type=\"button\" data-copy-code aria-label=\"Copy js code\">Copy\u003C\u002Fbutton>\u003C\u002Fdiv>\u003Cpre>\u003Ccode class=\"hljs\">\u003Cspan class=\"hljs-keyword\">let\u003C\u002Fspan> session = \u003Cspan class=\"hljs-literal\">null\u003C\u002Fspan>\n\u003Cspan class=\"hljs-variable language_\">window\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">addEventListener\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;message&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">e\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> {\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (e.\u003Cspan class=\"hljs-property\">origin\u003C\u002Fspan> !== \u003Cspan class=\"hljs-string\">&#x27;https:\u002F\u002Fpage.viablelearning.org&#x27;\u003C\u002Fspan>) \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (e.\u003Cspan class=\"hljs-property\">data\u003C\u002Fspan>?.\u003Cspan class=\"hljs-property\">viable\u003C\u002Fspan> === \u003Cspan class=\"hljs-number\">1\u003C\u002Fspan> &amp;&amp; e.\u003Cspan class=\"hljs-property\">data\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">type\u003C\u002Fspan> === \u003Cspan class=\"hljs-string\">&#x27;hello&#x27;\u003C\u002Fspan>) session = e.\u003Cspan class=\"hljs-property\">data\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">session\u003C\u002Fspan>\n})\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">viable\u003C\u002Fspan> = (\u003Cspan class=\"hljs-params\">message\u003C\u002Fspan>) =&gt; \u003Cspan class=\"hljs-variable language_\">window\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">parent\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">postMessage\u003C\u002Fspan>({ \u003Cspan class=\"hljs-attr\">viable\u003C\u002Fspan>: \u003Cspan class=\"hljs-number\">1\u003C\u002Fspan>, ...message }, \u003Cspan class=\"hljs-string\">&#x27;https:\u002F\u002Fpage.viablelearning.org&#x27;\u003C\u002Fspan>)\n\n\u003Cspan class=\"hljs-title function_\">viable\u003C\u002Fspan>({ \u003Cspan class=\"hljs-attr\">type\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;hello&#x27;\u003C\u002Fspan> }) \u003Cspan class=\"hljs-comment\">\u002F\u002F asks for hello again, if you started listening late\u003C\u002Fspan>\n\u003Cspan class=\"hljs-title function_\">viable\u003C\u002Fspan>({ \u003Cspan class=\"hljs-attr\">type\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;event&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">verb\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;answered&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">object\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;level-2&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">success\u003C\u002Fspan>: \u003Cspan class=\"hljs-literal\">true\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">score\u003C\u002Fspan>: \u003Cspan class=\"hljs-number\">1\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">max_score\u003C\u002Fspan>: \u003Cspan class=\"hljs-number\">1\u003C\u002Fspan> })\n\u003Cspan class=\"hljs-title function_\">viable\u003C\u002Fspan>({ \u003Cspan class=\"hljs-attr\">type\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;state&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">data\u003C\u002Fspan>: { \u003Cspan class=\"hljs-attr\">level\u003C\u002Fspan>: \u003Cspan class=\"hljs-number\">2\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">pieces\u003C\u002Fspan>: \u003Cspan class=\"hljs-number\">3\u003C\u002Fspan> } })\n\u003Cspan class=\"hljs-title function_\">viable\u003C\u002Fspan>({ \u003Cspan class=\"hljs-attr\">type\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;ask&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">text\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Can I get a hint?&#x27;\u003C\u002Fspan> })\n\u003C\u002Fcode>\u003C\u002Fpre>\u003C\u002Fdiv>\u003Cp>\u003Ccode>session\u003C\u002Fcode> is a random ID for this visit. Ignore other origins.\u003C\u002Fp>\n\u003Cdiv class=\"guide-table\">\u003Ctable>\u003Cthead>\n\u003Ctr>\n\u003Cth>\u003Ccode>type\u003C\u002Fcode>\u003C\u002Fth>\n\u003Cth>What happens\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\n\u003Ctr>\n\u003Ctd>\u003Ccode>event\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>Kept as an event: a \u003Ccode>verb\u003C\u002Fcode> and optionally \u003Ccode>object\u003C\u002Fcode>, \u003Ccode>score\u003C\u002Fcode>, \u003Ccode>max_score\u003C\u002Fcode>, \u003Ccode>success\u003C\u002Fcode>, \u003Ccode>completion\u003C\u002Fcode>, \u003Ccode>response\u003C\u002Fcode>, \u003Ccode>duration_ms\u003C\u002Fcode> and \u003Ccode>data\u003C\u002Fcode>.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>state\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>What your page shows now, kept at most every 5 seconds.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>ask\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>Puts \u003Ccode>text\u003C\u002Fcode> in the chat box for the learner to send. Nothing is sent for them.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>hello\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>Asks for the \u003Ccode>hello\u003C\u002Fcode> again if your page started listening late.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\n\u003C\u002Ftable>\u003C\u002Fdiv>\u003Cp>Prefer xAPI verbs: \u003Ccode>attempted\u003C\u002Fcode>, \u003Ccode>answered\u003C\u002Fcode>, \u003Ccode>completed\u003C\u002Fcode>, \u003Ccode>passed\u003C\u002Fcode>, \u003Ccode>failed\u003C\u002Fcode>, \u003Ccode>progressed\u003C\u002Fcode>, \u003Ccode>interacted\u003C\u002Fcode>. \u003Ccode>data\u003C\u002Fcode> holds up to 20 fields of numbers, true\u002Ffalse values or strings up to 200 characters. With \u003Cstrong>It says when the learner is done\u003C\u002Fstrong>, the first \u003Ccode>completed\u003C\u002Fcode> event, or one with \u003Ccode>completion: true\u003C\u002Fcode>, counts toward the activity being done.\u003C\u002Fp>\n\u003Ch2 id=\"what-the-ai-sees\">What the AI sees\u003Ca class=\"doc-anchor\" href=\"#what-the-ai-sees\" aria-label=\"Link to this section\">\u003C\u002Fa>\u003C\u002Fh2>\n\u003Cp>With \u003Cstrong>Its events\u003C\u002Fstrong>, 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. \u003Cstrong>Custom\u003C\u002Fstrong> sets 0–20 events and whether the state is included. The agent's \u003Cstrong>Profile\u003C\u002Fstrong> sets where this enters the prompt, and any step can read it as \u003Ccode>{{context.workspace}}\u003C\u002Fcode>. Learners are told on the panel what the agent sees.\u003C\u002Fp>\n\u003Ch2 id=\"what-gets-recorded\">What gets recorded\u003Ca class=\"doc-anchor\" href=\"#what-gets-recorded\" aria-label=\"Link to this section\">\u003C\u002Fa>\u003C\u002Fh2>\n\u003Cp>Events and states are kept with the learner, course, activity and activity version, at every recording level. The research export has them in \u003Ccode>workspace_events.csv\u003C\u002Fcode>. When a study runs in the course, its consent and conditions apply as in any activity.\u003C\u002Fp>\n\u003Cdiv class=\"doc-cards\">\u003Cul>\n\u003Cli>\u003Ca href=\"\u002Fdocs\u002Fteach\u002Factivities\">Activities\u003C\u002Fa>: build the activity around your page.\u003C\u002Fli>\n\u003Cli>\u003Ca href=\"\u002Fdocs\u002Fresearch\u002Fexport\">Export\u003C\u002Fa>: download the events with the course's data.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003C\u002Fdiv>",[991,992,993,994],{"level":14,"id":790,"text":791},{"level":14,"id":794,"text":795},{"level":14,"id":159,"text":160},{"level":14,"id":800,"text":801},[996,997,998,999,1000],{"id":17,"title":17,"text":788},{"id":790,"title":791,"text":792},{"id":794,"title":795,"text":796},{"id":159,"title":160,"text":798},{"id":800,"title":801,"text":802},1793404882922]