GeoAgent

agent
Security Audit
Pass
Health Pass
  • License — License: MIT
  • Description — Repository has a description
  • Active repo — Last push 0 days ago
  • Community trust — 79 GitHub stars
Code Pass
  • Code scan — Scanned 12 files during light audit, no dangerous patterns found
Permissions Pass
  • Permissions — No dangerous permissions requested
Purpose
This tool provides a shared AI agent framework for geospatial Python packages and QGIS plugins. It acts as an abstraction layer allowing large language models to consistently interact with mapping libraries, datasets, and geospatial workflows.

Security Assessment
Overall Risk: Low. The automated code scan reviewed 12 files and found no dangerous patterns or hardcoded secrets. The tool does not request inherently dangerous permissions. However, because it acts as a bridge between AI models and geospatial workflows, it inherently relies on external network requests to communicate with various LLM providers (such as OpenAI, Anthropic, and Google). Additionally, by design, it processes user geospatial data and prompts, so developers must ensure they configure their API keys and environment variables securely to prevent unintended data exposure.

Quality Assessment
The project demonstrates strong health and maintenance signals. It is highly active, with the most recent code push occurring just today. It enjoys a solid foundation of community trust, evidenced by 79 GitHub stars. Furthermore, it operates under the permissive and standard MIT license, making it highly accessible for integration and modification. The repository is well-documented and clearly outlines its core concepts and intended use cases.

Verdict
Safe to use.
SUMMARY

A AI Agent for Geospatial Data Analysis and Visualization

README.md

GeoAgent

QGIS Plugin
image
notebook-link
image
image
image
Conda Recipe
image
Conda Downloads
image
image
image

GeoAgent is a shared AI agent layer for geospatial Python packages, live
map widgets, and QGIS plugins. It gives projects such as leafmap,
anymap, geoai, geemap, STAC workflows, NASA Earthdata workflows,
and QGIS plugins one consistent way to expose geospatial tools to large
language models.

GeoAgent is built on Strands Agents. It
wraps Strands with geospatial context, tool metadata, optional package
adapters, provider configuration, and confirmation hooks for operations that
should not run silently.

Why GeoAgent?

Many geospatial libraries need the same agent features:

  • bind an agent to a live map, QGIS session, dataset, or workflow object;
  • expose package functions as structured tools with docstrings and metadata;
  • support OpenAI, ChatGPT/Codex OAuth, Anthropic, Google Gemini, Bedrock, LiteLLM, and local
    Ollama models;
  • keep optional geospatial stacks optional;
  • ask for confirmation before deleting layers, saving files, or running
    expensive processing jobs;
  • support multimodal plugin workflows such as pasted images and screenshots
    when the selected model provider supports vision;
  • provide a stable integration point for downstream packages and plugins.

GeoAgent centralizes that layer so each package does not need to maintain its
own agent framework.

Core Concepts

Concept Purpose
GeoAgent High-level facade around a Strands Agent.
GeoAgentConfig Provider, model, temperature, token, and client settings.
GeoAgentContext Runtime objects bound to the agent, such as a map or QGIS iface.
@geo_tool Decorator that turns a Python function into a Strands tool with GeoAgent metadata.
GeoToolRegistry Registry for tool metadata, safety flags, categories, and fast-mode filtering.
for_leafmap Factory that binds tools to a leafmap.Map-compatible object.
for_anymap Factory that binds tools to an anymap.Map-compatible object.
for_qgis Factory that binds tools to qgis.utils.iface and an optional QgsProject.
for_nasa_opera Factory that binds NASA OPERA search/display tools plus QGIS tools.
create_agent Factory for custom tools or package-specific integrations.

Installation

Install the core package:

pip install GeoAgent

Core installs only the agent framework dependencies, mainly strands-agents
and pydantic. Geospatial packages and provider clients are optional extras:

