07 · Calendar & weather context¶
The app reads two external context sources; this chapter explains how each one steers the recommendation.
The styling knowledge behind context is taught in Part II: §S3 · Occasion and context explains why five canonical occasion tags is the minimum useful taxonomy; §S4 · Weather and layering explains the temperature bands and the <60°F outerwear threshold.
Two external context streams enter the agent every run. This chapter documents both.
Calendar¶
Today: mock JSON¶
The prototype reads calendar_events.json — a list of 6 demo events spanning a week. Each event has:
{
"id": "EVT001",
"title": "Team Strategy Meeting",
"date": "2026-05-12",
"time": "10:00 AM",
"type": "work",
"formality": "business",
"notes": "Presenting quarterly results to senior leadership"
}
calendar_tool.get_upcoming_events(days_ahead=7) filters to the next N days and returns the next chronological event.
Production: real calendars¶
The architecture is calendar-source-agnostic. The agent only depends on the shape of an event. To swap in a real source we replace the body of get_upcoming_events():
| Source | Implementation path |
|---|---|
| Google Calendar | OAuth flow, google-api-python-client, fetch primary calendar, map fields. |
| Apple Calendar | No public API on iOS. Prototype uses .ics upload; production needs a native app or CalDAV. |
| Outlook 365 | Microsoft Graph API, similar OAuth pattern. |
.ics upload |
A small stdlib parser; suitable for the prototype today. |
A future wearly/lib/ics_import.py will accept an uploaded .ics, extract events for the next seven days, and write them into the same shape that calendar_events.json uses today. No agent changes needed.
Privacy¶
Calendar data never leaves the device in the prototype. Production would store events server-side per user, encrypted at rest, with explicit revocable consent.
Weather¶
Today: live Open-Meteo¶
weather_tool.get_weather() calls api.open-meteo.com/v1/forecast. No API key, no rate-limit issues for the demo. The default location is hard-coded to Minneapolis (44.9778, -93.2650) — production lets the user pick a city or opt in to geolocation.
The tool returns:
{
"city": "Minneapolis, MN",
"temp_f": 58.0,
"feels_like_f": 49.0,
"condition": "Partly Cloudy",
"wind_mph": 13.8,
"precip_chance_pct": 5,
"layer_advice": "A light jacket or trench coat is recommended."
}
layer_advice is generated from temp_f, precip_chance_pct, and wind_mph via simple thresholds:
| Temp | Advice |
|---|---|
| < 32°F | "Heavy coat, scarf, and gloves are essential." |
| < 45°F | "Wear a warm coat." |
| < 58°F | "A light jacket or trench coat is recommended." |
| < 70°F | "Light layers work well — a cardigan or blazer is enough." |
| ≥ 70°F | "No coat needed. Light, breathable clothing is ideal." |
Plus precipitation and wind addenda when thresholds are crossed.
The fallback path¶
If the network call raises any exception (timeout, DNS, blocked, rate-limited), the tool returns a deterministic seasonal estimate:
{ "temp_f": 52, "condition": "Partly Cloudy", "layer_advice": "A light jacket or coat is recommended.", ... }
The result dict includes a "error" string explaining the fallback. The UI surfaces this as a fallback status on the workflow card. The demo never breaks because of a network blip.
Privacy¶
Location is a single lat/lon used only for the weather call. Open-Meteo doesn't require an account. No reverse geocoding is performed; the city name is a display string only.
How calendar + weather drive the outfit¶
| Input | Influences |
|---|---|
| Event type | Occasion tag → wardrobe pool |
| Event formality | Dress-vs-separates branching, accessory choice |
| Temperature | Season (used in pool filter), outerwear inclusion |
| Condition | Layer advice surfaced in the UI; future: fabric choice |
| Wind | Layer advice; future: flow-fabric avoidance |
| Precip% | Layer advice; future: waterproof outerwear preference |
The connection between context and recommendation is explicit in the reasoning trail. Open the "Full Agent Reasoning" expander on any outfit result and you'll see lines that name temperature and weather as drivers — not just "outerwear added" but "outerwear added because it's 58°F."
Where to verify¶
- The mock data:
calendar_events.json. - The calendar tool:
calendar_tool.py. - The weather tool:
weather_tool.py. - The agent step that consumes both:
styling_agent.py(steps 1 and 3).
Key terms¶
- Calendar context — upcoming events; falls back to casual when none are scheduled (glossary).
- Weather context — live Open-Meteo lookup with seasonal fallback (glossary).
- Occasion tag — the canonical label calendar events map to (glossary).
Self-check¶
- (Remember) Which weather data source does Wearly call, and what's the fallback when it's unreachable?
- (Understand) Why does Wearly classify by tag rather than passing the raw event title into the workflow?
- (Apply) Walk through the context Wearly assembles for a 70°F Saturday brunch with no calendar event set.
Definitions live in the Glossary. Self-check questions follow Bloom's taxonomy progression (Remember → Understand → Apply → Analyze).