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

> Integrate GeoAgent and geocoding AI features in GeoLibre. Register plugins, configure credentials, and use core APIs for AI-assisted mapping. Learn how to enhance your GeoLibre project today.

- Repository: [Open Geospatial Solutions/GeoLibre](https://github.com/opengeos/GeoLibre)
- Tags: how-to-guide
- Published: 2026-08-01

---

**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`](https://github.com/opengeos/GeoLibre/blob/main/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`](https://github.com/opengeos/GeoLibre/blob/main/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`](https://github.com/opengeos/GeoLibre/blob/main/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`](https://github.com/opengeos/GeoLibre/blob/main/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`](https://github.com/opengeos/GeoLibre/blob/main/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`](https://github.com/opengeos/GeoLibre/blob/main/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`](https://github.com/opengeos/GeoLibre/blob/main/usePlugins.ts) in the desktop application. Both GeoAgent and reverse geocode plugins export a `GeoLibrePlugin` interface:

```ts
// 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:

```bash
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

```ts
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

```ts
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

```ts
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

```ts
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`](https://github.com/opengeos/GeoLibre/blob/main/packages/plugins/src/plugins/maplibre-geoagent.ts) | GeoAgent plugin: control loading, Earth Engine auth, overlay sync |
| [`packages/plugins/src/plugins/geoagent-layer-sync.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/plugins/src/plugins/geoagent-layer-sync.ts) | Store synchronization for GeoAgent overlays |
| [`packages/plugins/src/plugins/earth-engine-auth.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/plugins/src/plugins/earth-engine-auth.ts) | OAuth and token management for Earth Engine |
| [`packages/core/src/geocoding.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/core/src/geocoding.ts) | Core geocoding: providers, throttling, forward/reverse APIs |
| [`packages/plugins/src/plugins/maplibre-reverse-geocode.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/plugins/src/plugins/maplibre-reverse-geocode.ts) | Click handler and popup UI for reverse geocoding |
| [`apps/geolibre-desktop/src/lib/geocoding-fetch.ts`](https://github.com/opengeos/GeoLibre/blob/main/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`](https://github.com/opengeos/GeoLibre/blob/main/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](https://operations.osmfoundation.org/policies/nominatim/).

### 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`](https://github.com/opengeos/GeoLibre/blob/main/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.