Files
classroomio/prd/ai-course-assistant/README.md
T

281 lines
10 KiB
Markdown
Raw Normal View History

2026-03-09 11:18:22 +01:00
---
name: AI Course Assistant
overview: An AI-powered assistant embedded in the course UI that helps teachers organize content—update lesson text, tag exercises, generate questions from existing content, and draft lessons. Cloud-only; self-hosted instances cannot use this feature.
todos:
- id: prd-review
content: Finalize PRD with stakeholders, resolve open questions
status: pending
- id: architecture-decision
content: Decide agent execution model (API-first vs local-first)
status: pending
- id: package-scaffold
content: Create packages/ai-assistant package with API client
status: pending
- id: agent-api-routes
content: Design and implement agent API routes with auth + org scoping
status: pending
- id: chat-ui
content: Build chat interface in right sidebar (Sheet)
status: pending
- id: nav-integration
content: Add AI assistant button to course navigation/header
status: pending
- id: self-host-gate
content: Hide assistant and block agent routes when PUBLIC_IS_SELFHOSTED
status: pending
- id: safeguards
content: Enforce org/course permission checks in all agent actions
status: pending
isProject: false
---
# AI Course Assistant
## Purpose
Deliver an AI assistant inside the course UI that teachers can use to:
- **Update content**: "Update this piece of text in this lesson"
- **Tag exercises**: Tag an exercise and provide context
- **Generate questions**: "Given this text, come up with 5 new questions"
- **Draft lessons**: Ask the agent to write the initial draft of a lesson
The assistant operates in a right sidebar chat interface, triggered by an "AI Assistant" button in the course navigation.
## Goals
- Help teachers organize and author course content faster
- Operate strictly within the current org/course context (no cross-org access)
- Integrate natively with existing ClassroomIO APIs (lessons, exercises, content)
- Cloud-only; self-hosted users cannot use the AI assistant
## Non-Goals (v1)
- Student-facing AI (tutors/teachers only)
- Cross-course or cross-org operations
- Offline or fully local execution without API
- Custom model selection or fine-tuning
---
## Architecture Overview
```mermaid
flowchart TB
subgraph client [Dashboard Client]
NavButton["AI Assistant Button"]
ChatUI["Right Sidebar Chat"]
end
subgraph cloud [Cloud / API]
AgentService["Agent Service (packages/ai-assistant or API)"]
CourseAPI["Course / Lesson / Exercise APIs"]
end
subgraph db [Database]
LessonTable["lesson / lesson_language"]
ExerciseTable["exercise / exercise_template"]
ContentTable["course_content"]
end
NavButton -->|"Open"| ChatUI
ChatUI -->|"User message + context"| AgentService
AgentService -->|"Validate + Call"| CourseAPI
CourseAPI -->|"Persist"| db
CourseAPI -->|"Response"| ChatUI
```
---
## 1. Execution Model: API vs Local
**Open question**: How does the agent apply changes—via API directly, or by suggesting edits locally in the UI?
### Option A: API-First (Recommended for v1)
- Agent sends **structured intents** (e.g. `{ type: "update_lesson_text", lessonId, locale, payload }`) to a dedicated **agent API**
- Agent API validates permissions, calls existing services (`updateLessonService`, `updateLessonLanguageService`, etc.), returns results
- Client receives success/failure and refreshes or updates the relevant store
- **Pros**: Single source of truth, audit trail, reuses existing safeguards
- **Cons**: Slightly more latency; requires agent backend
### Option B: Local-First
- Agent returns **edit suggestions** as structured data (e.g. JSON patches)
- Client applies changes in the editor UI; user must explicitly accept (e.g. "Apply" button)
- Actual persistence happens through existing APIs when user saves
- **Pros**: Lower latency, no new backend routes
- **Cons**: More complex client logic; risk of sync drift; harder to audit
### Recommendation
**Start with Option A (API-First)**:
1. Reuse existing `courseTeamMemberMiddleware`, `orgMemberMiddleware`, and org/course checks
2. Agent executes actions via the same services used by the UI
3. Simpler mental model: agent is a "programmatic teacher" that talks to the same API
4. Easier to add rate limits, logging, and abuse prevention later
---
## 2. UI Specification
### Placement
- **Button**: "AI Assistant" in the **course header** (alongside Search, Notifications), visible only to teachers (not students)
- **Panel**: Right sidebar implemented with `@cio/ui` Sheet (`side="right"`), ~400px width on desktop
- **Mobile**: Full-screen sheet or drawer (reuse `lesson-version-history.svelte` pattern)
### Chat Interface
- Message list with user/assistant turns
- Text input at bottom with send button
- Optional: quick actions / suggested prompts (e.g. "Draft a lesson", "Generate 5 questions")
- Loading state while agent processes
- Error states with retry
### Context Awareness
- Pass `courseId`, `orgId`, `lessonId` (if viewing a lesson), `exerciseId` (if viewing an exercise) to the agent
- Agent can reference: "Update the text in the lesson you're viewing" without the user specifying IDs
---
## 3. Safeguards
### Authorization (Reuse Existing Middleware)
All agent API routes must use:
| Middleware | Purpose |
|------------|---------|
| `authMiddleware` | Require authenticated user |
| `orgMemberMiddleware` | Require `cio-org-id` and org membership |
| `courseTeamMemberMiddleware` | Require course team (ADMIN/TUTOR) or org admin |
### Scoping Rules
1. **Org scope**: Every action is scoped to the org in `cio-org-id` header
2. **Course scope**: Lesson/exercise edits must belong to a course where the user is a team member
3. **No cross-org**: Agent must never accept or execute requests for lessons/exercises in another org
### Implementation
- Agent API extracts `courseId`, `lessonId`, `exerciseId` from request payload
- Before any mutation, verify:
- Course belongs to the org
- User is `courseTeamMember` or `orgAdmin`
- Reuse `isCourseTeamMemberOrOrgAdmin` and `isUserOrgTeamMember` from `@cio/db/queries`
---
## 4. Self-Hosted vs Cloud
### Cloud (ClassroomIO-Hosted)
- AI assistant is **enabled** for teachers (within plan limits, if any)
- ClassroomIO provides the LLM API keys; no user configuration needed
### Self-Hosted
- AI assistant is **not available**. Self-hosters cannot use this feature.
- **Implementation**: Hide the "AI Assistant" button when `PUBLIC_IS_SELFHOSTED === 'true'`. Agent API routes return `403` or are not registered when self-hosted.
---
## 5. Package Design: `packages/ai-assistant`
The agent should live in a **package** that works natively with ClassroomIO APIs.
### Package Responsibilities
- **SDK / client**: Types and helpers for calling the agent API from the dashboard
- **Shared types**: Intent schemas, message formats
- **No UI**: UI stays in `apps/dashboard`; package is backend + types
### Suggested Structure
```
packages/ai-assistant/
src/
index.ts # Public exports
types.ts # Message, intent, response types
client.ts # Agent API client (optional; dashboard may use classroomio RPC)
package.json
tsconfig.json
```
### Agent API (in `apps/api`)
- New routes under e.g. `/course/:courseId/agent` or `/organization/agent`
- Routes: `POST /chat` (stream or non-stream), `POST /execute` (for structured intents)
- Agent service: interpret user message, map to intents, call lesson/exercise services, return result
### Complexity Estimate
| Component | Complexity | Notes |
|-----------|------------|-------|
| Package scaffold | Low | Thin wrapper around types + optional client |
| Agent API routes | Medium | Auth, validation, orchestration |
| LLM integration | Medium–High | Depends on provider (OpenAI, Anthropic, etc.) |
| Chat UI | Medium | Standard chat + Sheet |
| Self-host gate | Low | Env check + conditional render |
---
## 6. Data Sources & APIs (Existing)
| Action | API / Service | Auth |
|--------|---------------|------|
| Update lesson text | `PUT /course/:courseId/lesson/:lessonId/language/:locale` | courseTeamMember |
| Update lesson metadata | `PUT /course/:courseId/lesson/:lessonId` | courseTeamMember |
| Tag exercise (template tag) | Exercise template has `tag`; create/update exercise | courseTeamMember |
| Tag course (org tags) | `PUT /course/:courseId/tags` | courseTeamMember |
| Create lesson | `POST /course/:courseId/lesson` | courseTeamMember |
| Create exercise | Exercise creation flow | courseTeamMember |
| Get lesson content | `GET /course/:courseId/lesson/:lessonId` | courseMember |
Agent actions should call these through the existing service layer, not bypass them.
---
## 7. Suggested Implementation Phases
### Phase 1: Foundation
1. Add "AI Assistant" button to course header (hidden when self-hosted)
2. Add right Sheet with placeholder chat UI (no backend)
3. Create `packages/ai-assistant` with types and client stubs
4. Add agent API route skeleton with `courseTeamMemberMiddleware`
### Phase 2: Chat + Execution
1. Implement agent API `POST /chat` with LLM integration
2. Implement intent parsing: update lesson, generate questions, draft lesson
3. Wire agent to `updateLessonService`, `createLesson`, exercise services
4. Connect chat UI to API; display responses and errors
### Phase 3: Polish
1. Add quick-action prompts
2. Add context injection (current lesson/exercise)
3. Rate limiting and usage tracking (if needed)
---
## 8. Open Questions
1. **Streaming**: Should responses stream (SSE/WebSocket) or be non-streaming for v1?
2. **LLM provider**: OpenAI, Anthropic, or configurable per deployment?
3. **Rate limits**: Per-user, per-org, or per-course? Needed for cloud cost control?
4. **Exercise tagging**: Does "tag an exercise" mean org-level course tags, or exercise-template tags (e.g. mcq, coding)? Clarify semantics.
5. **Draft persistence**: When agent drafts a lesson, does it create a draft immediately or return text for user to paste? Recommendation: create draft via API, user reviews before publishing.
---
## 9. Success Criteria
- Teachers can open the AI assistant from the course header and chat in a right sidebar
- Agent can update lesson text, create draft lessons, and generate questions (as defined in Phase 2)
- No user can modify another org's data; all actions pass permission checks
- Self-hosted instances cannot use the assistant; UI and API are gated
- Agent package integrates cleanly with existing API and dashboard structure