SmartModeler GIS
Architecture & Design
Overview & Design Philosophy
SmartModeler GIS supports QGIS 3.44 LTR and QGIS 4 for building, executing, and iterating on real QGIS Processing workflows. It combines a typed node canvas with live algorithm discovery from the Processing registry, a validated AI planning system that operates through a fail-closed policy engine, and native .model3 interchange with the QGIS Model Designer.
The plugin rests on six principles:
- AI proposes, human disposes. Every AI-generated proposal is inert data until the user explicitly approves it. There is no auto-approve, no remembered approval, no background action. The AI never approves, applies, or undoes anything.
- Fail-closed security. All provider output is untrusted — even when the provider claims strict structured-output adherence. Every tool call is locally re-validated against a narrow contract. Unknown fields, ambiguous aliases, and malformed shapes are rejected.
- Deterministic offline workflows remain available without a network connection. The Studio works fully offline; the Agent Workspace is an optional enhancement, not a requirement.
- Provider neutrality. The Agent Workspace works with any configured AI connection — OpenAI, Anthropic, Gemini, DeepSeek, Ollama, OpenAI-compatible, Azure OpenAI — through a single structured protocol.
- No silent data mutation. Database writes, DDL, and live in-process Python require explicit second confirmation. Generated Python defaults to process isolation. Connection URIs, credentials, and source paths are never sent as tool metadata; attribute values only ever leave through
layer.field_values, one named field at a time. - Typed, validated graphs. Every node port is typed; every connection is validated against socket compatibility; every execution snapshot is immutable.
Dual-Surface Architecture
| Surface | UI | Purpose |
|---|---|---|
| Workflow Studio | Full-window canvas (SmartModelerWindow) | Visual graph editing: drag nodes from the algorithm palette, wire ports, configure parameters, run workflows. The primary design surface. |
| Agent Workspace | Dockable panel (AgentWorkspaceDock) | Multi-turn AI conversation with 25 read-only inspection tools. Generates validated proposals that the user reviews and approves. Integrated with Workflow Studio: proposals can patch the live graph or run Processing algorithms. |
Both surfaces share one execution slot — they cannot run or apply competing changes concurrently. The Agent Workspace reads the Workflow Studio's current graph through a read-only adapter; proposals are applied through a single trusted seam that validates the graph before installation.
Security Model: Fail-Closed by Default
The security architecture is layered:
| Layer | Mechanism |
|---|---|
| 1. Transport | Raw provider response capped at 100,000 characters. Rejected before JSON parsing if oversized. |
| 2. Envelope | Strict 5-key JSON schema. Ambiguous aliases, prose, or JSON substrings extracted from prose are rejected by the local parser. |
| 3. Tool validation | Every tool call is validated against a registry of exactly 25 read-only tools. Tool names must match a narrow regex. Argument shapes are structurally validated. |
| 4. Proposal validation | Eight proposal kinds, each with strict local validation. Model patches are validated against a detached graph clone. Style proposals are validated against the live layer's fields. |
| 5. Runtime policy | At Apply or Run time, the live state is re-checked. Processing runs are signature-pinned; only reviewed algorithms whose live signature passes the structural policy can execute. Results go to temporary layers only — no user-selected file, folder, or database destination. |
| 6. Power Mode gate | SQL, trusted scripts, and PyQGIS are opt-in only (off by default). Database writes and live Python require a second explicit confirmation. |
Workflow Studio
Graph Model & Typed Sockets
The graph is a pure-Python directed acyclic graph (DAG) defined in core/graph_model.py. Each node is an instance of a Processing algorithm; each port is a typed socket:
| Socket Type | Constant | Compatible With |
|---|---|---|
| Vector layer | VECTOR | Line, Polygon, Point, Multi* variants |
| Raster layer | RASTER | Single and multi-band rasters |
| Number | NUMBER | Integer, Double |
| String / Text | STRING | QGIS expression, domain text |
| Boolean | BOOLEAN | True/False |
| Field (attribute) | FIELD | Field name from a vector layer |
| Table | TABLE | Non-spatial attribute tables |
| File | FILE | File path (domain-constrained in Agent runs) |
| CRS | CRS | Coordinate Reference System |
| Extent | EXTENT | Bounding box |
| Enum | ENUM | Categorical choice |
| Any | ANY | Wildcard — accepts any type |
Connections are validated at edge-creation time: a VECTOR output can connect to a VECTOR or ANY input, but not to a RASTER or NUMBER input. Multi-layer collection inputs (allows_multiple=True) accept multiple connections.
Visual Canvas, Nodes, Ports & Connections
The Workflow Studio canvas (gui/canvas_scene.py, gui/canvas_view.py) is a QGraphicsScene-based interactive editor. Nodes are rendered as rounded rectangles with colour-coded port circles on input (left) and output (right) sides. Connections are Bézier curves that snap to port positions. The canvas supports: drag-to-pan, scroll-to-zoom, rubber-band selection, delete/duplicate, and auto-layout (core/auto_layout.py) for topological sorting of the graph.
Live Algorithm Discovery
The algorithm palette is populated directly from the QGIS Processing registry at Studio open time. Every installed Processing provider — native QGIS algorithms, GDAL, GRASS, SAGA, and PlanX plugins — contributes its algorithms as draggable node types. The registry audit verifies that every algorithm constructs a typed node and preserves its port schema through a bounded JSON round-trip. Configuration-dependent algorithms (those that change their ports based on a parameter choice) rebuild their live port schema from the stored configuration before validation or execution.
Execution Engine & Run Setup
The Run Setup dialog shows every workflow step in topological order. Each step displays its connected inputs and where they come from; open inputs are editable in-place with the project's compatible layers offered in a dropdown. When only one project layer matches an unbound vector input, it is auto-bound.
Execution takes an immutable snapshot of the workflow and runs it in a cancellable QGIS background task (QgsTask). The canvas is locked during the run except for the Cancel button (Esc). Nodes execute in topological order; unselected conditional branches are pruned. Algorithms marked NoThreading by QGIS are refused — the user is directed to export as .model3 and run manually.
Results are committed atomically on the main QGIS thread. Only explicitly published outputs are added to the project. A structured run report distinguishes completion, cancellation, failure, and partial execution, and retains exact result-layer identities for safe cleanup.
Smart Proposals: Contextual Next-Step Ranking
When a node is selected on the canvas, the Smart Proposal Bar (gui/smart_proposal_bar.py) ranks contextual next steps: which algorithms accept the selected node's output types as input? Each proposal explains and previews its target connection. Accepting a proposal adds and auto-connects the node as one undoable edit. This is a deterministic, offline feature — no AI required. The proposal engine (core/proposal_engine.py) matches output socket types against the input requirements of all installed algorithms.
Micro-Packages & Showcase Graphs
Current gallery: the catalog contains fifteen deterministic workflows: five compact starters and ten branching showcases covering PlanX-style network centrality and settlement fabric, Urban Resilience heat analysis, 15-minute transit access, suitability constraints, walkable-city access, blue-green resilience, urban morphology, flood readiness, and growth constraints. Double-click a gallery item to load it, then bind the highlighted input layers in Run Setup.
Five versioned, schema-validated micro-package workflows are shipped with the plugin. They build deterministic graphs directly without any AI profile or network request. Each is hidden when its required Processing algorithms are unavailable. The showcase gallery presents these as ready-to-run examples demonstrating common patterns: buffer → clip, select by attribute → dissolve, etc.
Workflow Studio — Extended Theory
Workflow Automation Theory
Theoretical Background
Workflow automation in geographic information systems rests on three converging theoretical pillars: visual programming language (VPL) theory, which provides the cognitive framework for representing computation graphically; directed acyclic graph (DAG) theory, which supplies the formal execution model; and end-user development (EUD) theory, which explains how domain experts without formal programming training can construct reproducible analytical pipelines. SmartModeler’s Workflow Studio instantiates all three within the QGIS Processing ecosystem.
Visual programming languages for GIS emerged from the broader recognition that spatial analysis workflows are inherently dataflow-oriented: a sequence of transformations applied to geographic data, where the output of one operation becomes the input of the next. Dobesova (2020) formally defined the VPL vocabulary for GIS as comprising symbols (nodes representing algorithms), connectors (edges representing data flow), and layout conventions that encode topological ordering. The QGIS Processing Modeler represents one such VPL implementation; SmartModeler extends this paradigm with typed socket validation, live algorithm discovery from the Processing registry, and an AI-assisted planning layer that operates through a fail-closed security model.
The dataflow programming model contrasts with imperative (control-flow) programming in a fundamental way: in a dataflow graph, execution order is determined by data dependencies rather than by an explicit sequence of instructions. This property—known as functional determinism—means that any two nodes with no direct or transitive dependency can execute concurrently without affecting the final result (Johnston, Hanna, & Millar, 2004). SmartModeler exploits this property in its execution engine: nodes at the same topological depth are eligible for parallel evaluation, though the current implementation serializes them within a single QgsTask for deterministic debugging.
The end-user development perspective is particularly salient for GIS workflows. Nardi (1993) established that domain experts develop computational artifacts not by learning general-purpose programming but by operating within task-specific formalisms that match their mental models. In GIS, the task-specific formalism is the spatial analysis pipeline itself: select, buffer, intersect, dissolve, calculate. SmartModeler’s Smart Proposal Bar operationalizes this insight by suggesting contextually appropriate next steps based solely on socket type compatibility, without requiring the user to search through hundreds of Processing algorithms.
Shneiderman (1983) articulated the principles of direct manipulation that underlie effective visual interfaces: continuous visual representation of the object of interest, physical actions (drag, connect, click) rather than complex syntax, and rapid, incremental, reversible operations with immediate visible feedback. The Workflow Studio canvas embodies these principles: nodes are continuously visible, connections are drawn as Bezier curves, parameters are edited in-place, and every operation (add node, connect, disconnect, delete) is an individually undoable edit.
Dataflow Graph Execution Model
Formally, a SmartModeler workflow is a 5-tuple \(G = (N, E, \tau_N, \tau_E, \sigma)\) where:
- \(N\) is the set of nodes, each representing an instance of a QGIS Processing algorithm with a unique identifier \(n_i \in N\).
- \(E \subseteq N \times N\) is the set of directed edges, where \((n_i, n_j) \in E\) indicates that an output of \(n_i\) is connected to an input of \(n_j\).
- \(\tau_N : N \to \mathcal{A}\) maps each node to its algorithm identifier from the Processing registry \(\mathcal{A}\).
- \(\tau_E : E \to \Sigma \times \Sigma\) maps each edge to a pair of socket types \((\sigma_{\text{out}}, \sigma_{\text{in}})\) such that the compatibility predicate \(\text{compat}(\sigma_{\text{out}}, \sigma_{\text{in}})\) holds.
- \(\sigma : N \to 2^{\Sigma \times \mathbb{V}}\) maps each node to its parameter bindings, where \(\mathbb{V}\) is the value space.
The execution semantics follow a two-phase model. In the planning phase, the graph is topologically sorted using Kahn’s algorithm (Kahn, 1962) to produce an ordered sequence \([n_{k_1}, n_{k_2}, \ldots, n_{k_m}]\) where for every edge \((n_i, n_j) \in E\), \(n_i\) precedes \(n_j\) in the ordering. In the execution phase, the engine iterates through the sorted nodes, resolving each node’s input connections to the cached outputs of its predecessors, and delegates actual computation to the QGIS Processing framework via QgsProcessingAlgorithm.
Typed Socket System and Type Safety
The socket type system provides construction-time guarantees about data flow compatibility. The type lattice \(\mathcal{L}\) is defined over 12 primitive socket types with a partial order induced by the ANY wildcard:
\[\forall \sigma \in \Sigma \setminus \{\text{ANY}\}: \sigma \preceq \text{ANY}\]
An edge \((n_i, \text{out}_p, n_j, \text{in}_q)\) is type-valid if and only if:
\[\tau(\text{out}_p) = \tau(\text{in}_q) \lor \tau(\text{out}_p) = \text{ANY} \lor \tau(\text{in}_q) = \text{ANY}\]
This compatibility relation is symmetric in practice but asymmetric in semantics: the output type must be usable as the input type. The implementation (GraphModel.socket_types_compatible) enforces this through exact equality or the ANY wildcard. Notably, subtype relationships (e.g., Point is-a Vector) are collapsed into the broader VECTOR category at the socket level; finer-grained geometry type compatibility is deferred to the QGIS Processing runtime.
Agent-Assisted Workflow Construction
The Agent Workspace adds a fourth theoretical layer: validated AI-assisted planning. Drawing on the fail-closed design principles articulated by Hua et al. (2024) in the TrustAgent framework, SmartModeler’s agent operates under a strict separation of proposal and execution: every AI-generated model patch is parsed as inert JSON data, validated against a detached graph clone, and presented as an approval card that the user must explicitly accept. The AI never executes, approves, or undoes anything. This architecture aligns with the broader literature on safe LLM-based tool use, where the key insight is that proposal validation must be local, deterministic, and independent of the LLM’s claims about its own output.
Literature
Kahn, A.B. (1962). Topological sorting of large networks. Communications of the ACM, 5(11), 558–562. DOI: 10.1145/368996.369025
Dobesova, Z. (2020). Visual programming for GIS applications. In J.P. Wilson (ed.), Geographic Information Science & Technology Body of Knowledge (1st Quarter 2020 ed.). DOI: 10.22224/gistbok/2020.1.7
Dobesova, Z. (2020). Evaluation of effective cognition for the QGIS Processing Modeler. Applied Sciences, 10(4), 1446. DOI: 10.3390/app10041446
Johnston, W.M., Hanna, J.R.P. & Millar, R.J. (2004). Advances in dataflow programming languages. ACM Computing Surveys, 36(1), 1–34. DOI: 10.1145/1013208.1013209
Nardi, B.A. (1993). A Small Matter of Programming: Perspectives on End User Computing. MIT Press. DOI: 10.7551/mitpress/6270.001.0001
Shneiderman, B. (1983). Direct manipulation: A step beyond programming languages. IEEE Computer, 16(8), 57–69. DOI: 10.1109/MC.1983.1654471
Graser, A. & Olaya, V. (2015). Processing: A Python framework for the seamless integration of geoprocessing tools in QGIS. ISPRS International Journal of Geo-Information, 4(4), 2219–2245. DOI: 10.3390/ijgi4042219
Hua, W. et al. (2024). TrustAgent: Towards safe and trustworthy LLM-based agents. In Findings of the ACL: EMNLP 2024, pp. 10563–10580. DOI: 10.18653/v1/2024.findings-emnlp.585
Dobesova, Z. & Dobes, P. (2014). Differences in visual programming for GIS. Applied Mechanics and Materials, 519–520, 353–356. DOI: 10.4028/www.scientific.net/AMM.519-520.353
Gamma, E., Helm, R., Johnson, R. & Vlissides, J. (1994). Design Patterns: Elements of Reusable Object-Oriented Software. Addison-Wesley.
Agent Workspace
Agent Workspace Architecture
The Agent Workspace (gui/agent_dock.py) is a dockable multi-turn AI chat panel. It operates through a capability-routed registry of 25 read-only inspection tools. Every provider turn is parsed as a strict structured envelope; mode, scope, and tool execution stay under application control.
The workspace connects through core/ai_client.py and core/ai_settings.py — a provider-neutral AI client supporting OpenAI, Anthropic, Gemini, DeepSeek, Ollama, OpenAI-compatible, and Azure OpenAI backends. API keys are stored in session memory or the optional encrypted QGIS vault. The offline profile keeps quick inspections working without any language model.
Provider-Neutral Structured Protocol
Every provider turn uses a strict 5-key JSON envelope (core/agent/protocol.py):
{
"assistant_text": str (≤8,000 chars),
"tool_calls": [AgentToolCall],
"proposal_kind": str (≤80 chars),
"proposal_json": str (≤MAX_PROPOSAL_JSON_CHARS),
"fence": bool
}
The local parser accepts a narrow set of authority-neutral tool-call field aliases used by real providers, normalizes them to the canonical contract, then performs the same local tool/argument validation. Ambiguous aliases, unknown fields, malformed shapes, prose, or JSON substrings extracted from prose are rejected. A fence: true response is a valid empty turn — the provider declined to answer.
25 Read-Only Inspection Tools
No source URI, style/label expression, baseline model parameter value, or credential is ever sent. Attribute values reach the model through one tool, layer.field_values, and only for a single explicitly named field: aggregate statistics plus a capped value sample, never a feature and never a row. That single exception exists because an agent that cannot see a value cannot distinguish a filter that correctly matched nothing from one that measured the wrong quantity — and it filled the gap by inventing an answer. Every other tool below remains metadata-only.
Tools are capability-routed: only the ones relevant to the current scope and request are advertised on a given turn, so a styling question never carries the database schemas. Power Mode and Workspace tools are absent entirely unless that mode is switched on.
| Group | Tool | What It Reads |
|---|---|---|
| Project & layers | project.summary | Project title, CRS and layer count. Never the saved project path. |
layer.list | Every layer's id, bounded name, kind, geometry type, CRS, visibility, provider key, an exact active-layer marker, and whether its CRS can measure area truthfully. | |
layer.describe | Field names, broad field types and feature count for one layer. Resolves an exact unique layer name as well as an id. | |
layer.field_values | The one tool that returns attribute values: minimum, maximum, mean, median, null count, distinct count and a capped sample for one named field. Ordering statistics appear only when every value is numeric. | |
layer.suggest_crs | Metric CRS candidates whose declared area of use actually contains the layer: its UTM zone, the project CRS, CRSs used by other layers, and recently used ones. | |
layer.style | Current renderer family, symbol summary and label state, plus a freshness receipt for a styling proposal. | |
| Processing | processing.search | Ranked, bounded search of the live Processing registry; runnable matches first. |
processing.describe | One algorithm's live typed signature: every parameter, its kind, bounds, live enum options, and how a proposal may bind it. | |
processing.resolve | Search and describe in one call, returning the freshness receipt a run proposal needs. | |
expression.search | Live QGIS built-in expression help for a named function. | |
| Workflow Studio | model.summary | The open graph's node list and edge count. |
model.describe | Node-and-edge topology of the open graph, with a receipt for a model patch. | |
model.validate | Validation issues for the open graph. | |
| Plugins | plugin.list | Installed plugin package names. |
plugin.describe | One installed plugin's metadata. | |
plugin.capabilities | What one installed plugin can actually be used for: its provider, runnable algorithms, and reviewed actions. | |
| Power Mode 🔒 | database.list | Configured database connections, by opaque token. Power Mode only. |
database.describe | Schemas, tables and column metadata for one connection. Power Mode only. | |
script.list | Imported trusted scripts and their pinned hashes. Power Mode only. | |
script.describe | One trusted script's full source for review. Power Mode only. | |
| Workspace (Developer) | workspace.list | Plugin source files inside the bounded workspace root. |
workspace.read | One workspace file's contents. | |
workspace.inspect | Workspace state for diagnostics. | |
workspace.search | Search across workspace source. | |
workspace.command | One reviewed, safe diagnostic command. |
Plan Mode vs Act Mode
| Mode | Proposal State | User Action Required |
|---|---|---|
| Plan | Review-only — shows Not applied status | Read the proposal, discuss with the agent, iterate. No change is made to QGIS. |
| Act | Pending — appears on a read-only approval card | Click Apply to commit. The proposal is re-validated against live state at click time. On failure, the change is rolled back atomically. |
In both modes, the agent's tool calls execute the same read-only inspections. The difference is only what happens with the validated proposal: in Plan it stays as review text; in Act it becomes a clickable approval card.
Eight Validated Proposal Types
| Proposal Kind | What It Produces |
|---|---|
model_patch | A complete replacement graph for the Workflow Studio. Validated on a detached clone before the approval card appears. |
layer_style | A symbology-and-labeling intent (single_symbol, categorized, graduated, raster_gray). Validated against the live layer's fields. |
processing_run | A single reviewed Processing run with signature-pinned algorithm. Results go to temporary layers. |
workflow_run | Run the current Workflow Studio graph (same as clicking Run in Studio). |
plugin_action | One explicitly reviewed cross-plugin action (e.g., open 02viz on a selected layer). Own approval card. |
sql_run 🔒 | Full-source SQL statement. Power Mode only. Database writes/DDL require second confirmation. |
trusted_script_run 🔒 | Hash-pinned trusted script. Power Mode only. Second confirmation required. |
python_run 🔒 | Generated PyQGIS source, shown in full on the approval card. Power Mode only. Defaults to process-isolated subprocess. Live in-process requires second confirmation + no-rollback warning. |
Action Ledger & Undo
Every applied agent action is recorded in a bounded in-session action ledger (core/agent/action_ledger.py). The Undo last agent action command reverts the most recent model, style, or run change — but only while the live target still matches the action's recorded post-state, so it never overwrites a later user edit. The ledger is capped at 10 actions per session; old entries are pruned.
Using the Agent in Practice
Everything above describes how the plugin is built. This chapter is about getting good results out of it. It is written from real sessions, including the ones that went badly — most of the guidance below exists because something failed first.
A worked session, start to finish
The task: download buildings for the current map view, measure them, keep the small ones, and classify them. This is the sequence that works, and the reason each step is phrased the way it is.
Set Mode: Act and Scope: Project before starting. Act is what produces approval cards; Plan will only ever show you a preview.
| # | What you type | What happens, and why it is phrased this way |
|---|---|---|
| 1 | download the buildings in the map extent with the zero2agent plugin | Naming the plugin removes a guess. The agent checks plugin.capabilities, resolves the download algorithm and proposes one run. You get point, line and polygon layers — two of them usually empty, which the chat now says out loud. |
| 2 | reproject Download curated OSM thematic preset - OUTPUT_POLYGONS to the local metric CRS | OSM arrives in EPSG:3857. Do this before measuring anything. The agent calls layer.suggest_crs and picks a real UTM zone or national grid; you no longer have to know the code yourself. |
| 3 | add an area column called alan_m2 to the reprojected layer | Giving the column a name means you can refer to it later without ambiguity. On a metric layer this is accepted; on the original 3857 layer it is refused with an explanation. |
| 4 | what are the minimum and maximum of alan_m2? | Switch to Ask for this — it costs no action budget. This is the step that tells you whether your threshold is sensible before you filter with it. |
| 5 | make a new layer with only the buildings where alan_m2 is 300 or less | “New layer” is the important part: it selects extraction rather than an in-place selection. A threshold phrased with the field name and a number is understood directly. |
| 6 | classify that layer by alan_m2 with jenks into 5 classes | An Apply card, not a Run card — styling is applied, not executed. You may leave the colours to the plugin or say “use a red to yellow ramp”. |
| 7 | apply a -2 metre buffer to it | Negative buffers shrink polygons and are supported. Say “metre” so the number is read as a distance. |
Steps 5–7 can be combined into one message if Continue multi-step requests is ticked; a single message carries at most four automatic steps. Each step still stops at its own approval card.
Writing requests the agent can act on
The agent is not guessing at your intent from a blank slate — it inspects the live project first. What it cannot do is resolve an ambiguity that only you can settle. These are the patterns that consistently work.
| Instead of | Write | Why |
|---|---|---|
| filter this layer | make a new layer from Buildings UTM where alan_m2 is under 300 | Names the layer, the field, the comparison and the output shape. “This layer” is ambiguous the moment a run has produced a second one. |
| calculate the area | add a decimal column alan_m2 with the area in square metres | Names the column and its type, so a later step can refer to it. |
| reproject to a suitable CRS | reproject to the local metric CRS | Both work now, but the second phrasing routes straight to the CRS suggestion tool instead of inviting an invented code. |
| style it nicely | classify by alan_m2, quantile, 5 classes, blue ramp | Method, field, class count and colour are four independent choices. Unstated ones are chosen for you, which may not be what you wanted. |
| do the whole analysis | one step per message | A rejected proposal in the middle of a five-step request costs the whole request. One step at a time fails cheaply. |
Steering the agent when it goes wrong
- Correct the fact, not the behaviour. “The field is
alan_m2, notalanm2” works. “Do it properly” does not — the agent has no way to tell what changed. - Paste the layer id when a layer cannot be found. Click Layers in the quick-inspection row, copy the exact
layer_id, and give it. This resolves any ambiguity in one turn. - If a result looks wrong, ask about the data before asking for a redo. “What is the minimum of
alan_m2?” usually reveals the real problem — an empty result after a correct filter is a fact about your data, not a bug. - Say what you already know. “The layer is already in UTM” or “the field is text, convert it first” saves an inspection turn and often an entire failed proposal.
- Do not ask it to approve its own work. “Just do it, do not ask me” cannot be honoured: Apply and Run belong to you by design, and no phrasing changes that.
- Start a new chat when you change task. Session memory is what lets “now style the result” work; it also means a long unrelated history is still in play.
Ways of working
| Situation | Use |
|---|---|
| You want to understand the project, a field's range, or what an algorithm does | Ask mode. Costs no action budget and changes nothing. |
| You want to see what would happen without any possibility of it happening | Plan mode. Proposals render as review-only. |
| You want the work done, one approved step at a time | Act mode. |
| The request concerns one layer you have selected | Scope Active layer. The agent stops asking which layer you mean. |
| The request spans several layers | Scope Project. |
| You want a reusable, inspectable pipeline rather than a one-off result | Workflow Studio. Build it there, save as .model3, re-run it on new data. |
| You need SQL, PyQGIS, or a trusted script | Power Mode, which is off by default and adds its own confirmations. |
On the action budget. A chat may complete ten actions, after which it asks whether to allow another ten — twice at most. This is deliberate: it is the point at which a person should look at what has accumulated. Say yes and the conversation, its layers and its notes are all preserved.
On temporary layers. Every run produces a temporary memory layer. They vanish when QGIS closes. When a result matters, right-click it and Make permanent before you move on.
What the messages mean, and what to do
These are the exact messages the plugin produces, why each one exists, and the action that resolves it. A refusal here is almost always the plugin stopping a run that would have succeeded and given you a wrong answer.
| Message | What actually happened | What to do |
|---|---|---|
| A geometry measure ($area/$length) was requested on … whose CRS does not measure in true metres | The layer is in a geographic CRS (degrees) or Web Mercator, where area is inflated by 1/cos²(latitude) — 1.76× at 41° north. A genuinely 324 m² building measures 569 m² there. | Reproject first: “reproject to the local metric CRS”. This is the single most consequential refusal in the plugin. |
| … is text, so QGIS would compare it letter by letter | An ordering comparison against a text field. QGIS runs this happily and returns nonsense: '1097' < '400' is true, '568' < '400' is false. | Ask for the value in a new numeric column, then filter on that. |
| … already exists as 'String' … write to a NEW field name instead | Recalculating a field never changes its type. QGIS ignores the requested type, reports success, and changes nothing. | Choose a different column name for the converted values. |
| WARNING: … contains no features. The operation ran; it matched nothing. | Not an error. The run worked and the result is empty. | Ask for the field's minimum and maximum. Either your threshold is outside the data, or something upstream measured the wrong quantity. |
| No layer with that id or name. Call layer.list and copy an exact layer_id. | The name given matches nothing, or two layers share it. | Click Layers, copy the exact layer_id, and paste it. Rename duplicate temporary layers — several runs in a row produce very similar names. |
| A choice label does not match any live option. Live options: … | An option was named that is not on this algorithm, or an abbreviation that matches two of them. | The message lists the live options; pick one verbatim. |
| The renderer field 'x' is not on the target layer. Live fields: … | The styling field does not exist. A single-character miss is corrected automatically and flagged on the approval card; anything larger is refused. | Use a field from the list in the message. |
| This chat has already completed its limit of 10 actions | The session budget is spent. | Answer Yes when asked to extend, or start a New chat. Two extensions are available per chat. |
| Agent Workspace could not start the workflow request: … | Workflow Studio could not hand the request to the agent. The reason follows the colon. | Usually an Offline profile, a missing API key, or a run already in progress. Open AI connections, or wait for the current run. |
| The AI response could not be understood: … | The provider returned a malformed envelope. The plugin repairs the first fault of each kind automatically; this appears when repair did not work. | Send the request again, more specifically. If it recurs on every message, the model is likely too small for structured output — see below. |
| Agent Chat needs a configured AI connection (not Offline) | No language model is selected. | AI connections… → choose a provider and paste a key. Quick inspections still work offline. |
Choosing a model
The plugin is provider-neutral: safety, validation and approval behave identically on every backend. Reliability does not. The agent must return a strict JSON envelope on every turn, so a model with weak structured-output support will spend turns being repaired instead of working. Prefer a current mid-to-large instruction-tuned model with native JSON mode; very small local models are usable for inspection but frustrating for proposals.
When to suspect the plugin rather than the model
A refusal that names a specific fact — a CRS, a field type, an option list — is the plugin doing its job. Suspect a defect when the agent loops on the same inspection three times, when a message contradicts something you can see in the Layers panel, or when an operation you know QGIS supports cannot be expressed at all. Those are worth reporting on the issue tracker, ideally with the chat transcript — several of the behaviours documented in this chapter were found exactly that way.
Document System
Undo/Redo, Dirty-State & Crash Recovery
The document system (core/document_state.py) tracks the complete editable graph with general Undo/Redo (unlimited stack). A dirty-state flag drives the title-bar asterisk and guards New/Open/Close with unsaved-change prompts. Crash recovery auto-saves to a temporary file; on next Studio open, if a recovery file exists and is newer than the last saved version, the user is offered the choice to restore it.
.model3 Interchange & Python Export
SmartModeler imports and exports three formats:
| Format | Extension | Direction | Notes |
|---|---|---|---|
| SmartModeler JSON v3 | .sm3 | Import & Export | Versioned, schema-validated. Ports are rebuilt from the live Processing registry on import — stored schemas are never trusted. |
| QGIS .model3 | .model3 | Import & Export | Native QGIS Model Designer format. Unbound inputs become model inputs so the workflow opens correctly in the QGIS Model Designer. Preserves boolean, string, number, field, CRS, extent, enum, map-layer, and multi-layer parameters; ordered mixed sources; conditional child dependencies; published outputs. |
| QGIS Python | .py | Export only | Runnable QGIS Python algorithm script. Uses the Processing API to reconstruct the workflow programmatically. |
Document Codec: V2 → V3 Migration
V2 documents are migrated through the same validation path as V3: ports are rebuilt from the live Processing registry, not from stored schemas. This ensures that a workflow saved under an older QGIS version with different algorithm signatures opens correctly on the current version.
Power Mode
Power Mode: Opt-In Advanced Capabilities
Power Mode is explicit and off by default. Keep it off for ordinary layer inspection, Processing filters, model patches, styling, and standard model runs. Enable it only when the request genuinely needs stored database inspection/SQL, an imported hash-pinned script, or generated PyQGIS that cannot be expressed as a reviewed Processing graph. When enabled, three additional proposal kinds become available. Each carries its own warning and confirmation gate; enabling the checkbox never executes code.
Full-Source SQL
The agent can inspect stored PostGIS/GeoPackage connection metadata through opaque receipts (never transmitting the actual URI or credentials) and propose one complete SQL statement. The approval card shows the full source. Database writes and DDL require a second explicit confirmation beyond the normal Apply click.
Trusted Scripts (Hash-Pinned)
A managed, hash-pinned trusted script can be proposed. The script's content hash is validated against a stored manifest before the approval card appears. Requires a second confirmation. Used for reviewed, reproducible data-processing pipelines.
Generated PyQGIS (Process-Isolated)
The agent can generate complete PyQGIS source code, shown in full on the approval card. By default, execution uses a cancellable, timeout-bounded separate QGIS subprocess: selected vector inputs are snapshotted; only requested/new vector outputs are imported back. This is process isolation, not a security sandbox — the code still has the current user's filesystem and network permissions. Live in-process Python requires a second confirmation and carries a no-rollback warning.
Processing Provider & Plugins
Processing Provider & Algorithms
SmartModeler registers as a QGIS Processing provider (processing/provider.py) with six algorithms:
| Algorithm ID | Purpose |
|---|---|
smartmodeler:osmdownload | Bounded OSM data acquisition for roads, buildings, and trees within a map-canvas extent |
smartmodeler:randomextract | Random feature subset extraction from a vector layer |
smartmodeler:fieldcalculator | QGIS field calculator with live expression validation |
smartmodeler:filterlayer | Attribute-based layer filtering with deterministic FID output |
smartmodeler:extractbyreferenceattribute | AI-facing district/area attribute filter followed by a reviewed spatial extraction |
smartmodeler:power | Power Mode execution gateway (only available when Power Mode is enabled) |
Plugin Capabilities Discovery
The plugin_capabilities tool (core/agent/plugin_capabilities.py) identifies what an installed plugin can be used for without importing, instantiating, or reading the plugin. It asks the Processing provider registry which Python package defined a given provider, then lists that provider's algorithms. Each algorithm is independently marked runnable or blocked from its live signature. UI-only plugins are resolved by package or visible name. A mapping is either proved or reported as unproved — a look-alike name is never presented as a confirmation.
Companion Plugin AI Bridge
Trusted PlanX companion plugins (such as 02Agent OSM Downloader) can open SmartModeler's AI Connections and Agent Workspace through a narrow public bridge (core/agent/plugin_actions.py). They receive only display-safe profile/provider/model information; API secrets remain in SmartModeler's session memory or encrypted QGIS vault. Each cross-plugin action uses its own application-reviewed adapter, shown on its own approval card. The first adapter opens 02viz on one selected vector layer and renders 02viz's offline smart chart suggestion.
Workflow Patterns & Best Practices
Theoretical Background: Design Patterns in GIS Workflows
Gamma et al.’s (1994) catalog of object-oriented design patterns established a vocabulary for reusable solutions to recurring problems. In the context of visual GIS workflows, analogous patterns emerge from the constraints of spatial data processing. SmartModeler’s micro-package gallery encodes fifteen such patterns, including ten multi-branch showcases, each a validated graph demonstrating a spatial analysis idiom.
Pattern 1: Buffer-Spatial Filter (Buffer → Clip)
Structure: A buffer node generates a proximity zone around input features; the buffered geometry feeds the overlay layer input of a clip node, which restricts the second input layer to the proximity zone.
Mathematical foundation: Given a set of source geometries \(\mathcal{S}\) and a set of target features \(\mathcal{T}\), the buffer-clip pattern computes:
\[\mathcal{T}_{\text{filtered}} = \{t \cap \text{buffer}(\mathcal{S}, d) : t \in \mathcal{T}, t \cap \text{buffer}(\mathcal{S}, d) \neq \emptyset\}\]
Applications: Find all buildings within 100 m of a road; extract land parcels intersecting a 500 m riparian buffer.
Socket chain: VECTOR → VECTOR (buffer) → VECTOR (clip overlay) + VECTOR (clip input) → VECTOR (result).
Pattern 2: Attribute Select-Transform (Select by Attribute → Field Calculator)
Structure: A selection node filters features by attribute expression; the field calculator derives new columns from existing ones on the filtered subset.
Applications: Select parcels with area > 500 m² and compute floor area ratio using "building_area" / "parcel_area".
Pattern 3: Spatial Join-Aggregate
Structure: A spatial join (intersects/contains) pairs features from two layers; a dissolve or statistics node aggregates the joined attributes by group.
Applications: Count buildings per land-use parcel; compute total road length per administrative district.
Pattern 4: Raster-Mask Extract
Structure: A vector-to-raster conversion produces a binary mask; a raster calculator multiplies the mask against a continuous raster to extract values within the mask region.
Applications: Extract elevation values within a watershed boundary; compute NDVI statistics for forested areas only.
Pattern 5: Multi-Criteria Overlay
Structure: Multiple reclassified raster layers are combined through weighted linear combination, producing a suitability surface.
Mathematical foundation: The weighted linear combination for \(m\) criteria layers:
\[S(x, y) = \sum_{i=1}^{m} w_i \cdot r_i(x, y) \quad \text{with} \quad \sum_{i=1}^{m} w_i = 1, \; w_i \geq 0\]
where \(r_i(x, y)\) is the reclassified value of criterion \(i\) at cell \((x, y)\).
Socket chain: Multiple RASTER inputs → RASTER (calculator) → RASTER (result).
Interpretation Guide: Workflow Design Principles
1. Prefer typed connections over literal values. When an input can be supplied either as a connected output or as a literal parameter, connecting it from upstream promotes reproducibility: changing the upstream data automatically propagates through the workflow. Literal parameters should be reserved for constants (thresholds, buffer distances, classification counts) that genuinely do not depend on other data.
2. Design for inspectability. Every intermediate node that produces a layer-type output can be published as a workflow output for inspection. This is particularly valuable for debugging: temporarily publish an intermediate buffer result to verify the proximity zone before applying it as a clip mask. In production, unpublish debugging outputs to keep the final result list clean.
3. Use the Smart Proposal Bar for exploration. The deterministic proposal engine surfaces algorithms you might not know exist. Selecting a raster node may reveal GDAL-based operations that accomplish in one step what would otherwise require a manual chain. The proposal bar is most effective when you select a node with multiple output types (e.g., a Processing algorithm that outputs both a vector layer and a statistics table).
4. Version workflows as .sm3 files. The SmartModeler JSON v3 format is designed for version control: it is deterministic (sorted keys, stable node IDs), human-readable, and diff-friendly. Commit .sm3 files alongside analysis scripts to document the exact workflow that produced published results.
5. Validate before running large workflows. Use the graph validation (automatic on Run) to catch missing inputs, incompatible connections, and cycle errors before execution. The validation issues list is specifically designed to be actionable: each issue includes the node ID and a human-readable message.
Agent Integration Patterns
When the Agent Workspace is used to assist workflow construction, two additional patterns become available:
6. Inspection-Assembly Pattern. The user asks the agent to list_layers and algorithm_help, building a shared understanding of the available data and tools. The agent proposes a model_patch that the user reviews on the approval card before applying. The assembled graph is then run through the Studio’s deterministic execution engine—not through the agent’s processing_run path. This keeps execution under the Studio’s direct control while leveraging the agent for initial layout.
7. Iterative Refinement Pattern. The user builds a rough workflow manually, runs it, inspects the output, then asks the agent for improvement suggestions. The agent uses current_model to read the existing graph structure, proposes targeted model_patch edits (add a normalization step, change a buffer distance), and the user reviews each edit individually. This pattern combines the user’s domain knowledge with the agent’s ability to recall less commonly used algorithms.
Literature
Kahn, A.B. (1962). Topological sorting of large networks. Communications of the ACM, 5(11), 558–562. DOI: 10.1145/368996.369025
Gamma, E., Helm, R., Johnson, R. & Vlissides, J. (1994). Design Patterns: Elements of Reusable Object-Oriented Software. Addison-Wesley.
Dobesova, Z. (2020). Visual programming for GIS applications. In J.P. Wilson (ed.), Geographic Information Science & Technology Body of Knowledge (1st Quarter 2020 ed.). DOI: 10.22224/gistbok/2020.1.7
Dobesova, Z. (2020). Evaluation of effective cognition for the QGIS Processing Modeler. Applied Sciences, 10(4), 1446. DOI: 10.3390/app10041446
Dobesova, Z. & Dobes, P. (2014). Differences in visual programming for GIS. Applied Mechanics and Materials, 519–520, 353–356. DOI: 10.4028/www.scientific.net/AMM.519-520.353
Nardi, B.A. (1993). A Small Matter of Programming: Perspectives on End User Computing. MIT Press. DOI: 10.7551/mitpress/6270.001.0001
Shneiderman, B. (1983). Direct manipulation: A step beyond programming languages. IEEE Computer, 16(8), 57–69. DOI: 10.1109/MC.1983.1654471
Graser, A. & Olaya, V. (2015). Processing: A Python framework for the seamless integration of geoprocessing tools in QGIS. ISPRS International Journal of Geo-Information, 4(4), 2219–2245. DOI: 10.3390/ijgi4042219
Hua, W. et al. (2024). TrustAgent: Towards safe and trustworthy LLM-based agents. In Findings of the ACL: EMNLP 2024, pp. 10563–10580. DOI: 10.18653/v1/2024.findings-emnlp.585
Johnston, W.M., Hanna, J.R.P. & Millar, R.J. (2004). Advances in dataflow programming languages. ACM Computing Surveys, 36(1), 1–34. DOI: 10.1145/1013208.1013209
Graph-Theoretical Formulation
Topological Ordering by Kahn’s Algorithm
The Workflow Studio’s execution engine computes the node execution order using Kahn’s algorithm (Kahn, 1962), a classic \(O(|N| + |E|)\) method for topological sorting of directed acyclic graphs. The algorithm operates by repeatedly removing source nodes (nodes with in-degree zero) from the graph, updating the in-degrees of their successors, and adding newly eligible nodes to a processing queue.
Algorithm (Kahn, 1962). Given a DAG \(G = (N, E)\):
- Compute the in-degree \(d_{\text{in}}(n)\) for every node \(n \in N\) by counting incoming edges \(|\{e \in E : e.\text{target} = n\}|\).
- Initialize a queue \(Q\) with all nodes where \(d_{\text{in}}(n) = 0\).
- While \(Q\) is not empty: remove a node \(n\) from \(Q\), append it to the sorted order \(\mathcal{O}\), and for each outgoing edge \((n, n')\), decrement \(d_{\text{in}}(n')\); if \(d_{\text{in}}(n')\) reaches zero, enqueue \(n'\).
- If \(|\mathcal{O}| < |N|\), the graph contains a cycle—reject the graph.
SmartModeler’s implementation (GraphModel.get_topological_order) extends Kahn’s algorithm with two additional constraint types beyond explicit edges: declarative dependencies (where node A declares a dependency on node B without a direct edge, used for conditional branch ordering) and duplicate dependency detection (which catches configuration errors where a node lists the same dependency twice). The in-degree computation integrates both edge-based and declarative dependencies:
\[d_{\text{in}}(n) = |\{e \in E : e.\text{end\_node} = n\}| + |\text{unique}(n.\text{dependencies})|\]
where \(\text{unique}(\cdot)\) deduplicates the dependency list and rejects self-dependencies (node.dependencies containing its own node_id).
Cycle Detection
Before establishing a new edge \((n_i, n_j)\), the graph model performs a reachability test to determine whether \(n_i\) is already reachable from \(n_j\). Let \(R(n)\) be the set of nodes reachable from \(n\) via directed edges and declarative dependencies. A proposed edge \((n_i, n_j)\) creates a cycle if and only if \(n_i \in R(n_j)\). The reachability test uses breadth-first search from \(n_j\) with early termination on encountering \(n_i\):
\[R(n_j) = \{n \in N : \exists \text{ path } n_j \rightsquigarrow n \text{ in } G\}\]
This test executes in \(O(|N| + |E|)\) worst-case time but typically terminates much earlier because GIS workflows tend to be shallow (median depth of 3–5 nodes in the micro-package gallery). The edge is rejected with the message “This connection would create a cycle” if the test detects \(n_i \in R(n_j)\).
Socket Compatibility as a Formal Language
The 12 socket types define an alphabet \(\Sigma = \{\text{VECTOR}, \text{RASTER}, \ldots, \text{ANY}\}\). The compatibility relation \(\sim \subseteq \Sigma \times \Sigma\) is:
\[\sigma_1 \sim \sigma_2 \iff (\sigma_1 = \sigma_2) \lor (\text{ANY} \in \{\sigma_1, \sigma_2\})\]
This relation is reflexive (every type is compatible with itself), symmetric (if A is compatible with B then B is compatible with A because of ANY), but not transitive: VECTOR is compatible with ANY, and ANY is compatible with RASTER, but VECTOR is not compatible with RASTER. The graph model enforces this at edge creation time (validate_connection), and the Smart Proposal engine uses the compatibility relation to compute a ranked set of candidate algorithms whose input ports accept the selected node’s output types.
The proposal scoring function for a candidate algorithm \(a \in \mathcal{A}\) given a selected node \(n_s\) is:
\[\text{score}(a, n_s) = \sum_{p_{\text{out}} \in \text{outputs}(n_s)} \sum_{p_{\text{in}} \in \text{inputs}(a)} \mathbf{1}[\tau(p_{\text{out}}) \sim \tau(p_{\text{in}})]\]
where \(\mathbf{1}[\cdot]\) is the indicator function. Algorithms with higher scores are ranked first because they can consume more of the selected node’s outputs in a single connection step.
Graph Validation Complexity
The complete graph validation pipeline (GraphModel.validate()) runs in \(O(|N| + |E|)\) time for the topological sort, plus \(O(|N| \cdot |\text{inputs}| + |\text{outputs}|)\) for per-node parameter checks. Typical workflows with 20–50 nodes and 30–80 edges validate in under 10 milliseconds on commodity hardware—fast enough to run interactively during graph editing. The validation produces a list of GraphIssue objects, each with a severity level (error or warning), a human-readable message keyed to the user’s locale, and the affected node ID for direct canvas navigation.
Literature
Kahn, A.B. (1962). Topological sorting of large networks. Communications of the ACM, 5(11), 558–562. DOI: 10.1145/368996.369025
Gamma, E., Helm, R., Johnson, R. & Vlissides, J. (1994). Design Patterns: Elements of Reusable Object-Oriented Software. Addison-Wesley.
Graser, A. & Olaya, V. (2015). Processing: A Python framework for the seamless integration of geoprocessing tools in QGIS. ISPRS International Journal of Geo-Information, 4(4), 2219–2245. DOI: 10.3390/ijgi4042219
Dobesova, Z. (2020). Evaluation of effective cognition for the QGIS Processing Modeler. Applied Sciences, 10(4), 1446. DOI: 10.3390/app10041446
Hua, W. et al. (2024). TrustAgent: Towards safe and trustworthy LLM-based agents. In Findings of the ACL: EMNLP 2024, pp. 10563–10580. DOI: 10.18653/v1/2024.findings-emnlp.585
OSM Data Acquisition Algorithms
Theoretical Background: The OpenStreetMap Data Model
OpenStreetMap (OSM) is the largest and most extensively studied volunteered geographic information (VGI) project, representing a paradigm shift from authoritative, state-produced geospatial data to collaborative, crowd-sourced mapping (Goodchild, 2007). As of 2026, OSM contains over 10 billion GPS points, 100 million ways, and 1 million relations contributed by more than 10 million registered users. The project’s data model is profoundly different from traditional GIS formats: it is a tag-based, schema-less topological model where geographic features are described by arbitrary key-value pairs rather than by a fixed attribute schema (Haklay & Weber, 2008).
The OSM data model comprises three geometric primitives:
- Nodes: Points with latitude and longitude coordinates (WGS84). Nodes represent point features (trees, bus stops, amenities) and serve as the vertices of ways.
- Ways: Ordered sequences of nodes (2–2000 nodes). Ways represent linear features (roads, rivers, boundaries) when open, and area features (buildings, parks, lakes) when closed (first node equals last node).
- Relations: Multi-element groupings that model complex geometries (multipolygons with holes, routes, turn restrictions). A relation references nodes, ways, and other relations as members, each with an optional role string.
Tags are free-form key=value pairs attached to any element. The OSM community maintains a de facto schema through the wiki-based Map Features convention, where commonly used keys (e.g., highway, building, natural, landuse, amenity) have documented value enumerations. However, any key=value pair is syntactically valid. This schema-less design is both a strength (enabling organic community-driven classification) and a challenge: tag completeness and semantic consistency vary dramatically across regions and feature types (Mooney & Minghini, 2017; Yeboah et al., 2021).
The Overpass API Architecture
The Overpass API (Olbricht, 2015) is the de facto read-only query interface for OSM data. Unlike the main OSM API—which is designed for editing and returns only individual elements by ID—Overpass provides a spatial and thematic query language (Overpass QL) that can retrieve all elements matching a tag filter within a bounding polygon. SmartModeler uses Overpass as its sole data acquisition channel, with three application-owned mirrors providing failover resilience.
An Overpass query is structured as a declarative specification with four components:
- Output format declaration:
[out:json]requests JSON (default is XML). - Timeout guard:
[timeout:45]caps server processing to 45 seconds. - Query body: One or more statements specifying the element type, tag filter, and bounding box.
- Output action:
out tags geom;returns element tags and reconstructed geometry.
SmartModeler abstracts Overpass QL construction entirely: the user (or AI agent) supplies only a tag key, an optional tag value, and a map-canvas extent. The plugin constructs the complete query, executes it against three mirrors with automatic failover, validates the response payload against dimensional and feature-count limits, and reconstructs QGIS geometries with proper CRS transformation (WGS84 to project CRS).
Quality Considerations in OSM Data
OSM data quality is intrinsically heterogeneous. Neis and Zipf (2012) demonstrated that contribution activity follows a heavily skewed distribution: a small core of active mappers produces the majority of data. Barron, Neis, and Zipf (2014) developed an intrinsic quality framework based on contributor history, edit patterns, and geometric revision frequency—metrics that do not require an external reference dataset. For SmartModeler users, the practical implications are:
- Completeness varies by region and feature type. Urban road networks in European cities may exceed 90% completeness, while buildings in rural sub-Saharan Africa may be below 20% (Yeboah et al., 2021).
- Tagging consistency is not guaranteed. A feature tagged
highway=pathin one region may behighway=footwayin another. Cross-referencing the OSM wiki for the study area’s mapping conventions is recommended. - Thematic accuracy depends on local mapper expertise and imagery quality. Brazilian road data showed 58% of road axes lacking toponymy (name) information (Silva et al., 2020).
SmartModeler mitigates these issues through transparent exposure of all OSM tags as feature attributes. The tags_json field preserves the complete tag dictionary for every feature, enabling post-hoc filtering and quality assessment. The osm_id and osm_type fields provide traceability back to the source element for verification against the main OSM database.
Algorithm 1: Download OSM Points
Algorithm ID: smartmodeler:osm_download_points
Mathematical Formulation
Given a map-canvas extent \(\mathcal{E} = (\lambda_{\min}, \phi_{\min}, \lambda_{\max}, \phi_{\max})\) in the project CRS, a tag key \(k\), and an optional tag value \(v\), the algorithm:
- Reprojects the extent to WGS84: \(\mathcal{E}_{\text{WGS84}} = \mathcal{T}_{\text{CRS}\to\text{EPSG:4326}}(\mathcal{E})\). If the project CRS is undefined, WGS84 is assumed.
- Validates the bounding box using the approximate area formula: \[A \approx (\phi_{\max} - \phi_{\min}) \times 111.32 \times (\lambda_{\max} - \lambda_{\min}) \times 111.32 \times \cos\left(\frac{\phi_{\max} + \phi_{\min}}{2} \cdot \frac{\pi}{180}\right)\] where \(111.32\) km/degree is the approximate meridian arc length. The area must satisfy \(0 < A \leq 100\) km².
- Constructs the Overpass query \(Q\):
\[Q = \texttt{[out:json][timeout:45]; node}[\texttt{"}k\texttt{"}=\texttt{"}v\texttt{"}](\phi_{\min},\lambda_{\min},\phi_{\max},\lambda_{\max})\texttt{; out tags geom;}\]
When \(v\) is empty or
*, the value constraint is omitted (key-existence filter). - Posts \(Q\) to the primary Overpass endpoint with automatic failover across two mirror endpoints using QGIS’ proxy-aware
QgsBlockingNetworkRequest. - Validates the JSON response: elements list is present, feature count \(\leq 100{,}000\), payload size \(\leq 64\) MiB, and each element is a valid dictionary.
- Geometrically reconstructs each node element as a point feature at \((\text{lon}_i, \text{lat}_i)\) and transforms to the project CRS if different from WGS84.
- Populates 17 attribute fields per feature from the OSM tags, including
osm_id,osm_type,name, the matched key and value, and 10 commonly used thematic keys.
Parameters
| Parameter | ID | Type | Required | Default | Description |
|---|---|---|---|---|---|
| OSM tag key | KEY | String | Yes | — | The OSM tag key to filter by (e.g., amenity, natural, tourism). Must match ^[A-Za-z0-9_:.~-]{1,80}$. |
| OSM tag value | VALUE | String | No | Empty (*) | The OSM tag value to filter by (e.g., bench, tree). Empty or * matches any value (key-existence filter). Max 120 characters. |
| Download extent | EXTENT | Extent | Yes | — | The bounding box in the project CRS. Auto-populated from the current map canvas extent. Area ceiling: 100 km². |
| OSM result | OUTPUT | FeatureSink | Yes | Temp layer | Destination for the downloaded point features. Defaults to a temporary memory layer. |
Output Schema
| Field | Type | Description |
|---|---|---|
osm_id | String | Unique OSM element identifier (node ID). |
osm_type | String | OSM element type—always node for this algorithm. |
name | String | Feature name from the name tag, if present. |
osm_key | String | The query key used to filter results. |
osm_value | String | The matched tag value for the query key. |
building, highway, amenity, landuse, leisure, natural, public_transport, shop, tourism | String | Ten commonly used thematic OSM keys extracted directly from element tags. Empty if the key is not present. |
height | String | Feature height from the height tag (typically in meters). |
building_levels | String | Number of building levels from the building:levels tag. |
tags_json | String | Complete OSM tag dictionary as a compact JSON string (max 16,000 characters, sorted keys). Enables post-hoc analysis of all available tags. |
Interpretation Guide
Primary use case: Extracting point-of-interest (POI) data from OSM for urban analysis, environmental assessment, or infrastructure mapping. Common tag queries include:
| Analysis Goal | Key | Value | Expected Features |
|---|---|---|---|
| Public transport stops | public_transport | stop_position | Bus stops, tram stops, train stations (nodes) |
| Street furniture | amenity | bench | Benches, waste baskets, bicycle parking |
| Urban trees | natural | tree | Individual mapped trees (point features) |
| Tourism infrastructure | tourism | * | Hotels, museums, viewpoints, information boards |
| Food and beverage | amenity | restaurant | Restaurants, cafes, fast food, bars |
Best practices: (1) Always verify the output CRS matches the project CRS—the algorithm transforms WGS84 coordinates but the user should confirm the transformation is valid for the study area. (2) For comprehensive POI inventories, run multiple queries (one per amenity type) and merge the results. The tags_json field preserves all original tags for classification refinement. (3) The 100 km² area limit ensures reasonable response times and server load; for larger study areas, use a tiled approach or download regional OSM extracts. (4) Nodes that are part of ways (e.g., intersection nodes) are also matched if they carry the queried tags; filter by osm_type if only standalone points are desired.
Limitations: The algorithm only returns OSM node elements. Point features encoded as closed ways (e.g., a building tagged amenity=school mapped as a building polygon) will not appear in the results. Use osm_download_polygons for area features. Tag values are returned as raw strings without normalization; values like yes, true, and 1 may represent the same semantic category across different mappers.
Literature
Goodchild, M.F. (2007). Citizens as sensors: The world of volunteered geography. GeoJournal, 69(4), 211–221. DOI: 10.1007/s10708-007-9111-y
Haklay, M. & Weber, P. (2008). OpenStreetMap: User-generated street maps. IEEE Pervasive Computing, 7(4), 12–18. DOI: 10.1109/MPRV.2008.80
Olbricht, R.M. (2015). Data retrieval for small spatial regions in OpenStreetMap. In J.J. Arsanjani, A. Zipf, P. Mooney & M. Helbich (eds.), OpenStreetMap in GIScience (pp. 101–122). Springer. DOI: 10.1007/978-3-319-14280-7_6
Neis, P. & Zipf, A. (2012). Analyzing the contributor activity of a volunteered geographic information project—The case of OpenStreetMap. ISPRS International Journal of Geo-Information, 1(2), 146–165. DOI: 10.3390/ijgi1020146
Mooney, P. & Minghini, M. (2017). A review of OpenStreetMap data. In G. Foody et al. (eds.), Mapping and the Citizen Sensor (pp. 37–59). Ubiquity Press. DOI: 10.5334/bbf.c
Barron, C., Neis, P. & Zipf, A. (2014). A comprehensive framework for intrinsic OpenStreetMap quality analysis. Transactions in GIS, 18(6), 877–895. DOI: 10.1111/tgis.12073
Yeboah, G. et al. (2021). Analysis of OpenStreetMap data quality at different stages of a participatory mapping process: Evidence from slums in Africa and Asia. ISPRS International Journal of Geo-Information, 10(4), 265. DOI: 10.3390/ijgi10040265
Graser, A. & Olaya, V. (2015). Processing: A Python framework for the seamless integration of geoprocessing tools in QGIS. ISPRS International Journal of Geo-Information, 4(4), 2219–2245. DOI: 10.3390/ijgi4042219
Staniek, M., Schumann, R., Züfle, M. & Riezler, S. (2024). Text-to-OverpassQL: A natural language interface for complex geodata querying of OpenStreetMap. Transactions of the Association for Computational Linguistics, 12, 562–575. DOI: 10.1162/tacl_a_00654
Silva, C.A.F. et al. (2020). The quality of OpenStreetMap in a large metropolis in northeast Brazil: Preliminary assessment of geospatial data for road axes. Boletim de Ciências Geodésicas, 26(3), e2020012. DOI: 10.1590/s1982-21702020000300012
Algorithm 2: Download OSM Lines
Algorithm ID: smartmodeler:osm_download_lines
Mathematical Formulation
Given the same input parameters as the point algorithm, the line download extends the query to OSM way elements. The Overpass query becomes:
\[Q_{\text{line}} = \texttt{[out:json][timeout:45]; way}[\texttt{"}k\texttt{"}=\texttt{"}v\texttt{"}](\phi_{\min},\lambda_{\min},\phi_{\max},\lambda_{\max})\texttt{; out tags geom;}\]
The critical geometric reconstruction step converts OSM way geometry (an ordered sequence of node coordinates) into a QGIS LineString. Let a way \(w\) be defined by its nodes \(\mathcal{N}_w = [n_1, n_2, \ldots, n_m]\) with coordinates \((\lambda_i, \phi_i)\) for each node. The reconstructed geometry is:
\[L_w = \text{LineString}((\lambda_1, \phi_1), (\lambda_2, \phi_2), \ldots, (\lambda_m, \phi_m))\]
A valid line requires \(m \geq 2\) nodes. Ways with fewer than 2 nodes are silently discarded. The geometric validation function \(\Gamma_{\text{line}} : \text{Element} \to \text{QgsGeometry} \cup \{\emptyset\}\) returns the constructed line or \(\emptyset\) if the element type is not way or the coordinate list is invalid.
After reconstruction, the line geometry is transformed to the project CRS if different from WGS84. The transformation \(\mathcal{T}_{\text{WGS84} \to \text{CRS}}\) uses QGIS’ coordinate transform context, which automatically applies the appropriate datum transformation grid. A transformation failure (non-zero return code) causes the feature to be silently skipped to avoid producing incorrectly positioned geometries.
Parameters
| Parameter | ID | Type | Required | Default | Description |
|---|---|---|---|---|---|
| OSM tag key | KEY | String | Yes | — | The OSM tag key to filter by (e.g., highway, waterway, railway). Must match ^[A-Za-z0-9_:.~-]{1,80}$. |
| OSM tag value | VALUE | String | No | Empty (*) | The OSM tag value to filter by. Empty or * matches any value. |
| Download extent | EXTENT | Extent | Yes | — | The bounding box in the project CRS. Area ceiling: 100 km². |
| OSM result | OUTPUT | FeatureSink | Yes | Temp layer | Destination for the downloaded line features. Geometry type: LineString. |
Interpretation Guide
The line algorithm is designed primarily for transportation network extraction but can retrieve any OSM data modeled as ways. Unlike the native QGIS QuickOSM plugin—which exposes the full Overpass QL editor—SmartModeler’s line downloader deliberately constrains the interface to a single key-value pair. This simplification serves two purposes: (1) it provides a safe, bounded surface for the AI agent’s osm_query tool, and (2) it reduces the risk of constructing queries that overload the Overpass servers.
| Analysis Domain | Key | Common Values | Output |
|---|---|---|---|
| Road network | highway | motorway, trunk, primary, secondary, residential, footway, cycleway, * | Complete classified road network as LineStrings |
| Waterways | waterway | river, stream, canal, drain | Hydrological network including water flow direction (way orientation) |
| Railways | railway | rail, subway, tram, light_rail | Rail network for accessibility and transit analysis |
| Boundaries | boundary | administrative | Administrative boundaries (may include closed ways representing areas) |
| Power lines | power | line, minor_line | Electricity transmission and distribution network |
Best practices: (1) For large road networks, query by individual highway class rather than highway=* to avoid hitting the 100,000 feature limit. The highway field in the output attribute table enables post-hoc filtering even with a wildcard query. (2) OSM ways are directed: the node order in a way encodes the digitization direction. For waterways, this corresponds to flow direction; for roads, it reflects the mapper’s digitization direction and may not correspond to traffic direction (which is encoded in the oneway tag accessible via tags_json). (3) Ways that form closed rings (first node = last node) with area-defining tags may represent area features rather than linear features. If the query key is typically used for areas (e.g., landuse), consider using the polygon algorithm instead.
Limitations: The algorithm does not perform topological network assembly. Ways that cross but do not share a common node will not be topologically connected in the output. OSM road networks are digitized along the centerline, not by lane; lane-level analysis requires additional processing (e.g., buffering by road width). Very long ways (those with more than 2000 nodes) are truncated by the Overpass API at the bounding box boundary; segments outside the extent are not returned.
Literature
Goodchild, M.F. (2007). Citizens as sensors: The world of volunteered geography. GeoJournal, 69(4), 211–221. DOI: 10.1007/s10708-007-9111-y
Haklay, M. & Weber, P. (2008). OpenStreetMap: User-generated street maps. IEEE Pervasive Computing, 7(4), 12–18. DOI: 10.1109/MPRV.2008.80
Olbricht, R.M. (2015). Data retrieval for small spatial regions in OpenStreetMap. In OpenStreetMap in GIScience (pp. 101–122). Springer. DOI: 10.1007/978-3-319-14280-7_6
Neis, P. & Zipf, A. (2012). Analyzing the contributor activity of a VGI project. ISPRS International Journal of Geo-Information, 1(2), 146–165. DOI: 10.3390/ijgi1020146
Mooney, P. & Minghini, M. (2017). A review of OpenStreetMap data. In Mapping and the Citizen Sensor (pp. 37–59). Ubiquity Press. DOI: 10.5334/bbf.c
Barron, C., Neis, P. & Zipf, A. (2014). A comprehensive framework for intrinsic OpenStreetMap quality analysis. Transactions in GIS, 18(6), 877–895. DOI: 10.1111/tgis.12073
Graser, A. & Olaya, V. (2015). Processing: A Python framework for geoprocessing tools in QGIS. ISPRS International Journal of Geo-Information, 4(4), 2219–2245. DOI: 10.3390/ijgi4042219
Staniek, M., Schumann, R., Züfle, M. & Riezler, S. (2024). Text-to-OverpassQL. Transactions of the Association for Computational Linguistics, 12, 562–575. DOI: 10.1162/tacl_a_00654
Silva, C.A.F. et al. (2020). The quality of OpenStreetMap in a large metropolis in northeast Brazil. Boletim de Ciências Geodésicas, 26(3), e2020012. DOI: 10.1590/s1982-21702020000300012
Jacobs, K.T. & Mitchell, S.W. (2020). OpenStreetMap quality assessment using unsupervised machine learning methods. Transactions in GIS, 24(5), 1280–1298. DOI: 10.1111/tgis.12680
Algorithm 3: Download OSM Polygons
Algorithm ID: smartmodeler:osm_download_polygons
Mathematical Formulation
The polygon algorithm is the most geometrically complex of the three. OSM area features can be represented as either closed ways (where the first and last nodes are identical) or multipolygon relations (where outer and inner member ways collectively define a region, possibly with holes). The algorithm handles both representations through a unified reconstruction pipeline.
Case 1: Closed Way. Let a way \(w\) with node sequence \(\mathcal{N}_w = [n_1, \ldots, n_m]\) be a closed ring if \(n_1 = n_m\). The geometry is constructed as a single-ring polygon:
\[P_w = \text{Polygon}([(\lambda_1, \phi_1), \ldots, (\lambda_m, \phi_m)])\]
A closed ring requires \(m \geq 4\) points (the starting point, at least two distinct vertices, and the closing point). Ways with fewer than 3 distinct coordinates cannot form a valid polygon and are discarded.
Case 2: Multipolygon Relation. Let a relation \(\mathcal{R}\) contain members \(\{m_1, \ldots, m_k\}\) where each member is a way with a role \(r_i \in \{\text{outer}, \text{inner}\}\). The geometry is constructed using set operations on the member geometries:
\[G_{\text{outer}} = \bigcup_{i: r_i = \text{outer}} \text{Polygon}(m_i)\]
\[G_{\text{inner}} = \bigcup_{j: r_j = \text{inner}} \text{Polygon}(m_j)\]
\[P_{\mathcal{R}} = G_{\text{outer}} \setminus G_{\text{inner}}\]
where \(\cup\) denotes geometric union (via QgsGeometry.unaryUnion) and \(\setminus\) denotes geometric difference. The algorithm uses QGIS’ native geometry engine (GEOS/C++) for these operations. After construction, the geometry is converted to multi-type to ensure consistent output across single and multi-polygon features: \(P_{\mathcal{R}} \to \text{MultiPolygon}\).
Query Construction (Polygon-Specific). The Overpass query for polygons differs from the point and line queries in two respects:
- Dual-element query: Both ways and relations are retrieved because an area feature may be modeled as either. The query uses a union block to combine the results: \[Q_{\text{poly}} = \texttt{[out:json][timeout:45]; (way}[\texttt{"}k\texttt{"}=\texttt{"}v\texttt{"}](\ldots)\texttt{; relation}[\texttt{"}k\texttt{"}=\texttt{"}v\texttt{"}](\ldots)\texttt{); out body geom;}\]
out body geomvsout tags geom: Thebodyqualifier requests member elements for relations (ways that form the outer and inner rings). Withoutbody, relation members would not be included in the response, making polygon reconstruction from relations impossible.
Parameters
| Parameter | ID | Type | Required | Default | Description |
|---|---|---|---|---|---|
| OSM tag key | KEY | String | Yes | — | The OSM tag key for area features (e.g., building, landuse, natural, leisure). |
| OSM tag value | VALUE | String | No | Empty (*) | The OSM tag value for filtering. Empty or * returns all features with the key. |
| Download extent | EXTENT | Extent | Yes | — | The bounding box. Area ceiling: 100 km². |
| OSM result | OUTPUT | FeatureSink | Yes | Temp layer | Destination for polygon features. Geometry type: MultiPolygon. |
Session Caching
All three OSM algorithms share a session-level response cache (_SESSION_CACHE) with a 15-minute TTL and a maximum of 6 cached queries. The cache key is the exact Overpass query string, enabling cache hits across repeated algorithm invocations with identical parameters. The cache is cleared when the TTL expires or when new queries displace the oldest entries (LRU eviction). This mechanism is particularly valuable for polygon downloads, which typically involve larger response payloads due to the body qualifier.
Interpretation Guide
The polygon algorithm is the primary tool for land-use, building footprint, and natural feature extraction. It handles the full complexity of OSM area modeling, including multipolygons with holes (e.g., a park with a lake, or a building with a courtyard).
| Analysis Domain | Key | Common Values | Typical Use |
|---|---|---|---|
| Building footprints | building | yes, residential, commercial, industrial, school, hospital, * | 3D city modeling, urban density analysis, building count estimation |
| Land use | landuse | residential, commercial, industrial, forest, farmland, grass | Land-use classification, urban growth modeling |
| Natural features | natural | water, wood, scrub, wetland, beach | Environmental assessment, habitat mapping |
| Recreation | leisure | park, pitch, playground, garden, sports_centre | Green space accessibility analysis |
| Amenities as areas | amenity | school, university, hospital, parking, place_of_worship | Facility service area analysis (areas, not points) |
Best practices: (1) Always inspect the osm_type field to distinguish between way-based and relation-based features. Relation-based features with complex inner/outer geometries may have subtle rendering issues at certain zoom levels. (2) For building footprint analysis, use building=* to capture all building types, then classify using the building attribute field. The building:levels and height attributes enable 3D extrusion for visualization in companion tools like planx_3d_city. (3) Overlapping polygons are common in OSM (e.g., a building inside a landuse area, or adjacent landuse polygons sharing a boundary but not being topologically clean). Post-processing with a small negative buffer followed by a positive buffer (Epsilon filter) can resolve minor sliver gaps. (4) Multipolygon relations with a large number of member ways (e.g., a complex coastline with 100+ outer way members) may exceed the Overpass response limits; zoom in or use regional extracts for such features.
Limitations: Area features that are tagged solely on nodes (e.g., a natural=tree node) or on unclosed ways are not captured. Relations whose member ways are not included in the Overpass response (e.g., when a relation spans beyond the bounding box and only some members intersect) may produce incomplete geometries; the algorithm checks for non-empty geometries before adding features. Very large relations (those with hundreds of members) increase download time proportionally to the number of member geometry requests.
Literature
Goodchild, M.F. (2007). Citizens as sensors: The world of volunteered geography. GeoJournal, 69(4), 211–221. DOI: 10.1007/s10708-007-9111-y
Haklay, M. & Weber, P. (2008). OpenStreetMap: User-generated street maps. IEEE Pervasive Computing, 7(4), 12–18. DOI: 10.1109/MPRV.2008.80
Olbricht, R.M. (2015). Data retrieval for small spatial regions in OpenStreetMap. In OpenStreetMap in GIScience (pp. 101–122). Springer. DOI: 10.1007/978-3-319-14280-7_6
Neis, P. & Zipf, A. (2012). Analyzing the contributor activity of a VGI project. ISPRS International Journal of Geo-Information, 1(2), 146–165. DOI: 10.3390/ijgi1020146
Mooney, P. & Minghini, M. (2017). A review of OpenStreetMap data. In Mapping and the Citizen Sensor (pp. 37–59). Ubiquity Press. DOI: 10.5334/bbf.c
Barron, C., Neis, P. & Zipf, A. (2014). A framework for intrinsic OSM quality analysis. Transactions in GIS, 18(6), 877–895. DOI: 10.1111/tgis.12073
Graser, A. & Olaya, V. (2015). Processing: A Python framework for geoprocessing tools in QGIS. ISPRS International Journal of Geo-Information, 4(4), 2219–2245. DOI: 10.3390/ijgi4042219
Arsanjani, J.J., Zipf, A., Mooney, P. & Helbich, M. (eds.) (2015). OpenStreetMap in GIScience: Experiences, Research, and Applications. Springer. DOI: 10.1007/978-3-319-14280-7
Yeboah, G. et al. (2021). OpenStreetMap data quality at different stages of participatory mapping. ISPRS International Journal of Geo-Information, 10(4), 265. DOI: 10.3390/ijgi10040265
Staniek, M., Schumann, R., Züfle, M. & Riezler, S. (2024). Text-to-OverpassQL. Transactions of the Association for Computational Linguistics, 12, 562–575. DOI: 10.1162/tacl_a_00654
Appendix A — Socket Types Reference
| Socket | Constant | Accepts From | Default QGIS Parameter Types |
|---|---|---|---|
| VECTOR | vector | VECTOR, ANY | QgsProcessingParameterFeatureSource, QgsProcessingParameterVectorLayer |
| RASTER | raster | RASTER, ANY | QgsProcessingParameterRasterLayer |
| NUMBER | number | NUMBER, ANY | QgsProcessingParameterNumber, QgsProcessingParameterDistance, QgsProcessingParameterArea |
| STRING | string | STRING, ANY | QgsProcessingParameterString, QgsProcessingParameterExpression |
| BOOLEAN | boolean | BOOLEAN, ANY | QgsProcessingParameterBoolean |
| FIELD | field | FIELD, STRING, ANY | QgsProcessingParameterField |
| TABLE | table | TABLE, ANY | QgsProcessingParameterFeatureSource (non-spatial) |
| FILE | file | FILE, STRING, ANY | QgsProcessingParameterFile |
| CRS | crs | CRS, ANY | QgsProcessingParameterCrs |
| EXTENT | extent | EXTENT, ANY | QgsProcessingParameterExtent |
| ENUM | enum | ENUM, NUMBER, STRING, ANY | QgsProcessingParameterEnum |
| ANY | any | Any type | Wildcard — used for generic pass-through |
Appendix B — Agent Tool Catalog
The live registry, as built by core/agent/runtime_tools.build_default_registry. Every one is READ_ONLY: no project mutation, no feature edit, no Processing execution, no plugin method invocation, no network access. Changing anything requires a validated proposal and your explicit click.
| Tool ID | Scope | Returns | Condition |
|---|---|---|---|
project.summary | Project | title, crs, layer_count | Always. The saved project path is never included. |
layer.list | Project | [{layer_id, name, kind, geometry_type, crs, visible, provider_key, active, area_safe_crs}] | Always |
layer.describe | One layer | {fields: [{name, field_type}], feature_count, resolved_by} | Exact id, or an exact unique name |
layer.field_values | One field of one layer | {numeric, minimum, maximum, mean, median, null_count, distinct_count, sample} | Ordering statistics only when every value is numeric |
layer.suggest_crs | One layer | {current_crs, current_crs_area_safe, suggestions: [{crs, description, reason}]} | Layer must have a locatable extent |
layer.style | One vector/raster | {renderer family, symbol summary, label state, context_token} | Always |
processing.search | Processing registry | [{algorithm_id, display_name, provider_id, agent_runnable}] | Bounded; runnable matches ranked first |
processing.describe | One algorithm | Live typed signature: params, kinds, bounds, enum options, proposal_binding, outputs, context_token | Always |
processing.resolve | One algorithm | Search + describe in one call, with the receipt a run proposal needs | Always |
expression.search | QGIS expressions | Live built-in help for a named function | Always |
model.summary | Studio graph | {nodes, edge_count, validation_issues} | Studio must be open |
model.describe | Studio graph | {nodes, edges, context_token} | Studio must be open |
model.validate | Studio graph | Validation issues | Studio must be open |
plugin.list | Plugins | Installed package names | Always |
plugin.describe | One plugin | Package metadata | Always |
plugin.capabilities | One plugin | {provider_id, algorithms: [{id, runnable}], reviewed actions} | Plugin must be installed and enabled |
database.list 🔒 | Connections | Connections by opaque token — never a URI or credential | Power Mode |
database.describe 🔒 | One connection | Schemas, tables, column metadata | Power Mode |
script.list 🔒 | Trusted scripts | [{script_id, name, script_hash}] | Power Mode |
script.describe 🔒 | One script | Full source for review | Power Mode |
workspace.list | Workspace root | Plugin source files | Workspace (Developer) scope |
workspace.read | One file | File contents | Workspace (Developer) scope |
workspace.inspect | Workspace | Diagnostic state | Workspace (Developer) scope |
workspace.search | Workspace | Source search results | Workspace (Developer) scope |
workspace.command | Workspace | One reviewed safe diagnostic command | Workspace (Developer) scope |
Appendix C — Glossary
| Agent Workspace | The dockable AI chat panel with read-only inspection tools and a validated proposal system. |
| DAG | Directed Acyclic Graph — the underlying data structure of a SmartModeler workflow. Cycles are rejected at edge-creation time. |
| Fail-closed | A security principle: when validation cannot confirm correctness, the operation is rejected rather than proceeding with potentially dangerous state. |
| Fence response | A valid empty provider turn where the AI declined to answer (fence: true). Not an error — the agent is choosing not to engage. |
| .model3 | QGIS Model Designer's native file format. SmartModeler imports and exports it, preserving all parameter types and model metadata. |
| Plan Mode | Agent mode where proposals are review-only. No changes can be made to QGIS. Used for exploration and discussion. |
| Act Mode | Agent mode where proposals produce approval cards. The user must explicitly click Apply to commit any change. |
| Power Mode | Opt-in capability set (off by default) that includes SQL, trusted scripts, and generated PyQGIS. |
| Processing run | Execution of one QGIS Processing algorithm through the Agent Workspace. Results go to temporary layers only — no user-selected destinations. |
| Socket type | The semantic type of a node port (VECTOR, RASTER, NUMBER, etc.). Determines which connections are valid. |
| Smart Proposal | Deterministic, offline next-step suggestion based on output-to-input socket type matching across the algorithm registry. |
| Workflow Studio | The full-window visual canvas for building and editing Processing workflows. |
Appendix D — Extended Bibliography
Volunteered Geographic Information & OpenStreetMap
Goodchild, M.F. (2007). Citizens as sensors: The world of volunteered geography. GeoJournal, 69(4), 211–221. DOI: 10.1007/s10708-007-9111-y
Haklay, M. & Weber, P. (2008). OpenStreetMap: User-generated street maps. IEEE Pervasive Computing, 7(4), 12–18. DOI: 10.1109/MPRV.2008.80
Olbricht, R.M. (2015). Data retrieval for small spatial regions in OpenStreetMap. In J.J. Arsanjani, A. Zipf, P. Mooney & M. Helbich (eds.), OpenStreetMap in GIScience (pp. 101–122). Springer. DOI: 10.1007/978-3-319-14280-7_6
Neis, P. & Zipf, A. (2012). Analyzing the contributor activity of a volunteered geographic information project—The case of OpenStreetMap. ISPRS International Journal of Geo-Information, 1(2), 146–165. DOI: 10.3390/ijgi1020146
Mooney, P. & Minghini, M. (2017). A review of OpenStreetMap data. In G. Foody et al. (eds.), Mapping and the Citizen Sensor (pp. 37–59). Ubiquity Press. DOI: 10.5334/bbf.c
Barron, C., Neis, P. & Zipf, A. (2014). A comprehensive framework for intrinsic OpenStreetMap quality analysis. Transactions in GIS, 18(6), 877–895. DOI: 10.1111/tgis.12073
Yeboah, G. et al. (2021). Analysis of OpenStreetMap data quality at different stages of a participatory mapping process: Evidence from slums in Africa and Asia. ISPRS International Journal of Geo-Information, 10(4), 265. DOI: 10.3390/ijgi10040265
Arsanjani, J.J., Zipf, A., Mooney, P. & Helbich, M. (eds.) (2015). OpenStreetMap in GIScience: Experiences, Research, and Applications. Springer. DOI: 10.1007/978-3-319-14280-7
Staniek, M., Schumann, R., Züfle, M. & Riezler, S. (2024). Text-to-OverpassQL: A natural language interface for complex geodata querying of OpenStreetMap. Transactions of the Association for Computational Linguistics, 12, 562–575. DOI: 10.1162/tacl_a_00654
Silva, C.A.F. et al. (2020). The quality of OpenStreetMap in a large metropolis in northeast Brazil: Preliminary assessment of geospatial data for road axes. Boletim de Ciências Geodésicas, 26(3), e2020012. DOI: 10.1590/s1982-21702020000300012
Jacobs, K.T. & Mitchell, S.W. (2020). OpenStreetMap quality assessment using unsupervised machine learning methods. Transactions in GIS, 24(5), 1280–1298. DOI: 10.1111/tgis.12680
Workflow Automation & Visual Programming for GIS
Kahn, A.B. (1962). Topological sorting of large networks. Communications of the ACM, 5(11), 558–562. DOI: 10.1145/368996.369025
Gamma, E., Helm, R., Johnson, R. & Vlissides, J. (1994). Design Patterns: Elements of Reusable Object-Oriented Software. Addison-Wesley.
Graser, A. & Olaya, V. (2015). Processing: A Python framework for the seamless integration of geoprocessing tools in QGIS. ISPRS International Journal of Geo-Information, 4(4), 2219–2245. DOI: 10.3390/ijgi4042219
Dobesova, Z. (2020). Visual programming for GIS applications. In J.P. Wilson (ed.), Geographic Information Science & Technology Body of Knowledge (1st Quarter 2020 ed.). UCGIS. DOI: 10.22224/gistbok/2020.1.7
Dobesova, Z. (2020). Evaluation of effective cognition for the QGIS Processing Modeler. Applied Sciences, 10(4), 1446. DOI: 10.3390/app10041446
Dobesova, Z. & Dobes, P. (2014). Differences in visual programming for GIS. Applied Mechanics and Materials, 519–520, 353–356. DOI: 10.4028/www.scientific.net/AMM.519-520.353
Nardi, B.A. (1993). A Small Matter of Programming: Perspectives on End User Computing. MIT Press. DOI: 10.7551/mitpress/6270.001.0001
Shneiderman, B. (1983). Direct manipulation: A step beyond programming languages. IEEE Computer, 16(8), 57–69. DOI: 10.1109/MC.1983.1654471
Johnston, W.M., Hanna, J.R.P. & Millar, R.J. (2004). Advances in dataflow programming languages. ACM Computing Surveys, 36(1), 1–34. DOI: 10.1145/1013208.1013209
QGIS Development Team. (2024). QGIS Processing Framework. docs.qgis.org
QGIS Development Team. (2024). QGIS Graphical Modeler. docs.qgis.org
AI-Assisted Planning & Agent Safety
Hua, W. et al. (2024). TrustAgent: Towards safe and trustworthy LLM-based agents. In Findings of the Association for Computational Linguistics: EMNLP 2024, pp. 10563–10580. DOI: 10.18653/v1/2024.findings-emnlp.585
Anthropic. (2024). “Tool Use (Function Calling).” Anthropic API Documentation.
OpenAI. (2024). “Function Calling Guide.” OpenAI API Documentation.
Anwar, M.R. & Sakti, L.D. (2024). Integrating artificial intelligence and environmental science for sustainable urban planning. IAIC Transactions on Sustainable Digital Innovation, 5(2), 179–191. DOI: 10.34306/itsdi.v5i2.666
Fauzi, C. (2024). A review geospatial artificial intelligence (Geo-AI): Implementation of machine learning on urban planning. In Proceedings of iCAST-ES 2023 (pp. 311–329). Atlantis Press. DOI: 10.2991/978-94-6463-364-1_30
Zhou, T. (2023). Application of artificial intelligence in geography. Journal of Physics: Conference Series, 2646, 012006. DOI: 10.1088/1742-6596/2646/1/012006