Split into Weather sub-agent + Daily Briefing orchestrator

This commit is contained in:
2026-04-13 01:31:53 +00:00
parent ebfa9c7154
commit e07341faf9
3 changed files with 341 additions and 0 deletions
+112
View File
@@ -0,0 +1,112 @@
#!/usr/bin/env python3
"""
Weather Agent
Fetches weather for Providence, UT and returns structured data + markdown section.
Called by the Daily Briefing agent. Can also run standalone.
"""
import sys
from datetime import datetime
from shared import MT, api_request, log_run
AGENT_ID = "weather"
# Providence, UT
LAT = 41.7064
LON = -111.8133
WEATHER_URL = (
f"https://api.open-meteo.com/v1/forecast?"
f"latitude={LAT}&longitude={LON}"
f"&current=temperature_2m,apparent_temperature,weather_code,wind_speed_10m,relative_humidity_2m"
f"&daily=weather_code,temperature_2m_max,temperature_2m_min,precipitation_sum,wind_speed_10m_max,sunrise,sunset"
f"&temperature_unit=fahrenheit&wind_speed_unit=mph&precipitation_unit=inch"
f"&timezone=America/Denver&forecast_days=7"
)
WMO_CODES = {
0: "Clear sky", 1: "Mainly clear", 2: "Partly cloudy", 3: "Overcast",
45: "Foggy", 48: "Icy fog", 51: "Light drizzle", 53: "Drizzle",
55: "Heavy drizzle", 61: "Light rain", 63: "Rain", 65: "Heavy rain",
66: "Freezing rain", 67: "Heavy freezing rain",
71: "Light snow", 73: "Snow", 75: "Heavy snow", 77: "Snow grains",
80: "Light showers", 81: "Showers", 82: "Heavy showers",
85: "Light snow showers", 86: "Heavy snow showers",
95: "Thunderstorm", 96: "Thunderstorm w/ hail", 99: "Severe thunderstorm",
}
DAY_NAMES = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
def fetch_weather():
"""Fetch weather data from Open-Meteo."""
return api_request(WEATHER_URL)
def format_section(weather):
"""Format weather into a markdown section and a one-line summary."""
now = datetime.now(MT)
current = weather["current"]
daily = weather["daily"]
condition = WMO_CODES.get(current["weather_code"], "Unknown")
temp = round(current["temperature_2m"])
feels = round(current["apparent_temperature"])
wind = round(current["wind_speed_10m"])
humidity = current["relative_humidity_2m"]
md = "## Weather\n\n"
md += "### Current Conditions\n\n"
md += "| | |\n|---|---|\n"
md += f"| **Condition** | {condition} |\n"
md += f"| **Temperature** | {temp}°F (feels like {feels}°F) |\n"
md += f"| **Wind** | {wind} mph |\n"
md += f"| **Humidity** | {humidity}% |\n\n"
md += "### 7-Day Forecast\n\n"
md += "| Day | Condition | High | Low | Precip | Wind |\n"
md += "|-----|-----------|------|-----|--------|------|\n"
for i in range(len(daily["time"])):
d = datetime.strptime(daily["time"][i], "%Y-%m-%d")
day_name = DAY_NAMES[d.weekday()]
if i == 0:
day_name = "**Today**"
elif i == 1:
day_name = "Tomorrow"
cond = WMO_CODES.get(daily["weather_code"][i], "?")
hi = round(daily["temperature_2m_max"][i])
lo = round(daily["temperature_2m_min"][i])
precip = daily["precipitation_sum"][i]
wind_max = round(daily["wind_speed_10m_max"][i])
precip_str = f'{precip}"' if precip > 0 else "-"
md += f"| {day_name} | {cond} | {hi}°F | {lo}°F | {precip_str} | {wind_max} mph |\n"
sunrise = daily["sunrise"][0].split("T")[1] if daily["sunrise"][0] else "?"
sunset = daily["sunset"][0].split("T")[1] if daily["sunset"][0] else "?"
md += f"\n**Sunrise:** {sunrise} | **Sunset:** {sunset}\n"
summary = f"{condition}, {temp}°F (feels like {feels}°F), wind {wind} mph"
return md, summary
def run():
"""Run the weather agent. Returns (markdown_section, summary) or raises."""
weather = fetch_weather()
section, summary = format_section(weather)
log_run(AGENT_ID, "success", output=summary)
return section, summary
if __name__ == "__main__":
try:
section, summary = run()
print(section)
print(f"\nSummary: {summary}")
except Exception as e:
err_msg = f"{type(e).__name__}: {e}"
print(f"Error: {err_msg}", file=sys.stderr)
log_run(AGENT_ID, "failed", err=err_msg)
sys.exit(1)