How to Integrate GeoAgent and Geocoding in GeoLibre: AI-Assisted Mapping Features

Integrate AI-assisted GeoAgent and geocoding features in GeoLibre by registering the maplibre-geoagent and maplibre-reverse-geocode plugins, configuring provider credentials via environment variables, and using the core geocodeForward and geocodeReverse APIs.

GeoLibre provides a modular plugin architecture that enables AI-assisted capabilities through GeoLibrePlugin implementations. The GeoAgent plugin combines Google Earth Engine with LLM-powered tools, while the geocoding system offers both forward and reverse address lookup. Both features build on the core geocoding service in @geolibre/core and mount as MapLibre controls via @geolibre/plugins.

GeoAgent Plugin Architecture

The GeoAgent plugin (packages/plugins/src/plugins/maplibre-geoagent.ts) wraps the maplibre-gl-geoagent control and manages three critical functions: dynamic control loading, Earth Engine authentication, and overlay synchronization.

Control Loading and Initialization

The plugin lazily imports the GeoAgent control through loadGeoAgentControl() and instantiates it with options defined in GEOAGENT_OPTIONS. These options include OAuth client ID, Earth Engine project ID, and default visualization parameters.

Earth Engine Authentication

Authentication flows through packages/plugins/src/plugins/earth-engine-auth.ts. The plugin calls authenticateEarthEngine() to obtain an access token, then applies it via applyEarthEngineAccessToken() and updates the control through updateEarthEngineOptions().

Overlay Synchronization

After any GeoAgent tool executes, the plugin invokes syncGeoAgentOverlaysToStore() from geoagent-layer-sync.ts. This ensures Earth Engine layers appear in GeoLibre's layer panel and remain synchronized with the core store.

Geocoding Core Implementation

The geocoding system in packages/core/src/geocoding.ts provides provider-agnostic address resolution with built-in throttling and request management.

Provider Registry

The GEOCODING_PROVIDERS registry supports five backends:

  • Nominatim (OpenStreetMap) – default, requires User-Agent header
  • Pelias – configurable endpoint
  • ArcGIS – commercial service
  • Mapbox – requires API key
  • Google – requires API key

Each provider implements four methods: buildForwardUrl, parseForward, buildReverseUrl, and parseReverse.

Request Throttling and Rate Limits

The core enforces Nominatim's public policy through:

  • shouldThrottle() – checks geocoderMinIntervalMs (1000ms default)
  • rowCap – limits result sets
  • Request deduplication via internal state

Fetch Override for Desktop Builds

The setGeocodingFetch() function allows the Tauri desktop shell to inject a native HTTP implementation that bypasses CORS and sets required headers like User-Agent. This is called from apps/geolibre-desktop/src/lib/geocoding-fetch.ts at application startup.

Reverse Geocoding Plugin

The reverse geocode plugin (packages/plugins/src/plugins/maplibre-reverse-geocode.ts) provides click-to-address functionality:

  • Registers a map click handler that calls geocodeReverse() from the core
  • Lazily imports Popup from maplibre-gl to display results
  • Includes a copy-to-clipboard button in the popup DOM
  • Uses restoreReverseGeocode() to rebind handlers after map re-initialization

Configuration and Setup

Plugin Registration

Plugins load automatically via usePlugins.ts in the desktop application. Both GeoAgent and reverse geocode plugins export a GeoLibrePlugin interface:

// Normally handled automatically by usePlugins.ts
import { maplibreGeoAgentPlugin } from '@geolibre/plugins';
import { maplibreReverseGeocodePlugin } from '@geolibre/plugins';

app.addPlugin(maplibreGeoAgentPlugin.id);
app.addPlugin(maplibreReverseGeocodePlugin.id);

Environment Variable Configuration

Create a .env file or set variables through the desktop UI:

VITE_GEOCODER_PROVIDER=nominatim        # nominatim | pelias | arcgis | mapbox | google

VITE_GEOCODER_EMAIL=you@example.com     # Required for public Nominatim

VITE_GEOCODER_API_KEY=YOUR_KEY          # Required for Mapbox, Google, ArcGIS

VITE_GEOCODER_ENDPOINT=https://custom/api/search
VITE_GEOCODER_REVERSE_ENDPOINT=https://custom/api/reverse

The core reads these through getGeocoderConfig() at runtime.

Code Examples

Activating GeoAgent Programmatically

