IBM AI Builders Challenge — Wildcard Theme: Future of Work An AI co-worker for land managers and emergency responders — not a replacement.
WildfireGIS replaces hours of manual GIS lookups, government-portal searching, and email drafting with a single automated pipeline: draw a burn boundary → get the intersecting municipality, the Mayor's contact, the Fire Chief's contact, and a professionally drafted civic notification email — in under 90 seconds.
- Problem Statement
- Architecture Overview
- Technical Execution
- Innovation
- Feasibility
- Challenge Fit — Future of Work
- Setup Instructions
- Demo Script (60–90 seconds)
- Known Limitations / Future Work
Every prescribed burn in Ontario — and across Canada — requires the burn boss or land manager to:
-
Manually identify jurisdiction. A burn polygon may cross municipal, county, First Nations, and provincial boundaries simultaneously. Determining which municipality's fire department and elected officials must be notified requires either expensive GIS software, time-consuming ArcGIS portal lookups, or a phone call to a regional office.
-
Hunt for civic contacts. Municipal websites vary wildly in quality. The Mayor's email may be buried under three navigation levels; the Fire Chief's contact may only exist in a 2-year-old PDF staff directory. There is no single authoritative source.
-
Draft a professional notification from scratch. Each notification must be factual, calm, and calibrated for a non-technical audience (elected officials, not foresters). A poorly worded email can cause public alarm, media escalation, or strained municipal relationships. Drafting and reviewing takes 30–60 minutes per municipality per burn.
-
Repeat for every affected municipality. A 500-hectare burn near a township boundary may require notifying 3–5 separate contacts across 2–3 municipalities.
This is a solved problem for AI. The jurisdictional data is public (Ontario LIO). The contact data is partially structured (OpenNorth Represent API, CKAN open data). The notification content follows a well-defined professional template. What was previously a 2–4 hour manual workflow per burn event can become a 90-second automated pipeline.
- Ontario alone runs hundreds of prescribed burns annually through the Ministry of Natural Resources and Forestry (MNRF) and licensed contractors.
- Canada-wide, the Canadian Forest Service and provincial agencies conduct thousands of prescribed burn operations per year.
- Delays in civic notification have historically caused public 911 call spikes, unnecessary emergency response mobilisation, and reputational damage to forestry agencies.
- Faster, consistent notification builds trust between land management agencies and local governments — a critical relationship during wildfire season.
┌─────────────────────────────────────────────────────────────────────┐
│ WildfireGIS │
│ │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ Blazor Server UI (BurnDashboard.razor) │ │
│ │ ┌──────────────┐ ┌──────────────────┐ ┌───────────────┐ │ │
│ │ │ Coordinate │ │ Contact Cards │ │ AI Email │ │ │
│ │ │ Input Panel │ │ (Mayor, Fire │ │ Draft Panel │ │ │
│ │ │ │ │ Chief, warn │ │ (editable + │ │ │
│ │ │ Centroid │ │ badges) │ │ mailto/ │ │ │
│ │ │ Area (ha) │ │ │ │ clipboard) │ │ │
│ │ └──────┬───────┘ └────────┬─────────┘ └──────┬────────┘ │ │
│ └─────────┼───────────────────┼────────────────────┼───────────┘ │
│ │ DI (Blazor Server │ same-process calls)│ │
│ ┌─────────▼───────┐ ┌────────▼──────────┐ ┌─────▼──────────┐ │
│ │ SpatialService │ │ CivicContactSvc │ │ EmailDraftSvc │ │
│ │ (NTS + ProjNet) │ │ │ │ │ │
│ │ • Polygon build │ │ Source 1: │ │ • Llama chat │ │
│ │ • Winding fix │ │ Represent API │ │ template │ │
│ │ • UTM ha calc │ │ (Mayor/Reeve) │ │ • Prompt │ │
│ │ • GeoJSON serial.│ │ │ │ injection │ │
│ └─────────┬───────┘ │ Source 2: │ │ hardening │ │
│ │ │ CKAN open data │ │ │ │
│ ┌─────────▼───────┐ │ (Fire Chief) │ └──────┬─────────┘ │
│ │ LioMunicipalSvc │ │ │ │ │
│ │ (ArcGIS REST) │ │ Graceful degrad. │ ┌──────▼─────────┐ │
│ │ POST /query │ │ + ContactCard │ │ WatsonxClient │ │
│ │ Polly retry │ │ normalisation │ │ IAM token + │ │
│ └─────────┬───────┘ └────────┬──────────┘ │ cache │ │
│ │ │ │ meta-llama/ │ │
│ ┌─────────▼───────────────────▼──────────────▼────────────────┐ │
│ │ External APIs │ │
│ │ • Ontario LIO ArcGIS REST (ws.lioservices.lrc.gov.on.ca) │ │
│ │ • OpenNorth Represent API (represent.opennorth.ca) │ │
│ │ • Ontario CKAN open data (data.ontario.ca) │ │
│ │ • IBM Cloud IAM (iam.cloud.ibm.com) │ │
│ │ • IBM watsonx.ai (us-south.ml.cloud.ibm.com) │ │
│ └──────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
Data flow:
- User inputs polygon coordinates in the left panel
SpatialServicebuilds NTS polygon, corrects winding order, computes centroid + hectares in UTM, serialises to GeoJSONLioMunicipalServicePOSTs the Esri polygon to Ontario's LIO ArcGIS server → returns municipal name(s)CivicContactServicequeries Represent API (Mayor) + Ontario CKAN (Fire Chief) → normalises toContactCardlistEmailDraftServicebuilds a Llama 3.3 chat-template prompt, callsWatsonxClient.GenerateWithMetadataAsync→ parses Subject + Body- Blazor UI renders all results in real-time; user edits draft → clicks "Open in Mail Client" (mailto:) or "Copy to Clipboard"
Winding-order correction is implemented explicitly rather than assumed. Input coordinates arrive in arbitrary order from a GIS tool or manual entry. The signed shoelace formula detects CW vs CCW orientation, and Array.Reverse() corrects CW → CCW in-place. This matters because GeoJSON RFC 7946 mandates CCW for exterior rings and several ArcGIS REST endpoints silently misinterpret CW rings.
Accurate hectare calculation via UTM reprojection. WGS84 Polygon.Area returns square-degrees — a meaningless unit (a 1°×1° cell spans ~12,000 km² at the equator but only ~3,000 km² at 60°N). The UTM zone is auto-selected from the centroid longitude (zone = floor((lon + 180) / 6) + 1), a ProjNet WKT CRS string is built on-the-fly (no EPSG database file required), and the polygon is reprojected before area calculation. Accuracy: <0.04% for polygons under 50 km wide.
- Uses POST (not GET) because burn polygons easily exceed the ~2,000-char safe GET URL limit; the LIO server returns HTTP 414 for large GET queries
- Esri JSON geometry format (
"rings"key, not GeoJSON"coordinates") is built by re-wrapping the GeoJSON coordinates array — no re-encoding required - Polly exponential back-off (2s → 4s → 8s + jitter) handles the LIO server's known instability during peak hours
- Soft-error detection: ArcGIS returns HTTP 200 even on failure; the response
"error"object is always checked before accessing"features"
- IBM-specific grant type:
urn:ibm:params:oauth:grant-type:apikey(not standardclient_credentials) - Token TTL is 3,600 s; the cache expires 300 s early to prevent race conditions between validity-check and HTTP dispatch
SemaphoreSlim(1,1)+ double-checked locking prevents stampede under concurrent Blazor circuit requests
Every possible failure mode returns a ContactCard with NeedsManualLookup=true and a LookupNote containing the exact URL to search manually. The pipeline never returns empty — the email draft is always generated with whatever contact information was found, and unverified recipients trigger a [VERIFY CONTACTS BEFORE SENDING] prefix on the subject line. This is a deliberate design choice: a partial notification with a clear warning is more useful than a failed one.
- Uses the Llama 3.3 Instruct chat template (Meta special tokens:
<|begin_of_text|>,<|start_header_id|>,<|eot_id|>) directly in theinputfield — activates the model's instruction-following mode - System prompt is fully static (zero interpolation). All user data flows through the user turn only.
Sanitise()strips\n,\r, and Llama special-token delimiters from all user-supplied strings before prompt assembly — prevents multi-line prompt injection via a crafted municipal name stop_sequences: ["<|eot_id|>", "###"]terminates generation cleanly at end-of-assistant-turn, preventing phantom next-user-turn hallucinations- Temperature 0.4 / top_k 50 / repetition_penalty 1.1 — tuned for professional prose, not creative output
- Standalone static class with no UI dependency — independently testable
- Line breaks encoded as
%0D%0A(CRLF), not bare%0A— required by Outlook on Windows - Conservative character encoding set (encodes all non-unreserved chars) for maximum mail-client compatibility
- URI length check against 1,900-char limit triggers automatic clipboard fallback — documented and tested
- Primary → To:, secondary → CC: pattern mirrors real notification practice (transparent to all parties)
The novel contribution is the automated end-to-end pipeline that no existing tool provides:
| Manual workflow today | WildfireGIS |
|---|---|
| Open ArcGIS Desktop or ArcGIS Online → upload boundary → run spatial query → write down municipal names | Paste coordinates → instant result |
| Search municipal website / provincial directory for Mayor contact | Represent API query → structured ContactCard |
| Search fire department registry / CKAN for Fire Chief | CKAN package_search + datastore_search + heuristic field extraction |
| Draft notification email in Word → review → copy-paste into Outlook | Llama 3.3 70B generates a professional, regulation-appropriate draft in seconds |
| Repeat for each of 3 municipalities | Single pipeline, parallel municipality lookup |
The chaining is the innovation: no individual component is novel in isolation. The novelty is that a land manager with no GIS expertise, no knowledge of ArcGIS REST APIs, no familiarity with CKAN, and no time to draft a careful email can get from "polygon coordinates" to "reviewed, ready-to-send civic notifications" in a single browser session.
This is classic AI augmentation of professional workflow — the tool handles the mechanical steps (spatial query, contact lookup, draft generation) while the land manager applies domain judgment (reviewing the draft, adding operational notes, deciding the send time).
| Feature | Status |
|---|---|
| Polygon input → centroid + hectares | ✅ Full NTS implementation with UTM reprojection |
| LIO municipal intersection query | ✅ ArcGIS REST POST with Polly retry |
| Mayor contact via Represent API | ✅ Live API integration with graceful degradation |
| CKAN Fire Chief lookup | ✅ 3-step package_search → datastore_search pattern |
| AI email draft via watsonx.ai | ✅ Llama 3.3 70B with chat-template prompt |
| Blazor Server UI with mailto/clipboard | ✅ RFC 6068 compliant with JS interop fallback |
| Gap | Description | Mitigation path |
|---|---|---|
| CKAN endpoint variability | Each of Ontario's 440+ municipalities publishes data on a different CKAN instance with different field names. The current heuristic field-matching covers ~70% of cases. | Build a curated municipality → CKAN endpoint mapping table; contribute upstream to Open511/OpenNorth |
| Represent API coverage | ~85% of Ontario municipalities are in the Represent database; rural townships and First Nations bands may be missing | Supplement with a manually maintained fallback CSV for known gaps |
| First Nations jurisdictions | Burns on Crown land near reserve boundaries may require notification to band councils not in Represent | Integrate FNMIS (First Nations Map) or manual contact list |
| Production secret management | .env file is appropriate for hackathon; production needs Azure Key Vault, AWS Secrets Manager, or IBM Secrets Manager |
DI-ready: swap SettingsLoader for a secrets provider without touching services |
| Multi-burn session state | Current Blazor Server circuit holds one burn at a time | Add a BurnSession list component and EF Core / SQLite persistence |
| Actual email delivery | mailto: URI opens the user's default mail client; does not send programmatically |
Add SMTP/SendGrid service for fully automated delivery (requires additional approval workflow) |
Wildcard Theme: Future of Work — Decision intelligence and the AI co-worker.
WildfireGIS is a concrete demonstration of how AI reshapes professional workflows in critical infrastructure, not knowledge work. The "Future of Work" conversation is often dominated by knowledge-worker examples (code generation, document summarisation). WildfireGIS targets a different population: land managers, prescribed burn bosses, and emergency responders — professionals whose work is spatially grounded, time-sensitive, and carries real public safety consequences.
The AI co-worker framing is literal here:
- The spatial analysis (centroid, hectares, jurisdiction lookup) is work the AI replaces entirely — it is mechanical, error-prone, and takes hours; a computer does it better in seconds
- The civic notification draft is work the AI assists with — it produces a professional starting point that the operator reviews, edits, and takes responsibility for before sending
- The operator retains full authority: every email is editable, every
[VERIFY CONTACTS]flag is visible, and the send action is always a human gesture
This models the correct relationship between AI tools and high-stakes professional work: AI handles the mechanical and informational, humans handle the judgmental and relational.
The pipeline also directly addresses the Future of Work theme's equity dimension: a small municipality or underfunded forestry contractor without a dedicated GIS analyst gets the same spatial intelligence and civic communication support as a large provincial agency with a full ArcGIS team. AI democratises access to expert-level analytical workflows.
- .NET 8 SDK
- An IBM Cloud account with:
- An IBM Cloud IAM API key
- A watsonx.ai project with Watson Machine Learning service associated
- Access to the
meta-llama/llama-3-3-70b-instructfoundation model in your region
git clone https://github.com/your-org/WildfireGIS.git
cd WildfireGIS/WildfireGIS
cp .env.example .env
# Open .env and fill in the four required values:
# API_KEY — IBM Cloud IAM API key
# PROJECT_ID — watsonx.ai project GUID
# CLOUD_URL — e.g. https://us-south.ml.cloud.ibm.com
# LLM_NAME — meta-llama/llama-3-3-70b-instruct| Variable | Location in IBM Cloud |
|---|---|
API_KEY |
cloud.ibm.com → Manage → Access (IAM) → API keys → Create |
PROJECT_ID |
dataplatform.cloud.ibm.com → Projects → [your project] → Manage → General → Project ID |
CLOUD_URL |
Match to region: us-south / eu-de / eu-gb / jp-tok |
LLM_NAME |
meta-llama/llama-3-3-70b-instruct (verify via GET {CLOUD_URL}/ml/v1/foundation_model_specs?version=2024-05-31) |
dotnet restore
dotnet runOpen http://localhost:5000 in a browser. The Blazor Server dashboard loads immediately; no build step required.
The .env file is for local development only. In CI/CD, set the four variables as process environment variables. SettingsLoader uses LoadOptions.NoClobber — real environment variables always shadow .env values.
Goal: show judges the full pipeline from coordinate input to a ready-to-send email, emphasising that the operator stays in control at every step.
0:00 — Context (15 s)
"A prescribed burn boss just received approval for a 280-hectare burn near Parry Sound, Ontario. Before ignition, they need to notify the Mayor and Fire Chief of every municipality the burn boundary touches. Normally this takes 2–4 hours. Let's do it in 90 seconds."
0:15 — Input (10 s)
Paste the four coordinates into the Coordinate Input panel (pre-populated as defaults). Set Fuel Types to "Mixed boreal forest, Jack pine". Click Analyse Burn Boundary.
0:25 — Spatial result (10 s)
While the spinner runs, explain: "The backend is running winding-order correction, reprojecting to UTM for accurate hectare math, and querying Ontario's LIO ArcGIS server for municipal boundaries." Results appear: Centroid, 279.3 ha, Municipality: PARRY SOUND
0:35 — Contact cards (15 s)
The centre panel populates with contact cards. Point out:
- The Mayor card with green source badge ("represent.opennorth.ca") and visible email/phone
- The Fire Chief card with the amber ⚠ warning ("CKAN returned no results — verify manually") "The system found the Mayor automatically. It couldn't find the Fire Chief in the open data — it flags that card so the operator knows to verify before sending, rather than silently failing."
0:50 — AI email draft (20 s)
The right panel shows the generated email. Read the subject line and first paragraph. Point out:
- The tone: professional, calm, no alarming language
- The
[VERIFY CONTACTS BEFORE SENDING]prefix on the subject (because Fire Chief is unverified)- The editable text areas: "The operator can edit any part of this before sending"
1:10 — Send action (10 s)
Click Open in Mail Client on the Mayor's contact card. The OS mail client opens with the address, subject, and body pre-filled. Click Copy to Clipboard for the Fire Chief card to show the fallback path.
1:20 — Closing (10 s)
"2–4 hours of manual GIS lookups, government portal searching, and email drafting — automated to 90 seconds, with the operator reviewing and approving every step. That's the AI co-worker for the future of land management."
-
CKAN coverage: Ontario's open data portal doesn't have fire department contacts for every municipality. The 3-step CKAN lookup works for ~70% of cases; the remaining 30% return manual-lookup cards.
-
Represent API completeness: Rural townships, unorganised territories, and First Nations lands may not appear in the Represent database. Coverage is best for cities and towns.
-
Single-burn session: The current UI holds one burn analysis at a time. Navigating away loses state.
-
No actual email sending: The tool opens the user's default mail client via
mailto:. It does not send email programmatically. This is intentional for the hackathon (avoids needing SMTP credentials) but is a production gap. -
Llama 3.3 70B availability: Model availability varies by watsonx.ai region. If the model is unavailable in your region, update
LLM_NAMEin.envto a supported alternative (e.g.ibm/granite-13b-instruct-v2).
- Interactive map (Leaflet.js or MapLibre GL) replacing the coordinate textarea — draw the burn boundary directly on a basemap
- Multi-burn session management with SQLite/EF Core persistence
- First Nations consultation layer — overlay First Nations reserve boundaries and link to band council contacts from the First Nations Major Projects Coalition directory
- Ontario MNRF fire weather data integration — pull FFMC/BUI/FWI indices for the centroid location to include fire behaviour context in the notification
- Programmatic email delivery via SendGrid/SMTP with operator approval workflow
- PDF notification package — generate a complete notification package (email + burn plan summary + GeoJSON map export) for the burn file
- Multi-province support — parameterise the LIO endpoint and Represent boundary sets to support BC, AB, MB jurisdictions
- Streaming LLM responses via
/ml/v1/text/generation_stream— show the email draft being written in real-time for demo impact
WildfireGIS/
├── .env.example ← credential template
├── .gitignore ← .env excluded
├── WildfireGIS.csproj
├── Program.cs ← ASP.NET Core / Blazor Server host
├── Api/
│ └── BurnApiEndpoints.cs ← Minimal API REST endpoints
├── Components/
│ ├── App.razor ← HTML document shell
│ ├── Routes.razor ← Blazor router
│ ├── Layout/
│ │ └── MainLayout.razor ← App chrome (header, footer)
│ └── Pages/
│ └── BurnDashboard.razor ← Main three-panel UI
├── Config/
│ ├── WatsonxSettings.cs ← Strongly-typed credential POCO
│ └── SettingsLoader.cs ← DotNetEnv loader + validation
├── Models/
│ ├── WatsonxModels.cs ← IAM + generation DTOs
│ ├── SpatialModels.cs ← LonLat, BurnPolygonInfo, ArcGIS DTOs
│ └── CivicModels.cs ← ContactCard, EmailDraft, BurnParameters, CKAN/Represent DTOs
├── Services/
│ ├── IamTokenProvider.cs ← IBM IAM token exchange + caching
│ ├── WatsonxClient.cs ← watsonx.ai HTTP wrapper
│ ├── SpatialService.cs ← NTS polygon + UTM area + GeoJSON
│ ├── LioMunicipalService.cs ← ArcGIS REST + Polly retry
│ ├── CivicContactService.cs ← Represent API + CKAN lookup
│ └── EmailDraftService.cs ← Llama prompt builder + output parser
├── Utilities/
│ └── MailtoUriBuilder.cs ← RFC 6068 mailto: URI + clipboard fallback
└── wwwroot/
├── app.css ← Flat CSS design system (no framework)
└── blazor-interop.js ← window.open mailto + Clipboard API
| Package | Version | Purpose |
|---|---|---|
DotNetEnv |
3.1.0 | .env file loading with NoClobber precedence |
NetTopologySuite |
2.5.0 | Computational geometry (polygon, algorithms) |
NetTopologySuite.IO.GeoJSON4STJ |
4.0.0 | NTS → GeoJSON via System.Text.Json |
ProjNet |
2.0.0 | WGS84 → UTM reprojection (pure .NET, no GDAL) |
Polly |
8.4.1 | Retry/timeout resilience for external APIs |
Polly.Extensions.Http |
3.0.0 | HTTP transient-error helpers |
Microsoft.AspNetCore.Components.Web |
8.0.0 | Blazor Server presentation layer |
Microsoft.Extensions.Logging.Console |
8.0.0 | Structured console logging |
MIT — see LICENSE.
Built for the IBM AI Builders Challenge · Wildcard Theme: Future of Work Powered by IBM watsonx.ai · Llama 3.3 70B Instruct · NetTopologySuite · Ontario LIO · OpenNorth Represent API