Extra Purpose
GeoAgent[openai] OpenAI model support through Strands.
GeoAgent[anthropic] Anthropic Claude model support through Strands.
GeoAgent[gemini] Google Gemini model support through Strands.
GeoAgent[ollama] Local Ollama model support.
GeoAgent[litellm] LiteLLM model support for many hosted and proxy providers.
GeoAgent[leafmap] leafmap live map integration.
GeoAgent[anymap] anymap live map integration.
GeoAgent[stac] STAC client dependencies.
GeoAgent[earthdata] NASA Earthdata dependencies.
GeoAgent[nasa-opera] NASA OPERA search dependencies.
GeoAgent[geoai] geoai integration dependencies.
GeoAgent[earthengine] Google Earth Engine dependencies.
GeoAgent[ui] Solara UI dependencies.
GeoAgent[providers] OpenAI, Anthropic, Gemini, Ollama, and LiteLLM provider clients.
GeoAgent[all] Most optional integrations. QGIS itself remains system-installed.

Examples:

pip install "GeoAgent[leafmap,openai]"
pip install "GeoAgent[anymap,anthropic]"
pip install "GeoAgent[stac,earthdata,openai]"

For QGIS, install GeoAgent in the Python environment used by QGIS. The
GeoAgent[qgis] extra is a marker extra; QGIS is provided by the desktop
application or system package manager.

Provider Configuration

GeoAgent selects a provider from environment variables when no provider is
specified:

Provider Environment
OpenAI OPENAI_API_KEY, optional OPENAI_MODEL
ChatGPT/Codex OAuth OPENAI_CODEX_ACCESS_TOKEN, optional OPENAI_CODEX_MODEL
Anthropic ANTHROPIC_API_KEY, optional ANTHROPIC_MODEL
Google Gemini GEMINI_API_KEY or GOOGLE_API_KEY, optional GEMINI_MODEL
LiteLLM LITELLM_API_KEY, optional LITELLM_MODEL and LITELLM_BASE_URL
Ollama OLLAMA_HOST or USE_OLLAMA=1, optional OLLAMA_MODEL
Bedrock AWS credential chain and model access, optional BEDROCK_MODEL

ChatGPT/Codex OAuth uses the Codex browser login flow and the Codex Responses
backend.

For notebooks and Python scripts, log in once with the CLI:

geoagent codex login

or from Python/Jupyter:

from geoagent import login_openai_codex

login_openai_codex()

GeoAgent stores the refresh token in your user config directory and exports
OPENAI_CODEX_ACCESS_TOKEN for the current Python process. Later sessions can
reuse the stored login automatically, or explicitly call:

from geoagent import ensure_openai_codex_environment

ensure_openai_codex_environment()

You can also configure providers explicitly:

from geoagent import GeoAgentConfig, for_leafmap

agent = for_leafmap(
    m,
    config=GeoAgentConfig(
        provider="openai",
        model="gpt-5.5",
        temperature=0,
        max_tokens=4096,
    ),
)

Factories also accept provider= and model_id= shortcuts:

agent = for_leafmap(m, provider="gemini", model_id="gemini-3.1-pro-preview")

Quickstart

Use GeoAgent directly when you do not need a map or package-specific toolset:

from geoagent import GeoAgent, GeoAgentConfig

agent = GeoAgent(config=GeoAgentConfig(provider="openai", model="gpt-5.5"))
resp = agent.chat("Explain STAC in two sentences.")
print(resp.answer_text)

Stream model output as it is generated:

import asyncio
from geoagent import GeoAgent

agent = GeoAgent()

async def main():
    async for event in agent.stream_chat("Explain STAC in two sentences."):
        if "data" in event:
            print(event["data"], end="", flush=True)

asyncio.run(main())

Bind an agent to a live leafmap map:

import leafmap
from geoagent import for_leafmap

m = leafmap.Map()
agent = for_leafmap(m)

resp = agent.chat("Add a marker for Knoxville and zoom to it.")
print(resp.answer_text)
m

Bind an agent to an anymap map:

import anymap
from geoagent import for_anymap

m = anymap.Map()
agent = for_anymap(m)
agent.chat("Change the basemap and list the current layers.")

Use GeoAgent inside QGIS:

from qgis.utils import iface
from geoagent import for_qgis

agent = for_qgis(iface)
resp = agent.chat("Summarize the project layers and zoom to the active layer.")
print(resp.answer_text)

geoagent.tools.qgis is import-safe outside QGIS. It imports QGIS classes only
inside tool bodies, so tests and non-QGIS environments can import the module.

The OpenGeoAgent QGIS plugin adds a dockable chat UI on top of this factory. It
supports provider and model controls, streaming responses, pasted image
attachments, screenshot capture from the map canvas, QGIS window, or selected
screen regions, image preview and save actions, Markdown transcript copying,
and copying the PyQGIS script used for an executed result.

QGIS Plugin

OpenGeoAgent is the QGIS plugin interface for GeoAgent. It adds a dockable AI
assistant to QGIS so you can inspect projects, navigate the map canvas, load
data, run processing workflows, style layers, and execute confirmation-gated
PyQGIS scripts from natural language.

OpenGeoAgent QGIS plugin

Key plugin features:

  • provider and model controls for Bedrock, OpenAI, ChatGPT/Codex OAuth,
    Anthropic, Google Gemini, Ollama, and LiteLLM;
  • project-aware QGIS tools for layers, selections, map navigation, processing,
    project saving, and attribute table actions;
  • image-aware chat with clipboard paste and screenshot attachments for models
    that support vision inputs;
  • screenshot capture from the map canvas, selected map regions, the QGIS
    window, and selected screen regions;
  • image preview and save/export actions;
  • copy Markdown transcript and copy executed PyQGIS script actions;
  • confirmation-gated run_pyqgis_script fallback when a task needs QGIS API
    operations that are not covered by a dedicated tool;
  • lazy dependency checks so opening the chat dock stays responsive.

See the QGIS plugin documentation for setup and usage.

Built-In Tool Surfaces

leafmap and anymap

for_leafmap(m) and for_anymap(m) expose a shared map-control surface:

  • inspect state and layers: get_map_state, list_layers;
  • navigate: set_center, fly_to, set_zoom, zoom_in, zoom_out,
    zoom_to_bounds, zoom_to_layer;
  • manage layers: add_layer, remove_layer, clear_layers,
    set_layer_visibility, set_layer_opacity;
  • add data: add_vector_data, add_geojson_data, add_raster_data,
    add_cog_layer, add_stac_layer, add_xyz_tile_layer,
    add_pmtiles_layer, add_marker;
  • change basemaps and export maps: change_basemap, save_map.

Layer lookup accepts exact names or a unique case-insensitive substring for
operations such as remove_layer, zoom_to_layer, set_layer_visibility, and
set_layer_opacity.

QGIS

for_qgis(iface, project=None) exposes tools that run through a Qt GUI-thread
marshaller:

  • inspect project and layer state: list_project_layers, get_active_layer,
    get_project_state, get_layer_summary, inspect_layer_fields,
    get_selected_features;
  • navigate: zoom_in, zoom_out, zoom_to_layer, zoom_to_extent,
    zoom_to_selected, set_center, set_scale, refresh_canvas;
  • manage layers and data: add_vector_layer, add_raster_layer,
    add_xyz_tile_layer, remove_layer, set_layer_visibility,
    set_layer_opacity;
  • select and process: select_features_by_expression, clear_selection,
    run_processing_algorithm;
  • open QGIS UI and save: open_attribute_table, save_project;
  • run confirmation-gated PyQGIS fallback scripts with run_pyqgis_script
    when a task requires QGIS API operations that are not covered by a dedicated
    tool.

QGIS chat uses a sequential tool executor and GUI-thread marshalling so map
canvas and layer-tree calls are routed safely. The PyQGIS fallback receives
the current iface, project, canvas, and active_layer, making it useful
for actions such as raster band renderer changes, labeling tweaks, layer tree
updates, and other QGIS API operations.

NASA OPERA

for_nasa_opera(iface, project=None) exposes NASA OPERA product tools and the
standard QGIS tool surface:

  • inspect OPERA products: get_available_datasets, get_dataset_info;
  • search Earthdata granules: search_opera_data;
  • display results: display_footprints, display_raster, create_mosaic.

The OPERA integration is implemented as native GeoAgent tools and does not wrap
the NASA OPERA plugin's legacy nasa_opera.ai.tools registry.

When adding OPERA capabilities, implement the reusable tool logic in
geoagent/tools/nasa_opera.py. Keep the NASA OPERA QGIS plugin focused on UI,
settings, provider selection, progress display, and compatibility aliases. The
plugin consumes GeoAgent tool metadata automatically, so new GeoAgent OPERA
tools are available to the plugin AI Assistant without duplicating tool logic.

