Skip to content

Architecture overview

github-actions[bot] edited this page Oct 25, 2026 · 1 revision

This page comes from site/content/architecture/overview.md in the repository and is regenerated on every merge to main. To correct it, edit that file; changes made here are overwritten.

Cartogen AI is a single Python package that QGIS loads as a plugin. It has no server and no build step. A request goes from the dock panel to an agent that talks to a model provider and calls tools; the tools use PyQGIS and Processing against your open project, and the results come back to the chat.

<title id="d1t">Architecture of Cartogen AI</title> Five layers: the QGIS host, the plugin UI, the agent core, the tools, and the outside world of model providers and data services. <style> .bx{fill:var(--surface);stroke:var(--line);stroke-width:1.5} .ac{fill:var(--accent-soft);stroke:var(--accent);stroke-width:1.5} .am{fill:var(--amber-soft);stroke:var(--amber);stroke-width:1.5} .tx{fill:var(--text);font:600 14px var(--font)} .sm{fill:var(--muted);font:12.5px var(--font)} .ar{stroke:var(--muted);stroke-width:1.5;fill:none;marker-end:url(#h)} </style> QGIS 4.2 (host process) UI: dock panel, settings, memory, help, dialogs core/ui · chat formatting is Qt-free · Processing provider (hub siting, service area) registers with the Toolbox The dock runs each request on a QgsTask worker thread and shows plan, steps, confirmations and the reply Agent core (core/agent): the tool-calling loop orchestrator · task matcher · tool router · prompt builder · history manager · usage tracker · scheduler guards: loop guard · response guard · plan gate · egress gate · model view · output router · stray-fragment gate state: spatial memory · chat persistence · results store · lineage · provenance · evidence folder Tools (212) @register_tool registry · one module per domain dispatcher runs them on the GUI thread, or on the worker for network-only and two-phase tools QGIS APIs qgis.core · Processing · QgsNetworkAccessManager Auth Manager · QgsTask · layouts · print export Isolated worker process for model-written scripts Outside the machine Model providers: OpenRouter, Gemini (cloud) or Ollama (local) · data: HDX, OSM, GDACS, USGS, UCDP, NASA, WorldPop

The five layers

Layer Where What it does
UI core/ui/ The dock panel, settings, memory, layer-sensitivity, account and help dialogs. Runs on the GUI thread. Logic that can be tested without Qt (chat formatting, colour derivation, icons as SVG strings) is kept Qt-free on purpose.
Agent core core/agent/ CartogenAi in agent_orchestrator.py is the tool-calling loop. It composes a tool dispatcher, a usage tracker and a history manager, and consults the task matcher, tool router and guards. See The agent loop.
Tools core/agent/tools/ 294 tools, one module per domain, registered with @register_tool. See Tools and routing.
Providers infrastructure/providers/ One client per model provider behind a common interface. See Providers and networking.
Services and models core/services/, core/models/, core/validators/, core/representation/ Prompt refiner, tool router, response guard; confidence, sensitivity, egress-gate and plan-gate models; schema and P-code validators; the map representation planner.

Cross-cutting: core/logger.py (structured, metadata-only logging), core/exceptions.py, core/net.py (HTTP through QGIS), infrastructure/auth.py (credentials), infrastructure/settings_keys.py (every QgsSettings key under cartogen_ai/).

What is deliberately not here

  • No server. Everything runs in your QGIS process, except an optional isolated subprocess for model-written scripts. service/ in the repository is an unfinished prototype for a hosted gateway and is not part of the plugin or its tests.
  • No tier-gating. One GPL v2 codebase; there is no licence-check logic.
  • No model hosting. Requests go straight from your machine to the provider you configured, with your key. The "Cartogen API" provider is a stub.

Design rules that shape the code

  1. Every module degrades without QGIS. Each module that touches qgis.core has its own QGIS_AVAILABLE guard, so the unit tests run on a plain Python install. Real QGIS behaviour is covered by a separate live test job. See Testing and CI.
  2. The model is untrusted input. Its tool calls can carry attacker-influenced arguments (prompt injection, a hallucination, a malicious provider), so the dangerous capabilities are gated in code, not in the prompt. See Security overview.
  3. Say what was and was not done. Replies are cross-checked against the tool calls that actually ran; a guard stop always reports what finished. See Guards.
  4. Metadata-only logging. Logs never contain prompts, replies, tool arguments, results or coordinates.

Where to read next

Clone this wiki locally