Build

Interactive canvas

Kid-facing HTML in a sandboxed iframe. Avatar reactions via the Sprout SDK. Single completion call.

What you'll build

Your kid plays an interactive moment on the iPad: a mini-game, a math drill, a drawing, a quiz, a narrated story. Sprout's avatar reacts in real time to what they're doing, celebrating right answers, encouraging on misses, noticing when they're stuck. Completion gets scored, timed, or marked done.

The artifact is a one-off or recurring task in the kid app, with custom interactive HTML rendered inside it.

Pieces you'll combine

Build it

Seven movements:

1. Author the canvas (dry-run). Two-step commit so the parent sees a preview before anything ships.

Shell
canvas.create({
name: "<activity name>",
emoji: "🌟",
html: `<section id="content"><!-- your kid-facing HTML --></section>
<script>
sprout.signal("celebration");
sprout.signal("attempt-failed");
sprout.signal("user-stuck");
sprout.score({ value: finalScore, max: maxScore });
</script>`,
completionSchema: { kind: "score", maxScore: 5 },
dimensions: { age: "8-9" },
dryRun: true
})
# Returns { previewHtml, analyzerIssues, specHash }

2. Show the preview, get the OK, commit.

Shell
canvas.create({ ...same input..., dryRun: false, specHash: "<echoed>" })
# Returns { canvasId }

3. Wrap in a skill so the canvas has a governed home in your library.

Shell
skill.write({
name: "<activity name> canvas skill",
description: "Deliver the linked canvas to a kid as a one-off task.",
category: "home_agent",
prompt: "Create a task for {{input.child_id}} with the linked canvas, due {{input.date}}, with a {{input.gems}}-gem reward.",
handsReferenced: ["task_create"],
inputVariables: [{ name: "child_id" }, { name: "date" }, { name: "gems" }],
canvasIds: ["<canvasId>"]
})
# Returns { skillId }

4. Invoke the skill to deliver the task.

Shell
skill.invoke({
skillId: "<skillId>",
input: { child_id: "<kidId>", date: "2026-05-24", gems: 5 }
})
# Your agent renders the prompt, calls task.create with runMode "canvas".

5. Hook up avatar reactions inside the canvas HTML using the SDK. The signals fire mid-activity; the completion call fires once at the end.

JavaScript (inside the canvas)
// Mid-activity signals
sprout.signal("celebration");
sprout.signal("attempt-failed");
sprout.signal("user-stuck");
// Mandatory single completion call
sprout.score({ value: 4, max: 5 });
// Or: sprout.complete({ summary: "..." })
// Or: sprout.timed({ durationSeconds: 287 })

6. Give the buddy a voice (optional). Call sprout.tts.speak({ text }) to have the Sprout buddy read a prompt or hint aloud , great for pre-readers. Send only text; the buddy speaks on the kid's device (the web preview has no buddy and rejects the call). A resolved { spoken: true } means the buddy got the request, not that the audio played , so keep the words on screen too. await it inside try / catch, and call sprout.tts.stop() when you move on.

JavaScript (inside the canvas)
try {
// Send ONLY text , the buddy reads it aloud on the kid's device.
await sprout.tts.speak({ text: "Try counting the apples one by one." });
} catch {
// Rejects in the web preview (no buddy); degrade quietly , the
// on-screen hint is the source of truth.
}
// Quiet the buddy before the next question:
await sprout.tts.stop().catch(() => {});

7. Wire memory so the kid resumes. Write durable run state into sprout.state and it auto-persists as the kid works , no save button. On reopen the host seeds it with the saved snapshot before your code runs, so default-fill what's missing and branch on sprout.resumed. Never assign sprout.state = {…} wholesale , it wipes a resumed run.

JavaScript (inside the canvas)
const S = sprout.state;   // saved snapshot on resume, {} on a fresh start
S.step ??= 0;             // default-fill ONLY what's missing
S.answers ??= {};
if (sprout.resumed) goToStep(S.step);   // returning mid-run , rebuild UI
else showIntro();                        // brand-new run , intro / tutorial
S.answers.q1 = "blue";   // mutate freely; every change auto-persists

Full memory pattern: Canvases that remember.

Full SDK contract: resources/read sprout://canvas/sdk.

When to use it

Tools touched

Recommended skills

Drop these into your library to compose with this pattern.

Screen readerin prodQuiz templatetemplate

Roadmap

Seen in walkthroughs

Solar system learning loop Chore + photo proof

Was this page helpful?