Operations
The morning brief
What it reads, what it writes, and how to customize it.
The morning brief is Mayva’s flagship worker. It runs at 06:00 local, reads your context, and writes a structured plan for the day.
What it reads
In order of priority:
- Last night’s recovery (
health_signalskind=recovery) — the band drives the tone. - Sleep duration & efficiency (
health_signalskind=sleep). - Today’s calendar (
calendar_eventswhere date = today). - Yesterday’s outcomes (
outcomesjoined totasksfrom yesterday). - Active goals (
data/goals/*.md). - Profile preferences (
data/profile/preferences.md,prohibitions.md). - Inbox signal (
email_signalsunread count from non-newsletter senders).
All of this is composed in packages/core/agent/context.ts::buildBriefContext(). About 1,500 tokens of input on a typical day.
What it writes
const MorningBriefSchema = z.object({
date: z.string(), // YYYY-MM-DD
recoveryBand: z.enum(['green','yellow','red','none']),
body: z.string(), // 3-5 sentence narrative
items: z.array(z.object({
title: z.string(),
priority: z.enum(['p0','p1','p2']),
durationMin: z.number().int().positive(),
suggestedStart: z.string().optional(), // ISO timestamp
reason: z.string(), // why this item, not just what
})),
protectives: z.array(z.string()), // "skip heavy lifting today"
});
One row in morning_brief per date. Re-running overwrites idempotently.
How tone changes with recovery
packages/core/agent/morning-brief.ts swaps a fragment of the system prompt by band:
| Band | Tone fragment |
|---|---|
| green | ”It’s a green day. Schedule the hardest work first. Don’t waste it.” |
| yellow | ”Recovery is yellow. Protect deep work. Defer hard meetings. Two items on the must-do list, not five.” |
| red | ”Recovery is red. This is a protective day. Default to lower-strain work. Re-evaluate plans that require physical or social energy.” |
| none | (no fragment — pure planning, no health editorializing) |
These fragments are strings in the file. Edit them. Re-run pnpm brief. Done.
Customizing the prompt
// packages/core/agent/morning-brief.ts
const SYSTEM = `
You are Mayva's morning brief author. Your job is to plan the day for the user
based on the context provided. Be concise. Lead with the recovery state.
${toneFragment(band)}
Output structured JSON matching MorningBriefSchema. The body field is 3-5
sentences total, narrative voice, second-person. The items field is 2-7 entries.
Priorities: p0 is non-negotiable (health, safety, scheduled commitments), p1 is
work toward active goals, p2 is everything else.
Never invent calendar events. Never say "I" — the brief is your output, not your
voice. Never editorialize about health beyond the tone fragment above.
`;
Common edits:
- Switch model: change
model: 'claude-3-5-sonnet'to'claude-3-5-haiku'for ~4× cheaper at modest quality loss. - Different time: change
croninpackages/workers/src/scheduled/morning-brief.ts. The cron string is on line 5. - Different schema: edit
MorningBriefSchemainpackages/shared/src/schemas/brief.ts. The dashboard’sMorningBriefCardreads the same schema, so it’ll keep working as long as the shape stays compatible. - Different memory layers: add to
buildBriefContext()inpackages/core/agent/context.ts.
When the brief decides not to run
If recovery for today is missing and Whoop is enabled, the brief waits up to 30 minutes for the next whoop-sync to populate it. After that, it runs with band: 'none'.
If data/profile/ is empty (fresh install), the brief refuses to run and emits a single suggestion: “set up your profile — see docs/getting-started.” Defensive — we don’t want a useless brief on day one.
Reading yesterday’s outcomes
A reliable brief considers what you actually did, not just what you planned. The outcomes table holds explicit completions, but most “done” signals are implicit (the task is past its window, it’s not marked deferred, no further activity). The brief composer uses a getYesterdayOutcomes() function that:
- Lists tasks with
status='done'from yesterday. - Lists tasks with
status='pending'from yesterday → likely missed. - Looks at
worker_runsfor any agent-dispatched actions that completed.
This gives the brief enough to say “you missed the finance review but knocked out the hard work in the morning; today, protect the morning again.”