-
Notifications
You must be signed in to change notification settings - Fork 45
Meeting System
Elisa's meeting system enables real-time collaborative design reviews with AI agents during the build process. Agents join meetings at key milestones to provide feedback, suggestions, and co-design alongside the kid.
Meetings are triggered automatically during builds at specific completion percentages or events (25%, 50%, 60%, deploy_started, session_complete). Each meeting features an agent with a distinct persona, a specialized canvas for collaborative design, and two-way chat. Meetings can be accepted, declined, or initiated by the kid. Canvas outputs materialize as real files in the workspace.
| Type ID | Agent | Persona | Canvas | Trigger Event | Trigger Condition | Always-On | Opt-In |
|---|---|---|---|---|---|---|---|
buddy-agent |
Buddy | Friendly teammate | explain-it |
task_completed |
>= 25% tasks done | Yes | No |
doc-agent |
Scribe | Documentation guide | explain-it |
task_completed |
>= 50% tasks done | Yes | No |
design-task-agent |
Design Review | Visual design coach | design-preview |
task_starting |
Keywords: sprite, art, icon, theme, visual, image, animation, character, logo, avatar | No | Keyword-gated |
architecture-agent |
Blueprint | Build architect | blueprint |
session_complete |
Post-build (100%) | Yes | No |
media-agent |
Marketing | Marketing director | campaign |
task_completed |
>= 25% tasks done | No | Yes |
social-media-agent |
Social Media | Social strategist | campaign |
task_completed |
>= 50% tasks done | No | Yes |
web-design-agent |
Styler | Web designer | launch-pad |
task_completed |
>= 60% tasks done AND deploy_target == "web" | No | Yes |
art-agent |
Pixel | Pixel art director | theme-picker |
deploy_started |
BOX-3 device present | No | Yes |
integration-agent |
Interface Designer | System integrator | interface-designer |
composition_started |
Nugget composition begins | No | Composition-scoped |
| Custom meetings | User-defined | User persona | Any canvas type | User-defined | User-defined | No | Opt-in via team blocks |
Each meeting follows a state machine from invitation to completion:
-
invited — Agent creates meeting invite,
meeting_inviteevent sent. Kid is notified. - accepted or declined — Kid accepts or declines within the invite toast. If accepted, moves to active.
- active — Meeting open for chat and canvas collaboration. Lasts until kid or agent ends it.
- completed — Meeting ended. Outcomes and canvas data persisted.
[invited] --accept--> [active] --end--> [completed]
|
+--decline--> [declined]
Trigger Flow:
- Orchestrator evaluates a build event (e.g., task_completed at 50%)
- MeetingTriggerEngine matches event against all registered meeting types
- For each match, team filtering checks if meeting is enabled for this session
- MeetingService.createInvite() creates the meeting and sends
meeting_inviteWS event - Frontend shows meeting invite toast with agent name and description
- Kid accepts/declines; frontend sends REST call or closes toast
- On accept, MeetingService.acceptMeeting() transitions to active, pre-populates canvas data, and sends
meeting_startedevent
The team filtering system controls which meetings fire during a build:
Always-On Defaults (fire automatically without team blocks):
-
buddy-agent(Buddy Check-in) -
doc-agent(Documentation) -
architecture-agent(Blueprint Review) -
design-task-agent(Design Review - keyword-gated on task title/description)
Opt-In Agents (require team_member blocks in the NuggetSpec):
-
media-agent(Marketing) -
social-media-agent(Social Media) -
web-design-agent(Web Designer) -
art-agent(Pixel Art) -
integration-agent(Interface Designer) - Custom meetings (kid-defined via Blockly)
Logic:
- If NuggetSpec has no
meeting_teamarray, only always-on defaults fire - If
meeting_teamis present, it acts as an allowlist: only always-on defaults + explicitly selected agents fire - Kid can add team members to the spec via Blockly
Teamblocks, each specifying a meeting type ID and optional persona customization
Each meeting type uses a specialized canvas for real-time visual collaboration:
| Canvas Type | Purpose | Features |
|---|---|---|
blueprint |
Build architecture review | Task list + health breakdown, test results, complexity, system inputs/outputs (Architecture Agent) |
explain-it |
Documentation & notes | Live markdown editor with suggestions panel (Buddy, Scribe) |
design-preview |
Live visual design | Canvas 2D drawing with palette, scene elements, background, real-time preview (Design Review) |
campaign |
Marketing assets | Poster, social card, storyboard templates for marketing collateral (Marketing, Social Media) |
launch-pad |
Web launch page | 4 template variants (hero-features, centered-minimal, split-image-text, full-banner) with hero/description/colors (Web Designer) |
theme-picker |
Device theme selection | Theme options (default, forest, sunset, pixel) for BOX-3 display (Pixel Art) |
interface-designer |
Interface contracts | Provides/requires diagram editor for nugget composition (Interface Designer) |
bug-detective |
Bug diagnosis | Bug report template with test failure details and diagnosis notes (post-build bug fixing) |
test-dashboard |
Test result review | Test status, pass/fail indicators, error messages (visual test monitoring) |
code-explorer |
Code review | File browser with annotations and highlighted lines (code discussion) |
whiteboard |
Freeform notes | Drawing canvas with text annotations (sketching ideas) |
live-preview |
Web preview | Embedded iframe of local server preview with refresh control (web review) |
agent-studio |
Custom agent canvas | Extensible for future agent types |
Meetings fire at specific points during the build pipeline:
| Milestone | Event | Agents Triggered | Use Case |
|---|---|---|---|
| 0% | Build starts | None | Initialization phase |
| 25% (early-mid) |
task_completed at 25% |
Buddy, Marketing | Early check-in & marketing kickoff |
| 50% (mid-build) |
task_completed at 50% |
Scribe, Social Media | Documentation checkpoint & social strategy |
| 60% (late-mid) |
task_completed at 60% |
Styler (web only) | Web launch page design |
| Task starts | task_starting |
Design Review (keyword-gated) | Pre-task visual design review |
| Deploy starts | deploy_started |
Pixel (BOX-3 only) | Device theme customization |
| Build complete | session_complete |
Blueprint | Final architecture review & health summary |
| Composition | composition_started |
Interface Designer | Nugget composition interface design |
Deduplication: Each meeting type fires at most once per session. Subsequent matching events are ignored.
Kids can start meetings manually from the Team tab:
- Kid clicks on an idle agent in the Team tab
- Frontend calls
POST /api/sessions/:id/meetings/startwith the meeting type ID - Backend creates invite + auto-accepts it (sets
kidInitiated: true) - Meeting opens immediately in active state
- Kid controls when to end (auto-end logic disabled for kid-initiated meetings)
This allows exploratory design conversations at any time during the build.
When a meeting is accepted, the backend pre-populates canvas data from the current build context:
Blueprint canvas — Health metrics:
-
tasks: Array of {id, title, status} -
tests: Array of {name, passed, details} -
total_tasks,tasks_done,tests_passing,tests_total -
health_score(0-100),health_grade(A-F) -
health_breakdown({tasks_score, tests_score, corrections_score, budget_score}) -
complexity(simple/moderate/complex) -
system_inputs,system_outputs(arrays of {name, type, source})
Theme-picker canvas — Current theme:
-
currentTheme(one of: "default", "forest", "sunset", "pixel")
Other canvas types receive empty {} and populate via chat interaction.
The MeetingAgentService uses two parallel Claude API calls for each agent response:
-
Chat call — Generates conversational text (plain text, NO JSON)
- System prompt: agent persona, build context, kid-friendly language rules
- Max tokens: 300
- Timeout: 45 seconds
-
Canvas call — Generates canvas data (JSON only)
- System prompt: canvas schema, field requirements, JSON-only output rules
- Max tokens: 4096
- Timeout: 45 seconds
Both calls run in parallel via Promise.allSettled, allowing graceful failure: if canvas fails, chat still returns. Canvas failures are logged as warnings (expected under load); chat timeouts are logged as errors.
This separation prevents JSON from leaking into chat (which confuses kids) and ensures structured data for the canvas.
| Method | Path | Purpose |
|---|---|---|
| GET | /api/sessions/:id/meetings |
List all meetings for session |
| GET | /api/sessions/:id/meetings/:mid |
Get single meeting details |
| POST | /api/sessions/:id/meetings/start |
Kid-initiated meeting: create invite + auto-accept |
| POST | /api/sessions/:id/meetings/:mid/accept |
Accept a meeting invite |
| POST | /api/sessions/:id/meetings/:mid/decline |
Decline a meeting invite |
| POST | /api/sessions/:id/meetings/:mid/message |
Send chat message in active meeting |
| POST | /api/sessions/:id/meetings/:mid/outcome |
Record meeting outcome (decision/artifact) |
| POST | /api/sessions/:id/meetings/:mid/end |
End an active meeting |
| POST | /api/sessions/:id/meetings/:mid/materialize |
Materialize canvas data into workspace files |
| Event | Payload | Meaning |
|---|---|---|
meeting_invite |
meetingId, meetingTypeId, agentName, title, description | New meeting invite available |
meeting_started |
meetingId, agentName, canvasType | Meeting accepted and active |
meeting_message |
meetingId, role (agent|kid), content | New message in active meeting |
meeting_canvas_update |
meetingId, canvasType, data | Canvas data updated (real-time) |
meeting_outcome |
meetingId, outcomeType, data | Outcome recorded (decision/artifact) |
meeting_ended |
meetingId, outcomes | Meeting completed |
meeting_blocking_task |
task_id, meeting_type_id | Task is blocked waiting for meeting |
meeting_unblocking_task |
task_id | Task unblocked after meeting ends |
Meeting outputs can be materialized as real files in the workspace:
| Canvas Type | Output Files | Location |
|---|---|---|
explain-it |
Markdown document | docs/{title}.md |
launch-pad |
HTML launch page | web/launch-page.html |
campaign |
HTML poster + social card |
marketing/poster.html, marketing/social-card.html
|
interface-designer |
Interface contracts JSON | design/interfaces.json |
theme-picker |
Theme config JSON | design/theme-config.json |
design-preview |
Design scene JSON | design/{scene}-design.json |
blueprint |
No files (Blueprint is review-only) | — |
bug-detective |
No files (bug diagnosis is discussion) | — |
Materialization is optional — kids can save or discard meeting outputs.
When a task is keyword-gated (e.g., a design task), the orchestrator can pause task execution and invite a design review meeting:
- Task starts with title/description matching design keywords
- MeetingTriggerWiring evaluates
task_startingtrigger -
evaluateAndInviteForTask()creates a design review meeting with task context - ExecutePhase emits
meeting_blocking_taskevent — frontend shows pulsing "Meeting" badge on task - ExecutePhase waits for meeting to complete (
waitForMeetings()) - On meeting end, ExecutePhase resumes task execution and emits
meeting_unblocking_task
This keeps visual design work collaborative without blocking the entire build.
Kids can define custom meetings via Blockly Team blocks:
Team member block:
- Agent name (text input)
- Persona (text input)
- Canvas type (dropdown: explain-it, design-preview, campaign, etc.)
- Trigger event (dropdown: task_completed, task_starting, deploy_started, session_complete)
- Trigger condition (optional text input: "at 40%", "on keywords", etc.)
Each custom meeting is registered with a generated ID (custom-<sessionId>-<index>) and receives automatic trigger conditions based on canvas type:
-
explain-it: >= 40% tasks done -
design-preview: On task_starting with design keywords -
campaign: >= 30% tasks done -
blueprint: session_complete - Others: >= 50% tasks done (default)
Custom meetings are always opt-in (require the team block) and are unregistered when the session ends.
The design-preview canvas enables live visual design collaboration using Canvas 2D JavaScript:
Agent sends:
{
"scene_title": "Game Title Screen",
"description": "Main menu with buttons",
"background": "linear-gradient(135deg, #0a0a2e, #1a1a4e)",
"palette": ["#ff006e", "#00d4ff", "#ffbe0b"],
"elements": [
{
"name": "background",
"description": "starfield",
"color": "#0a0a2e",
"draw": "ctx.fillStyle = color; ctx.fillRect(0, 0, w, h);"
},
{
"name": "title_text",
"description": "game title",
"color": "#ff006e",
"draw": "ctx.font = '32px Arial'; ctx.fillStyle = color; ctx.fillText('Play', w/2, h/3);"
}
]
}Frontend renders the canvas in real-time by executing the draw code for each element. Kid can give feedback ("Make the title bigger", "Change the background to space") and agent re-renders live.
| Scenario | Behavior |
|---|---|
| Meeting creation fails | Warning logged, meeting skipped, build continues |
| Chat API timeout | Fallback text returned, canvas still generated |
| Canvas API timeout | Logged as warning, meeting continues with empty canvas |
| Canvas JSON parse failure | Sanitization attempted (literal newlines escaped), then discarded |
| Kid declines all invites | Meetings simply removed from invite queue, build continues |
| Meeting ends mid-block | Task resumes immediately with meeting_unblocking_task event |
Meetings are wired into the orchestrator pipeline at key points:
Orchestrator.run(spec)
|-> PlanPhase: decompose into tasks
|-> ExecutePhase:
| task_completed at 25% --> evaluateAndInvite('task_completed')
| (Buddy + Marketing fire if opt-in enabled)
| task_starting --> evaluateAndInviteForTask()
| (Design Review if keywords match)
| task_completed at 50% --> evaluateAndInvite('task_completed')
| (Scribe + Social Media)
| task_completed at 60% --> evaluateAndInvite('task_completed')
| (Styler if web)
|-> TestPhase: run tests
|-> DeployPhase:
| deploy_started --> evaluateAndInvite('deploy_started')
| (Pixel if BOX-3)
|-> evaluateAndInvite('session_complete')
| (Blueprint agent final review)
For task-starting triggers that require sequential gating (only one design review at a time), ExecutePhase uses waitForMeetings() to block task execution until the meeting ends. For fire-and-forget triggers (task_completed, session_complete), meetings fire in parallel with task execution.
Elisa — A kid-friendly IDE for orchestrating AI agent teams