ParentInsights Agent
| File | lib/agents/parentInsightsAgent.ts (runParentInsightsAgent) |
| Triggered by | app/api/parent-insights/route.ts (on Parent Insights page load) |
| Model | gemini-2.5-pro (Vertex AI) |
What it does
Reads the child's quiz history from Firestore (up to 20 most recent quizzed stories) and generates a parent-friendly reading progress report:
- Progress summary — 2-3 sentences describing how the child is doing
- Topics enjoyed — story themes the child gravitates towards (e.g. "underwater adventures", "magical animals")
- Quiz highlight — best quiz moment or most recent improvement
- Encouragement tip — one practical action the parent can take
- Overall progress —
excellent/good/developingbased on average quiz score
The report is shown in-app at /parent-insights and can be emailed to the parent via nodemailer (Gmail SMTP).
Tools
| Tool | Parameters |
|---|---|
submit_parent_insights | childSummary, topicsEnjoyed[], quizHighlight, encouragementTip, overallProgress |
Progress logic
| Average score | overallProgress |
|---|---|
| ≥ 80% | "excellent" |
| 50–79% | "good" |
| < 50% | "developing" (framed positively as a growth opportunity) |
Caching
Uses the same latestQuizDate cache strategy as LearningAdvisor:
- Client reads
sessionStoragekeyparent_insights_{uid}→ shows cached summary instantly - Client sends
lastKnownQuizDateto the API - API compares against Firestore's latest
lastQuizDate - Match → returns
{ upToDate: true }(0 Gemini tokens) - New quiz → runs Gemini, returns fresh summary, client updates cache
The Refresh indicator on the page is non-interactive — the summary auto-refreshes only when a new quiz is completed.
Email delivery
When the parent taps Send Now, the API:
- Generates a fresh summary (always, bypasses cache)
- Sends a styled HTML email via nodemailer using Gmail SMTP (
EMAIL_USER,EMAIL_PASS,EMAIL_SERVER,EMAIL_PORTfrom.env.local) - Saves
lastSentAt,email, andfrequencyto Firestoreusers/{uid}/settings/parentInsights
Parent settings (email + frequency) are persisted in Firestore via lib/firebase/parentSettings.ts.
Flow
Parent opens /parent-insights
│
▼
Read sessionStorage cache → show instantly if present
│
▼
POST /api/parent-insights { action: "get", userId, lastKnownQuizDate }
│
├─ Fetch stories with quiz scores from Firestore (up to 20 most recent)
│
├─ latestQuizDate === lastKnownQuizDate?
│ │ YES → { upToDate: true } (0 Gemini tokens)
│ │
│ ▼ NO
│ ParentInsights LLM call
│ └── submit_parent_insights({
│ childSummary: "...",
│ topicsEnjoyed: ["magical animals", ...],
│ quizHighlight: "...",
│ encouragementTip: "...",
│ overallProgress: "good"
│ })
│
▼
Page shows: progress badge, summary, quiz highlight, topics, tip
Parent enters email + picks weekly/monthly → Send Now
│
▼
POST /api/parent-insights { action: "send", parentEmail, frequency }
│
├─ Generate fresh summary (always)
├─ Send HTML email via nodemailer
└─ Save lastSentAt to FirestoreInput / Output
typescript
// Input (QuizRecord[]) — same as LearningAdvisor
{
storyTitle: string;
storyPrompt: string;
score: number;
total: number;
language: string;
completedAt: string; // ISO string
}[]
// Output (ParentInsightsSummary)
{
childSummary: string; // 2-3 sentences for the parent
topicsEnjoyed: string[]; // 2-4 story themes
quizHighlight: string; // 1 sentence about a quiz achievement
encouragementTip: string; // 1 actionable tip for the parent
overallProgress: "excellent" | "good" | "developing";
}Stateless agent design
Configured with includeContents: "none" — same as QuizMaster. Prevents session history accumulation and infinite tool-call loops.
Observability span
Span name: agent/ParentInsights
| Attribute | Example value |
|---|---|
agent.name | ParentInsights |
agent.model | gemini-2.5-pro |
agent.quiz_count | 6 |
agent.avg_score | 78 |
agent.progress | good |
agent.duration_ms | 3100 |
