Route Researcher
Research mountain peaks across North America and generate comprehensive route beta reports combining data from multiple sources including PeakBagger, SummitPost, WTA, AllTrails, weather forecasts, avalanche conditions, and trip reports.
Overview
Route Researcher
Research mountain peaks across North America and generate comprehensive route beta reports combining data from multiple sources including PeakBagger, SummitPost, WTA, AllTrails, weather forecasts, avalanche conditions, and trip reports.
Data Sources: This skill aggregates information from specialized mountaineering websites (PeakBagger, SummitPost, Washington Trails Association, AllTrails, The Mountaineers, and regional avalanche centers). The quality of the generated report depends on the availability of information on these sources. If your target peak lacks coverage on these websites, the report may contain limited details. The skill works best for well-documented peaks in North America.
When to Use This Skill
Use this skill when the user requests:
- Research on a specific mountain peak
- Route beta or climbing information
- Trip planning information for peaks
- Current conditions for mountaineering objectives
Examples:
- "Research Mt Baker"
- "I'm planning to climb Sahale Peak next month, can you research the route?"
- "Generate route beta for Forbidden Peak"
Progress Checklist
Research Progress:
- Phase 1: Peak Identification (peak validated, ID obtained)
- Phase 2: Peak Information Retrieval (coordinates and details obtained)
- Phase 3: Data Gathering (parallel execution)
- Phase 3a: Python conditions fetch (weather, air quality, daylight, avalanche, peakbagger stats/ascents)
- Phase 3b: Researcher agents (3 in parallel - web sources + trip reports)
- Phase 3c: Results aggregated
- Phase 3d: Access/permits (inline WebSearch)
- Phase 4: Route Analysis (synthesize route, crux, hazards)
- Phase 5: Report Generation (Report Writer agent)
- Phase 6: Report Review & Validation (Report Reviewer agent)
- Phase 7: Completion (user notified, next steps provided)
Orchestration Workflow
Phase 1: Peak Identification
Goal: Identify and validate the specific peak to research.
-
Extract Peak Name from user message
- Look for peak names, mountain names, or climbing objectives
- Common patterns: "Mt Baker", "Mount Rainier", "Sahale Peak", etc.
-
Search PeakBagger using peakbagger-cli:
uvx --from git+https://github.com/dreamiurg/peakbagger-cli.git@v1.7.0 peakbagger peak search "{peak_name}" --format json- Parse JSON output to extract peak matches
- Each result includes: peak_id, name, elevation (feet/meters), location, url
-
Handle Multiple Matches:
-
If multiple peaks found: Use AskUserQuestion to present options
- For each option, show: peak name, elevation, location, AND PeakBagger URL
- Format each option description as: "[Peak Name] ([Elevation], [Location]) - [PeakBagger URL]"
- This allows user to click through and verify the correct peak
- Let user select the correct peak
- Provide "Other" option if none match
-
If single match found: Confirm with user
- Present confirmation message with peak details and PeakBagger link
- Show: "Found: [Peak Name] ([Elevation], [Location])"
- Include PeakBagger URL in the message so user can verify: "[PeakBagger URL]"
- Use AskUserQuestion: "Is this the correct peak? You can verify at [PeakBagger URL]"
-
If no matches found:
- Try peak name variations systematically (see "Peak Name Variations" section):
- Word order reversal: "Mountain Pratt" → "Pratt Mountain"
- Title variations: Mt/Mount, St/Saint
- Add location: Include state or range name
- Remove titles: Try just the core name
- Run multiple searches in parallel with different variations
- Combine results and present best matches to user
- If still no results, use AskUserQuestion to ask for:
- A different peak name variation
- Direct PeakBagger peak ID or URL
- General PeakBagger search
- Try peak name variations systematically (see "Peak Name Variations" section):
-
-
Extract Peak ID:
- From search results JSON, extract the
peak_idfield - Store for use in subsequent peakbagger-cli commands
- Also store the PeakBagger URL for reference links
- From search results JSON, extract the
Phase 2: Peak Information Retrieval
Goal: Get detailed peak information and coordinates needed for location-based data gathering.
This phase must complete before Phase 3, as coordinates are required for weather, daylight, and avalanche data.
Retrieve detailed peak information using the peak ID from Phase 1:
uvx --from git+https://github.com/dreamiurg/peakbagger-cli.git@v1.7.0 peakbagger peak show {peak_id} --format json
This returns structured JSON with:
- Peak name and alternate names
- Elevation (feet and meters)
- Prominence (feet and meters)
- Isolation (miles and kilometers)
- Coordinates (latitude, longitude in decimal degrees)
- Location (county, state, country)
- Routes (if available): trailhead, distance, vertical gain
- Peak list memberships and rankings
- Standard route description (if available in routes data)
Error Handling:
- If peakbagger-cli fails: Fall back to WebSearch/WebFetch and note in "Information Gaps"
- If specific fields missing in JSON: Mark as "Not available" in gaps section
- Rate limiting: Built into peakbagger-cli (default 2 second delay)
Once coordinates are obtained from this step, immediately proceed to Phase 3.
Phase 3: Data Gathering
Goal: Gather comprehensive route information from all available sources.
Execution Strategy: Run Python script for deterministic API data + dispatch specialized agents in parallel for web research. This hybrid approach minimizes token usage while maximizing parallelism.
Step 3A: Fetch Conditions Data (Python Script)
Run the conditions fetcher script to gather all API-based data:
cd "{repo_root}/skills/route-researcher/tools"
uv run python fetch_conditions.py \\
--coordinates "{latitude},{longitude}" \\
--elevation {elevation_m} \\
--peak-name "{peak_name}" \\
--peak-id {peak_id}
This returns JSON with:
- weather: 7-day forecast with temperatures, precipitation, freezing levels
- air_quality: AQI ratings and any concerns
- daylight: Sunrise, sunset, civil twilight
- avalanche: NWAC region and URL for manual check
- peakbagger: Ascent statistics and recent ascents (if peak_id provided)
- gaps: Any API failures noted for report
Run this in parallel with Step 3B — include both the Bash command for fetch_conditions.py and all 3 Task calls in the same response turn to maximize parallelism.
Step 3B: Dispatch Researcher Agents (Parallel)
Dispatch 3 Researcher agents in a single message (all Task calls together). Each agent researches assigned sources and fetches trip report content directly.
Agent 1: PeakBagger + SummitPost
Task(
subagent_type="general-purpose",
model="sonnet",
prompt="""You are a route researcher gathering mountaineering data for {peak_name}.
## Your Assignment
Research from these sources: PeakBagger, SummitPost
## PeakBagger Research
1. Search: "{peak_name} site:peakbagger.com"
2. Extract route descriptions from peak page
3. List recent ascents with trip reports:
```bash
uvx --from git+https://github.com/dreamiurg/peakbagger-cli.git@v1.7.0 peakbagger peak ascents {peak_id} --format json --with-tr --limit 20
-
Identify trip reports with content (word_count > 0)
-
Fetch content for up to 5 recent trip reports using:
uvx --from git+https://github.com/dreamiurg/peakbagger-cli.git@v1.7.0 peakbagger ascent show {ascent_id} --format json
SummitPost Research
-
Search: "{peak_name} site:summitpost.org"
-
Use WebFetch to extract: route name, difficulty, approach, description, hazards
-
If WebFetch fails, use:
uv run python {repo_root}/skills/route-researcher/tools/cloudscrape.py "{url}"
Trip Report Extraction
For each report fetched, extract: date, author, route conditions, gear mentioned, hazards.
Output Format (return EXACTLY this JSON)
{
"sources": ["PeakBagger", "SummitPost"],
"route_info": [
{"source": "...", "name": "...", "difficulty": "...", "description": "...", "hazards": [...]}
],
"trip_reports": [
{"source": "...", "date": "...", "author": "...", "url": "...", "summary": "...", "conditions": "...", "has_gpx": false}
],
"gaps": ["what couldn't be fetched and why"]
}
```"""
)
Agent 2: WTA + Mountaineers
Task(
subagent_type="general-purpose",
model="sonnet",
prompt="""You are a route researcher gathering mountaineering data for {peak_name}.
## Your Assignment
Research from these sources: WTA, Mountaineers.org
## WTA Research
1. Search: "{peak_name} site:wta.org"
2. Find the hike page and extract: trail name, difficulty, distance, elevation gain, hazards
3. Get trip reports from AJAX endpoint: {wta_url}/@@related_tripreport_listing
4. Fetch content for up to 5 recent trip reports using:
```bash
uv run python {repo_root}/skills/route-researcher/tools/cloudscrape.py "{trip_report_url}"
Mountaineers Research
- Search: "{peak_name} site:mountaineers.org route"
- Extract route beta, technical requirements, hazards
Fallback
If WebFetch fails for any page, use cloudscrape.py as shown above.
Output Format (return EXACTLY this JSON)
{
"sources": ["WTA", "Mountaineers"],
"route_info": [
{"source": "...", "name": "...", "difficulty": "...", "description": "...", "hazards": [...]}
],
"trip_reports": [
{"source": "...", "date": "...", "author": "...", "url": "...", "summary": "...", "conditions": "...", "has_gpx": false}
],
"gaps": ["what couldn't be fetched and why"]
}
```"""
)
Agent 3: AllTrails
Task(
subagent_type="general-purpose",
model="sonnet",
prompt="""You are a route researcher gathering mountaineering data for {peak_name}.
## Your Assignment
Research from AllTrails
## AllTrails Research
1. Search: "{peak_name} site:alltrails.com"
2. Use WebFetch to extract: trail name, difficulty, distance, elevation gain, route type, best season, hazards
3. If WebFetch fails, use:
```bash
uv run python {repo_root}/skills/route-researcher/tools/cloudscrape.py "{url}"
Output Format (return EXACTLY this JSON)
{
"sources": ["AllTrails"],
"route_info": [
{"source": "...", "name": "...", "difficulty": "...", "distance_miles": N, "elevation_gain_ft": N, "description": "...", "hazards": [...]}
],
"trip_reports": [],
"gaps": ["what couldn't be fetched and why"]
}
```"""
)
Execute all 3 agents in parallel by including all Task calls in a single response.
Step 3C: Aggregate Results
After Python script and all agents return, aggregate into unified data structure:
{
"conditions": { /* from fetch_conditions.py */ },
"route_data": {
"sources": [ /* merged from all 3 agents */ ],
"trip_reports": [ /* merged from all agents */ ]
},
"gaps": [ /* merged gaps from all sources */ ]
}
Partial Failure Handling:
- If any agent fails entirely, proceed with data from successful agents
- Note failed sources in the gaps array
- Minimum viable: conditions data + at least one route source
Step 3D: Access and Permits (Inline)
Run WebSearch for access information:
WebSearch queries:
1. "{peak_name} trailhead access"
2. "{peak_name} permit requirements"
3. "{peak_name} forest service road conditions"
Extract trailhead names, required permits, access notes. Add to route_data.
Phase 4: Route Analysis
Goal: Analyze gathered data to determine route characteristics and synthesize information.
Step 4A: Determine Route Type
Based on route descriptions, elevation, and gear mentions, classify as:
- Glacier: Crevasses mentioned, glacier travel, typically >8000ft
- Rock: Technical climbing, YDS ratings (5.x), protection mentioned
- Scramble: Class 2-4, exposed but non-technical
- Hike: Class 1-2, trail-based, minimal exposure
Step 4B: Synthesize Route Information from Multiple Sources
Goal: Combine trip reports and route descriptions from Step 3B researcher agents, plus conditions data from Step 3A, into comprehensive route beta.
Source Priority:
- Trip reports (Step 3B agents) - first-hand experiences
- Route descriptions (Step 3B agents) - published beta baseline
- PeakBagger/ascent data (Step 3A Python script) - basic info, patterns
Synthesis Pattern for Route, Crux, and Hazards:
- Start with baseline from route descriptions (standard route name, published difficulty)
- Enrich with trip report details (landmarks, specific conditions, actual experiences)
- Note conflicts when trip reports disagree with published info
- Highlight consensus ("Multiple reports mention...")
- Include specifics (elevations, locations, quotes)
Example (Route Description):
"The standard route follows the East Ridge (Class 3). Multiple trip reports mention a well-cairned use trail branching right at 4,800 ft—this is the correct turn. The use trail climbs through talus (described as 'tedious' and 'ankle-rolling'). In early season, this section may be snow-covered, requiring microspikes."
Apply this pattern to:
- Route: Use baseline structure, add landmarks/navigation from trip reports, include actual times
- Crux: Describe location/difficulty, add trip report assessments, note conditions-dependent variations
- Hazards: Extract ALL hazards from trip reports (rockfall, exposure, route-finding, seasonal), organize by type, include specific locations and mitigation strategies. Be comprehensive—safety-critical.
Extract Key Information:
From all synthesized data, identify:
- Difficulty Rating: YDS class, scramble grade, or general difficulty (validated by trip reports)
- Crux: Hardest/most technical section of route (synthesized above)
- Hazards: All identified hazards (synthesized above)
- Notable Gear: Any unusual or important gear mentioned in trip reports or beta (to be included in relevant sections, not as standalone section)
- Trailhead: Name and approximate location
- Distance/Gain: Round-trip distance and elevation gain (compare published vs actual trip report data)
- Time Estimates: Calculate three-tier pacing based on distance and gain:
- Fast pace: Calculate based on 2+ mph and 1000+ ft/hr gain rate
- Moderate pace: Calculate based on 1.5-2 mph and 700-900 ft/hr gain rate
- Leisurely pace: Calculate based on 1-1.5 mph and 500-700 ft/hr gain rate
- Use the slower of distance-based or gain-based calculations for each tier
- Example: For 4 miles round-trip, 2700 ft gain:
- Fast: max(4mi/2mph, 2700ft/1000ft/hr) = max(2hr, 2.7hr) = ~3 hours
- Moderate: max(4mi/1.5mph, 2700ft/800ft/hr) = max(2.7hr, 3.4hr) = ~3-4 hou