Use it from the QGIS Python console or from plugin code. For direct tool
testing, use submit_nasa_opera_search_task(...); this avoids LLM/provider
initialization and reports progress in QGIS's message bar and Log Messages
panel:

from geoagent.tools.nasa_opera import submit_nasa_opera_search_task

task = submit_nasa_opera_search_task(
    iface,
    dataset="OPERA_L3_DSWX-HLS_V1",
    bbox="-95.5,29.5,-95.0,30.0",
    start_date="2024-01-01",
    end_date="2024-01-31",
    max_results=5,
    display_footprints=True,
)

For a longer QGIS-console script, see examples/nasa_opera_qgis.py.

Natural-language OPERA chat is intentionally disabled inside QGIS for now.
Use direct tools or submit_nasa_opera_search_task(...) so QGIS task/thread
ownership remains explicit.

Direct Tool Calls

Every GeoAgent exposes the underlying Strands tool caller. This is useful for
tests, notebooks, and plugin UI actions:

agent = for_leafmap(m)
agent.tool.add_marker(lat=35.9606, lon=-83.9207, name="Knoxville")
agent.tool.list_layers()

You can inspect registered tool names and metadata:

agent.tool_names
agent.tool_registry.get_all_tools_config()

Safety and Confirmation

Tools carry metadata such as requires_confirmation, destructive, and
long_running. Confirmation is enforced by a Strands hook before gated tools
run.

By default, confirmation-required tools are denied unless you pass a
confirmation callback:

from geoagent import auto_approve_all, for_leafmap

agent = for_leafmap(m, confirm=auto_approve_all)

For real applications, pass a callback that opens a Qt dialog, notebook modal,
web UI prompt, or CLI prompt. Use confirmation for operations that delete data,
overwrite files, save projects, launch expensive jobs, or call external
services with cost implications.

Custom Tools

Package integrations can expose their own functions with @geo_tool:

from geoagent import GeoAgentContext, create_agent, geo_tool

@geo_tool(category="demo")
def buffer_distance(layer_name: str, distance: float) -> str:
    """Buffer a named layer by a distance in map units."""
    return f"Buffered {layer_name} by {distance}."

agent = create_agent(
    context=GeoAgentContext(),
    tools=[buffer_distance],
)

For package-specific adapters, prefer a factory that binds live objects through
closures, just like for_leafmap, for_anymap, and for_qgis. This keeps
widgets, clients, credentials, and session objects out of the LLM-visible
arguments.

Fast Mode

Pass fast=True to reduce the exposed tool surface and cap response tokens for
lower-latency map control:

agent = for_leafmap(m, fast=True)

Fast mode keeps common inspection, navigation, and basemap tools, filters out
heavier or more specialized tools, and limits model responses to short
post-tool replies. The cap is conservative enough for tool calls while avoiding
very long responses. The model call still dominates latency for local models,
so small prompts may not show a large timing difference on every provider.

Examples

Runnable notebooks live under docs/examples/:

  • docs/examples/intro.ipynb — basic GeoAgent usage.
  • docs/examples/openai_codex.ipynb — ChatGPT/Codex OAuth in Python/Jupyter.
  • docs/examples/stream_chat_openai_codex.ipynb — streamed ChatGPT/Codex output.
  • docs/examples/live_mapping.ipynb — live map workflow.
  • docs/examples/qgis_agent.ipynb — QGIS-oriented workflow using mocks.
  • examples/nasa_opera_qgis.py — NASA OPERA workflow for QGIS.

Prompt ideas:

  • "List layers on the current map."
  • "Add a marker for Seattle and zoom to it."
  • "Show the QGIS project state and summarize each layer."
  • "Select parcels where population is greater than 10000."
  • "Add a STAC layer and set its opacity to 0.6."
  • "Search for January 2024 OPERA surface water near Houston and display the footprints."

Development

git clone https://github.com/opengeos/GeoAgent.git
cd GeoAgent
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
pre-commit install

Run checks:

ruff check geoagent tests
pytest -q

See docs/contributing.md for guidance on adding new
package and tool integrations.

License

GeoAgent is released under the MIT License. See LICENSE.

Links

Reviews (0)

No results found