GeoAgent: a shared AI agent layer for geospatial Python and QGIS
A multimodal AI agent for geospatial data analysis and interactive visualization
At a glance
- What is it?
- GeoAgent gives leafmap, anymap, STAC, NASA Earthdata and QGIS plugins one agent stack instead of one per library. It is a thin, opinionated binding layer, not a data-processing engine, and that boundary matters when you decide to adopt it.
- Who is it for?
- Adopt GeoAgent if you maintain a geospatial Python package or a QGIS plugin and want tool exposure, provider switching and confirmation hooks without writing that layer yourself. Skip it if you need a data-processing engine or a stable API surface for a long-lived internal application, since the package is at 1.9.0 and the README documents no deprecation policy.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 2 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The duplicated agent stack GeoAgent is trying to remove
Every geospatial Python library that wants an LLM interface ends up rebuilding the same four things: a way to hand the model a list of callable functions, a way to describe those functions so the model uses them correctly, a way to talk to several model providers, and a way to stop the agent before it does something the user cannot undo. leafmap, anymap, geoai, geemap, STAC clients and NASA Earthdata clients all need roughly that set. GeoAgent's stated purpose is to be that shared layer so each library does not maintain its own.
The audience is narrower than the pitch suggests. This is a library for people who write geospatial Python packages or QGIS plugins, or who build internal tooling on top of leafmap or anymap. An analyst who just wants to ask a map a question is downstream of that work, not the direct user. The README frames GeoAgent as a shared layer with one consistent interface, which is a maintenance argument as much as a feature argument: the value is in not writing the same provider plumbing six times.
How GeoAgent binds tools to a live map or QGIS session
The mechanism is a facade over a Strands Agents Agent. GeoAgent itself does not implement the agent loop. It adds geospatial context, structured tool metadata, optional package adapters, provider configuration and confirmation hooks on top of Strands.
Four objects carry the design. GeoAgentConfig holds provider, model, temperature, token and client settings. GeoAgentContext holds runtime objects bound to the agent, such as a map or a QGIS iface. The @geo_tool decorator turns an ordinary Python function into a Strands tool with GeoAgent metadata attached. GeoToolRegistry stores tool metadata, safety flags, categories and fast-mode filtering.
The factories are where this becomes concrete. for_leafmap binds tools to a leafmap.Map-compatible object. for_anymap does the same for anymap.Map. for_qgis binds tools to qgis.utils.iface and an optional QgsProject. for_nasa_opera binds NASA OPERA search and display tools plus QGIS tools. for_stac binds STAC catalog search and asset tools with optional QGIS loading. create_agent is the escape hatch for custom tools or package-specific integrations.
The confirmation hook is the part worth copying into your own design. The README states that GeoAgent pauses the agent before destructive, expensive or otherwise irreversible operations, and names deleting layers, saving files and running expensive processing jobs as examples. That is a policy decision encoded in the tool metadata and registry rather than in a prompt, which is the right place for it. A prompt-level instruction to be careful is not a control. A registry flag that halts execution is.
Installing GeoAgent and binding tools to a leafmap map
The core package installs from PyPI and pulls in only strands-agents and pydantic. Geospatial packages and provider clients are extras, so the base install stays small.
pip install GeoAgentA leafmap workflow with OpenAI support needs both extras named together. The README gives this combination as an example.
pip install "GeoAgent[leafmap,openai]"The extras table lists openai, anthropic, gemini, ollama, litellm, openrouter, openai-compatible, vllm, leafmap, anymap, stac, earthdata, nasa-opera, geoai, earthengine, ui, browser, providers and all. The providers extra bundles OpenAI, Anthropic, Gemini, Ollama, LiteLLM, OpenRouter and OpenAI-compatible clients. The all extra covers most optional integrations, but the README notes that QGIS itself remains system-installed, so a QGIS workflow needs QGIS on the machine before any pip command matters.
One packaging detail deserves attention. The pyproject.toml carries a comment explaining that strands-vllm pins openai below version 2.0, which conflicts with the openai>=2.0 required by the default openai-codex provider. Because of that conflict, the vllm extra is not part of providers or all. The documented workaround is to point the openai-compatible provider at a vLLM server's /v1 URL. That is a real constraint, not a footnote: if you install GeoAgent[all] expecting vLLM support, you will not get it, and you will need to configure the compatible provider instead.
Python 3.11 or newer is required, and the classifiers list 3.11, 3.12 and 3.13. The repository also ships a console entry point, geoagent, mapped to geoagent.cli:main, so a command-line surface exists alongside the library API. The README does not document that CLI's subcommands, so treat it as something to inspect rather than something to script against on the strength of the README alone.
Provider breadth, vision input, and the parts the README leaves open
GeoAgent supports OpenAI, ChatGPT/Codex OAuth, Anthropic, Google Gemini, Bedrock, OpenRouter, LiteLLM, any OpenAI-compatible server, vLLM and local Ollama models. That list is the strongest argument for the shared-layer approach, because provider churn is exactly the work a single package should absorb once rather than five times.
The multimodal claim is conditional, and the README says so. Pasted images and screenshots in plugin workflows are supported when the selected model provider supports vision. That qualifier matters for anyone planning a screenshot-driven QGIS workflow: the capability belongs to the provider, not to GeoAgent, and switching to a text-only model removes it.
What the README does not cover is as informative as what it does. There is no documented rollback path for an agent action that was confirmed and then turned out to be wrong. There is no stated deprecation policy for the factory functions, and no compatibility matrix tying GeoAgent versions to leafmap, anymap or QGIS versions. The registry exposes fast-mode filtering, but the README does not explain what fast mode changes about tool selection or what it trades away. If your deployment depends on any of those, you are reading source, not documentation.
Where GeoAgent is the wrong layer
GeoAgent does not process raster or vector data. It routes requests to tools that do. If your problem is a large reprojection job, a tiling pipeline or a classification run, an agent layer adds a model call, a token budget and a failure mode in front of work that a script would do deterministically. The confirmation hook exists precisely because some of those operations are expensive, but a hook is not a reason to put a language model in the loop.
The second limitation is version maturity. The current release is 1.9.0, published on 2026-08-09, after 1.8.2 on 2026-06-02 and 1.8.1 on 2026-05-25. Three releases in roughly ten weeks is a fast cadence for a package whose factories are meant to be a stable integration point for downstream libraries. Downstream maintainers should pin, and should expect the tool metadata schema to move.
The third is scope. GeoAgent's abstraction is a map or a QGIS iface bound to an agent. If your workflow has no live map object, no QGIS session and no STAC or Earthdata client, the factories have nothing to bind to and you are left with create_agent plus your own tool definitions, which is a smaller win than the README's framing implies.
GeoAgent against a general-purpose agent framework
The obvious comparison is Strands Agents itself, since GeoAgent is built on it and the dependency floor is strands-agents>=1.37. Using Strands directly gives you the agent loop, the tool decorator and the provider adapters without the geospatial layer. What you would then write yourself is the GeoToolRegistry equivalent: the safety flags, the categories, the fast-mode filtering, and the confirmation hook that halts before a destructive call. You would also write your own leafmap, anymap and QGIS bindings.
That is a real choice, not a formality. If you are building one agent for one application, Strands directly is fewer moving parts and no upstream release cadence to track. If you are maintaining a package that other people integrate with, the registry and the confirmation hook are the parts you would otherwise reinvent badly, and GeoAgent's value is that those decisions are already made and shared across leafmap, anymap, geoai, geemap, STAC and NASA Earthdata.
The same logic separates GeoAgent from writing bespoke LangChain or LlamaIndex glue. Those frameworks solve orchestration generally. GeoAgent solves tool exposure for geospatial objects specifically, which is why for_qgis can take a QgsProject and why for_stac knows about catalog search and asset tools. General frameworks do not ship those bindings.
Licence, maintenance and what an upgrade actually costs
GeoAgent is MIT licensed, and the pyproject.toml declares the same. MIT is permissive, so embedding it in a commercial plugin or a closed internal tool is straightforward on the licence side. One point to check rather than assume: the dependency tree is not uniform. Strands Agents, pydantic, leafmap, anymap, geoai, geemap, earthengine-api, pystac-client, planetary-computer and earthaccess each carry their own licence, and the extras you install decide which of those you inherit. That is a review task, not a legal conclusion.
Maintenance looks current. The repository is not archived, and the last push was on 2026-09-06, which is recent. The release history shows 1.9.0 on 2026-08-09, 1.8.2 on 2026-06-02 and 1.8.1 on 2026-05-25. The repository carries a pre-commit configuration, a tests directory, a docs directory and a mkdocs.yml, plus a scripts directory, which suggests the project maintains its own documentation and test surface rather than relying on the README alone.
The upgrade cost is dominated by the extras model, and that is a feature. Because core installs only strands-agents and pydantic, a version bump of GeoAgent does not force a leafmap or QGIS upgrade. The cost lands on the factories instead: for_leafmap, for_anymap, for_qgis, for_nasa_opera and for_stac are the integration points, and a signature change in any of them propagates to every downstream package that calls it. Pin GeoAgent in your requirements and read the release notes before moving, because the README does not describe a deprecation window.
Editorial conclusion
Adopt GeoAgent if you maintain a geospatial Python package or a QGIS plugin and want tool exposure, provider switching and confirmation hooks without writing that layer yourself. Skip it if you need a data-processing engine or a stable API surface for a long-lived internal application, since the package is at 1.9.0 and the README documents no deprecation policy. Verify first that your Python is 3.11 or newer, that you can install the extras you actually need, and that your chosen provider is reachable from the environment where the agent runs. The vLLM extra is deliberately excluded from providers and all, so a vLLM deployment has to go through the openai-compatible provider pointed at the server's /v1 URL.
Frequently asked questions
What is GeoAgent and what does it do?
GeoAgent is a shared AI agent layer for geospatial Python packages, live map widgets and QGIS plugins. It binds tools to objects such as a leafmap map or a QGIS iface, exposes them to large language models through Strands Agents, and pauses the agent before destructive, expensive or irreversible operations.
How do I install GeoAgent?
Install the core package with pip install GeoAgent, which pulls in strands-agents and pydantic. Geospatial integrations and provider clients are optional extras, so a leafmap workflow with OpenAI uses pip install "GeoAgent[leafmap,openai]".
Does GeoAgent work with QGIS?
Yes. The for_qgis factory binds tools to qgis.utils.iface and an optional QgsProject, and GeoAgent is distributed as a QGIS plugin. QGIS itself remains system-installed and is not part of any pip extra, including GeoAgent[all].
Which model providers does GeoAgent support?
The README lists OpenAI, ChatGPT/Codex OAuth, Anthropic, Google Gemini, Bedrock, OpenRouter, LiteLLM, any OpenAI-compatible server, vLLM and local Ollama models. vLLM is not included in the providers or all extras because strands-vllm pins openai below version 2.0; the documented alternative is pointing the openai-compatible provider at the vLLM server's /v1 URL.
What Python version does GeoAgent require?
The pyproject.toml sets requires-python to >=3.11 and classifies Python 3.11, 3.12 and 3.13. The base dependencies are strands-agents>=1.37 and pydantic>=2.0.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/opengeos-geoagent)