Contributing¶
Contributions are welcome. GeoAgent is intended to be a shared integration layer for the geospatial Python and QGIS ecosystem, so high-quality package adapters, tests, and documentation are especially valuable.
Ways to Contribute¶
- Report bugs and reproducible failures.
- Improve existing adapters for
leafmap,anymap, QGIS, STAC, Earthdata, Earth Engine,geoai, or related packages. - Add integrations for new geospatial packages and tools.
- Improve mock objects so integrations can be tested in CI.
- Improve docs, examples, notebooks, and prompt patterns.
- Review pull requests and help keep APIs consistent.
Use GitHub issues for bug reports and feature proposals: https://github.com/opengeos/GeoAgent/issues
Development Setup¶
GeoAgent uses pyproject.toml and supports Python 3.11 and later.
1 2 3 4 5 6 | |
Install optional extras when working on a specific integration:
1 2 3 | |
For QGIS work, use the Python environment bundled with QGIS or make sure your development environment can import the relevant QGIS modules. Unit tests should still pass without QGIS installed by using mocks and lazy imports.
Local Checks¶
Run the standard checks before opening a pull request:
1 2 | |
If you change documentation, build the docs locally when possible:
1 | |
Keep changes focused. Avoid unrelated formatting churn or broad refactors in pull requests that add one adapter or fix one behavior.
Pull Request Guidelines¶
Before submitting a pull request:
- Add or update tests for the behavior you changed.
- Update README and docs when the user-facing tool surface changes.
- Keep optional integrations import-safe when their dependencies are missing.
- Use
@geo_toolfor tools exposed to the agent. - Mark destructive, persistent, costly, or long-running tools with confirmation metadata.
- Preserve existing factory behavior unless the pull request is explicitly about changing it.
- Include a concise summary of what changed and how you tested it.
Adding a New Package or Tool Integration¶
GeoAgent integrations should feel consistent no matter which geospatial package
they wrap. Use this checklist when adding a package such as geemap, xarray,
rasterio, pyogrio, lonboard, duckdb, whitebox, a QGIS plugin, or a
domain-specific service client.
1. Decide the Integration Shape¶
Use a tool module when the package exposes reusable functions that do not need a long-lived object:
1 | |
Use a factory when tools need a live object, session, widget, client, or QGIS interface:
1 2 3 4 5 | |
Factories should bind the live object through closures. Do not expose widgets, clients, credentials, database handles, or QGIS objects as tool arguments.
2. Keep Optional Dependencies Optional¶
Do not import heavy optional packages at module import time unless they are required by GeoAgent core. Prefer lazy imports inside tool bodies:
1 2 3 4 5 6 7 | |
This keeps import geoagent and import geoagent.tools.<module> usable in CI
and in environments that do not have every geospatial stack installed.
If the integration needs a new dependency, add it under
[project.optional-dependencies] in pyproject.toml, not as a required core
dependency.
3. Design Tool Functions for LLM Use¶
Good tools are small, explicit, and typed:
- Use clear function names:
add_cog_layer,search_stac,clip_raster. - Use typed parameters and simple return values:
dict,list,str, numbers, booleans. - Prefer structured data over long prose.
- Keep docstrings accurate; Strands uses them as tool descriptions.
- Use domain defaults that are safe and unsurprising.
- Validate ambiguous user input and return actionable messages.
- Avoid requiring the model to pass live Python objects.
Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
4. Use Metadata for Safety and Filtering¶
Use @geo_tool metadata deliberately:
1 2 3 4 5 6 7 8 | |
Mark tools as confirmation-required when they:
- delete or overwrite data;
- save projects or files;
- trigger long-running processing;
- call paid APIs or services;
- mutate remote state;
- make changes that are hard to undo.
Use available_in=("full", "fast") only for tools that are safe, quick, and
useful in low-latency mode.
5. Register the Integration¶
For a tool-only integration, export the tool factory from
geoagent/tools/__init__.py if it is part of the public API.
For a new top-level factory:
- Add the adapter module under
geoagent/tools/. - Add a
for_<package>factory ingeoagent/core/factory.py. - Add it to
geoagent/__init__.pyand__all__. - Update
assemble_toolsif the integration should participate in shared context assembly. - Add optional dependencies in
pyproject.toml. - Add docs and examples.
Keep new factories similar to for_leafmap, for_anymap, and for_qgis:
- accept
config,model,provider,model_id,fast,confirm, andextra_toolswhere appropriate; - create a
GeoAgentContext; - assemble and register tools;
- return a
GeoAgent.
6. Add Mocks and Tests¶
Every integration should be testable without requiring a full desktop GIS, cloud account, or heavyweight service.
Recommended tests:
- module imports without optional dependencies installed;
- factory returns an empty list or graceful result for
Nonewhere applicable; - expected tool names are registered;
- safety metadata is correct;
- tools call the expected mock methods;
- ambiguous and missing layer/resource names are handled;
- destructive tools require confirmation;
- fast mode includes only intended tools;
- docs examples do not reference missing tool names.
Place lightweight mocks in geoagent/testing/_mocks.py when they are useful
across tests. Keep mocks intentionally small: they should verify GeoAgent calls
the right methods and handles state correctly, not fully emulate external
packages.
7. Document the Integration¶
Update the relevant docs:
README.mdfor major public features.docs/index.mdfor package-level overview changes.docs/tools.mdfor new tool surfaces.- API docs pages if new modules or factories should appear in navigation.
- Example notebooks or snippets for common workflows.
Document:
- installation extras;
- required environment variables;
- factory usage;
- tool names and their purpose;
- safety/confirmation behavior;
- any limitations or package-version assumptions.
NASA OPERA Plugin Tools¶
The NASA OPERA QGIS plugin uses GeoAgent as its tool provider. Add new OPERA capabilities to GeoAgent first, not to the plugin-local AI code.
Use this split:
- GeoAgent: reusable OPERA search, display, download, mosaic, analysis, and QGIS-safe tool logic.
- NASA OPERA plugin: dock widgets, settings, provider/model selection, status text, dependency installation, and UI-specific behavior.
- Plugin compatibility aliases: old tool names or plugin-only shims, when
needed, in the plugin's
nasa_opera/ai/tools.py.
Recommended workflow:
- Add the tool implementation in
geoagent/tools/nasa_opera.pyinsidenasa_opera_tools(...). - Decorate it with
@geo_tool(...)and write clear typed parameters and structured return values. - Keep QGIS API calls inside the existing GUI-thread helper (
_on_gui(...)). Network, parsing, and file-preparation work should stay outside GUI calls where possible. - Add or update tests in
tests/test_nasa_opera_tools.py. Use mocks; do not require a live QGIS session or real Earthdata credentials for CI. - Update
NASA_OPERA_SYSTEM_PROMPTingeoagent/core/factory.pyif the model needs guidance about when to use the new tool. - Update
docs/tools.md,README.md, orexamples/nasa_opera_qgis.pywhen the tool is user-facing. - Only change the NASA OPERA plugin repo when the feature needs UI controls, settings, progress/status behavior, or an alias for backwards compatibility.
Rule of thumb: if it is a capability, put it in GeoAgent; if it is QGIS plugin presentation or wiring, put it in the NASA OPERA plugin.
Integration Quality Bar¶
An integration is ready when:
- importing GeoAgent still works without the optional package installed;
- the tool API is small, typed, and documented;
- live objects are captured by closures, not exposed as tool arguments;
- user-visible mutations have confirmation where appropriate;
- tests pass with mocks in CI;
- docs show installation, setup, and a minimal working example;
- behavior is consistent with existing
leafmap,anymap, and QGIS adapters.
Reporting Bugs¶
Please include:
- operating system and Python version;
- GeoAgent version or commit SHA;
- package extras installed;
- relevant provider and model;
- QGIS version if applicable;
- minimal code to reproduce the issue;
- full traceback or failing command output.
Proposing Features¶
For new integrations, open an issue first when the scope is large. Include:
- package or service to integrate;
- main user workflows;
- proposed tool names;
- required optional dependencies;
- whether tools mutate state, call paid services, or run long jobs;
- testing strategy without requiring real credentials or desktop applications.
Small improvements and focused bug fixes can go directly to a pull request.