import { app } from '@geolibre/app';

// Enable the plugin from custom UI (e.g., toolbar button)
await app.activatePlugin('maplibre-gl-geoagent');

// The control mounts automatically and handles Earth Engine auth

Forward Geocoding in Custom Tools

import { geocodeForward, getGeocoderConfig } from '@geolibre/core';

async function locateFacility(address: string) {
  const config = getGeocoderConfig();
  const matches = await geocodeForward(address, {
    config,
    limit: 5,
    bbox: [-125, 25, -66, 49] // Optional US bounding box bias
  });
  
  return matches.map(m => ({
    lat: m.lat,
    lon: m.lon,
    name: m.displayName,
    confidence: m.score
  }));
}

Manual Reverse Geocoding

import { geocodeReverse } from '@geolibre/core';

async function getAddressFromCoordinates(lng: number, lat: number) {
  const result = await geocodeReverse(lng, lat, {
    zoom: 18  // Address detail level (1-18)
  });
  
  if (!result) {
    throw new Error('No address found at this location');
  }
  
  return {
    fullAddress: result.displayName,
    country: result.address?.country,
    city: result.address?.city || result.address?.town
  };
}

Desktop Fetch Override

import { setGeocodingFetch } from '@geolibre/core';
import { fetch as tauriFetch } from '@tauri-apps/api/http';

// Must be called before any geocoding operations
setGeocodingFetch(async (url, options) => {
  const response = await tauriFetch(url, {
    method: options?.method || 'GET',
    headers: {
      'User-Agent': 'GeoLibre/1.0 (https://geolibre.org)',
      ...options?.headers
    }
  });
  
  return new Response(JSON.stringify(response.data), {
    status: response.status,
    headers: response.headers
  });
});

Key Implementation Files

Path Purpose
packages/plugins/src/plugins/maplibre-geoagent.ts GeoAgent plugin: control loading, Earth Engine auth, overlay sync
packages/plugins/src/plugins/geoagent-layer-sync.ts Store synchronization for GeoAgent overlays
packages/plugins/src/plugins/earth-engine-auth.ts OAuth and token management for Earth Engine
packages/core/src/geocoding.ts Core geocoding: providers, throttling, forward/reverse APIs
packages/plugins/src/plugins/maplibre-reverse-geocode.ts Click handler and popup UI for reverse geocoding
apps/geolibre-desktop/src/lib/geocoding-fetch.ts Tauri HTTP wrapper for desktop builds

Summary

  • GeoAgent integrates Earth Engine + LLM tools through a plugin that handles authentication, control mounting, and layer synchronization.
  • Geocoding supports five providers with configurable endpoints, rate limiting, and a fetch override mechanism for desktop environments.
  • Both features follow GeoLibre's plugin pattern: core logic in @geolibre/core, UI controls in @geolibre/plugins, and platform-specific adaptations in the desktop shell.
  • Configuration uses VITE_GEOCODER_* environment variables read via getGeocoderConfig().
  • Desktop builds must call setGeocodingFetch() to inject Tauri's HTTP client and satisfy provider header requirements.

Frequently Asked Questions

How do I enable GeoAgent in a custom GeoLibre build?

Import maplibreGeoAgentPlugin from @geolibre/plugins and add it to your plugins array in usePlugins.ts or call app.addPlugin(maplibreGeoAgentPlugin.id) programmatically. Activation occurs automatically from the Plugins menu or via app.activatePlugin().

Why is Nominatim geocoding failing with 403 errors?

Public Nominatim requires a valid User-Agent header and prefers an identifying email. In desktop builds, call setGeocodingFetch() with a custom fetch that includes these headers. Web builds must ensure the hosting domain complies with Nominatim's Usage Policy.

Can I use a private geocoding endpoint with GeoLibre?

Yes. Set VITE_GEOCODER_ENDPOINT and VITE_GEOCODER_REVERSE_ENDPOINT to your custom URLs, and select a compatible provider configuration. The buildForwardUrl and buildReverseUrl methods in your provider will use these endpoints instead of defaults.

How does GeoAgent synchronize Earth Engine layers with the layer panel?

After each tool execution, syncGeoAgentOverlaysToStore() in geoagent-layer-sync.ts reads the GeoAgent control's overlay state and dispatches updates to the core store. This mirrors the pattern used by other data sources to maintain reactive UI consistency.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →