# sarahgoel/satquery-ai architecture

> Architecture diagram of the GitHub repository sarahgoel/satquery-ai, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-09-27). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/sarahgoel/satquery-ai
- Repository: https://github.com/sarahgoel/satquery-ai

## Overview

SatQuery AI is an analyst-facing Earth-observation assistant: users submit natural-language questions with GeoTIFF scenes, then receive mapped analysis results and auditable traces. The documented workflow parses raster metadata, checks spatial alignment, classifies intent, dispatches to temporal, cross-modal, grounding, or VQA analysis, and records execution evidence. The graph preserves these documented capability branches; source excerpts are partial, so uncertain internal calls are omitted. README-documented PostGIS persistence and UI capabilities are included.

Main entry points: [`backend/app/services/agent.py`](https://github.com/sarahgoel/satquery-ai/blob/main/backend/app/services/agent.py) (Analysis controller), [`frontend/src/pages/GeospatialAnalysis.jsx`](https://github.com/sarahgoel/satquery-ai/blob/main/frontend/src/pages/GeospatialAnalysis.jsx) (Analysis workspace), [`backend/app/tools/registry.py`](https://github.com/sarahgoel/satquery-ai/blob/main/backend/app/tools/registry.py) (Analysis tool registry), [`backend/api/routes.py`](https://github.com/sarahgoel/satquery-ai/blob/main/backend/api/routes.py) (Query endpoint)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_ui["Analyst console"]
  node_workspace["Analysis workspace"]
  node_composer["Query and uploads<br/>[QueryComposer.jsx]"]
  node_map["Map results<br/>[MapViewer.jsx]"]
  node_traceui["Trace viewer<br/>[TraceViewer.jsx]"]
  node_reports["Report export"]
end

subgraph group_api["Request orchestration"]
  node_queryapi["Query endpoint<br/>[routes.py]"]
  node_controller["Analysis controller<br/>[agent.py]"]
  node_router["Intent router<br/>[semantic_router.py]"]
end

subgraph group_analysis["EO analysis"]
  node_parser["Raster metadata parser<br/>[parser.py]"]
  node_alignment["Spatial alignment<br/>[alignment.py]"]
  node_tools["Analysis tool registry<br/>[registry.py]"]
  node_temporal["Temporal change<br/>[temporal_change.py]"]
  node_crossmodal["Cross-modal analysis<br/>[cross_modal.py]"]
  node_grounding["Feature grounding"]
  node_geovector["Raster vectorization<br/>[vector.py]"]
  node_spectral["Spectral products<br/>[spectral.py]"]
  node_vqa["EO VQA models<br/>[rs_vlm.py]"]
  node_changevqa["Change VQA model<br/>[change_vqa.py]"]
  node_fusion["Sensor fusion model<br/>[fusion.py]"]
end

subgraph group_audit["Trace and persistence"]
  node_trace["Execution trace store<br/>[trace_store.py]"]
  node_db[("PostGIS database<br/>[session.py]")]
end

node_analyst(("EO analyst"))
node_ollama["Ollama serving"]

node_analyst -->|"uses"| node_workspace
node_workspace -->|"collects query"| node_composer
node_composer -->|"submits scenes"| node_queryapi
node_queryapi -->|"starts analysis"| node_controller
node_controller -->|"parses rasters"| node_parser
node_controller -->|"validates overlap"| node_alignment
node_controller -->|"classifies intent"| node_router
node_router -.->|"requests routing"| node_ollama
node_controller -->|"dispatches tools"| node_tools
node_tools -->|"runs change analysis"| node_temporal
node_tools -->|"runs joint analysis"| node_crossmodal
node_tools -->|"localizes features"| node_grounding
node_tools -->|"answers image query"| node_vqa
node_temporal -->|"uses model"| node_changevqa
node_crossmodal -->|"uses model"| node_fusion
node_grounding -->|"vectorizes masks"| node_geovector
node_controller -->|"computes indices"| node_spectral
node_controller -->|"records execution"| node_trace
node_trace -->|"persists traces"| node_db
node_queryapi -->|"returns analysis"| node_workspace
node_workspace -->|"shows overlays"| node_map
node_workspace -->|"shows trace"| node_traceui
node_workspace -->|"exports report"| node_reports

click node_workspace "https://github.com/sarahgoel/satquery-ai/blob/main/frontend/src/pages/GeospatialAnalysis.jsx"
click node_composer "https://github.com/sarahgoel/satquery-ai/blob/main/frontend/src/components/geospatial/QueryComposer.jsx"
click node_map "https://github.com/sarahgoel/satquery-ai/blob/main/frontend/src/components/MapViewer.jsx"
click node_traceui "https://github.com/sarahgoel/satquery-ai/blob/main/frontend/src/components/TraceViewer.jsx"
click node_reports "https://github.com/sarahgoel/satquery-ai/blob/main/frontend/src/components/ReportDownloader.jsx"
click node_queryapi "https://github.com/sarahgoel/satquery-ai/blob/main/backend/api/routes.py"
click node_controller "https://github.com/sarahgoel/satquery-ai/blob/main/backend/app/services/agent.py"
click node_parser "https://github.com/sarahgoel/satquery-ai/blob/main/backend/app/services/geospatial/parser.py"
click node_alignment "https://github.com/sarahgoel/satquery-ai/blob/main/backend/app/services/geospatial/alignment.py"
click node_router "https://github.com/sarahgoel/satquery-ai/blob/main/backend/app/agents/semantic_router.py"
click node_tools "https://github.com/sarahgoel/satquery-ai/blob/main/backend/app/tools/registry.py"
click node_temporal "https://github.com/sarahgoel/satquery-ai/blob/main/backend/app/services/analytical/temporal_change.py"
click node_crossmodal "https://github.com/sarahgoel/satquery-ai/blob/main/backend/app/services/analytical/cross_modal.py"
click node_grounding "https://github.com/sarahgoel/satquery-ai/blob/main/backend/app/services/grounding_service.py"
click node_geovector "https://github.com/sarahgoel/satquery-ai/blob/main/backend/app/services/geospatial/vector.py"
click node_spectral "https://github.com/sarahgoel/satquery-ai/blob/main/backend/app/services/geospatial/spectral.py"
click node_vqa "https://github.com/sarahgoel/satquery-ai/blob/main/backend/app/services/models/rs_vlm.py"
click node_changevqa "https://github.com/sarahgoel/satquery-ai/blob/main/backend/app/services/models/change_vqa.py"
click node_fusion "https://github.com/sarahgoel/satquery-ai/blob/main/backend/app/services/models/fusion.py"
click node_trace "https://github.com/sarahgoel/satquery-ai/blob/main/backend/app/utils/trace_store.py"
click node_db "https://github.com/sarahgoel/satquery-ai/blob/main/backend/app/database/session.py"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_workspace,node_composer,node_map,node_traceui,node_reports toneBlue
class node_queryapi,node_controller,node_router toneAmber
class node_parser,node_alignment,node_tools,node_temporal,node_crossmodal,node_grounding,node_geovector,node_spectral,node_vqa,node_changevqa,node_fusion toneMint
class node_trace,node_db toneRose
class node_analyst,node_ollama toneIndigo
```

## Components

### Analyst console

- [Analysis workspace](https://github.com/sarahgoel/satquery-ai/blob/main/frontend/src/pages/GeospatialAnalysis.jsx): `frontend/src/pages/GeospatialAnalysis.jsx`
- [Query and uploads](https://github.com/sarahgoel/satquery-ai/blob/main/frontend/src/components/geospatial/QueryComposer.jsx): `frontend/src/components/geospatial/QueryComposer.jsx`
- [Map results](https://github.com/sarahgoel/satquery-ai/blob/main/frontend/src/components/MapViewer.jsx): `frontend/src/components/MapViewer.jsx`
- [Trace viewer](https://github.com/sarahgoel/satquery-ai/blob/main/frontend/src/components/TraceViewer.jsx): `frontend/src/components/TraceViewer.jsx`
- [Report export](https://github.com/sarahgoel/satquery-ai/blob/main/frontend/src/components/ReportDownloader.jsx): `frontend/src/components/ReportDownloader.jsx`

### Request orchestration

- [Query endpoint](https://github.com/sarahgoel/satquery-ai/blob/main/backend/api/routes.py): `backend/api/routes.py`
- [Analysis controller](https://github.com/sarahgoel/satquery-ai/blob/main/backend/app/services/agent.py): `backend/app/services/agent.py`
- [Intent router](https://github.com/sarahgoel/satquery-ai/blob/main/backend/app/agents/semantic_router.py): `backend/app/agents/semantic_router.py`

### EO analysis

- [Raster metadata parser](https://github.com/sarahgoel/satquery-ai/blob/main/backend/app/services/geospatial/parser.py): `backend/app/services/geospatial/parser.py`
- [Spatial alignment](https://github.com/sarahgoel/satquery-ai/blob/main/backend/app/services/geospatial/alignment.py): `backend/app/services/geospatial/alignment.py`
- [Analysis tool registry](https://github.com/sarahgoel/satquery-ai/blob/main/backend/app/tools/registry.py): `backend/app/tools/registry.py`
- [Temporal change](https://github.com/sarahgoel/satquery-ai/blob/main/backend/app/services/analytical/temporal_change.py): `backend/app/services/analytical/temporal_change.py`
- [Cross-modal analysis](https://github.com/sarahgoel/satquery-ai/blob/main/backend/app/services/analytical/cross_modal.py): `backend/app/services/analytical/cross_modal.py`
- [Feature grounding](https://github.com/sarahgoel/satquery-ai/blob/main/backend/app/services/grounding_service.py): `backend/app/services/grounding_service.py`
- [Raster vectorization](https://github.com/sarahgoel/satquery-ai/blob/main/backend/app/services/geospatial/vector.py): `backend/app/services/geospatial/vector.py`
- [Spectral products](https://github.com/sarahgoel/satquery-ai/blob/main/backend/app/services/geospatial/spectral.py): `backend/app/services/geospatial/spectral.py`
- [EO VQA models](https://github.com/sarahgoel/satquery-ai/blob/main/backend/app/services/models/rs_vlm.py): `backend/app/services/models/rs_vlm.py`
- [Change VQA model](https://github.com/sarahgoel/satquery-ai/blob/main/backend/app/services/models/change_vqa.py): `backend/app/services/models/change_vqa.py`
- [Sensor fusion model](https://github.com/sarahgoel/satquery-ai/blob/main/backend/app/services/models/fusion.py): `backend/app/services/models/fusion.py`

### Trace and persistence

- [Execution trace store](https://github.com/sarahgoel/satquery-ai/blob/main/backend/app/utils/trace_store.py): `backend/app/utils/trace_store.py`
- [PostGIS database](https://github.com/sarahgoel/satquery-ai/blob/main/backend/app/database/session.py): `backend/app/database/session.py`

### Other components

- **EO analyst**
- **Ollama serving**

## Connections

- EO analyst → Analysis workspace: uses
- Analysis workspace → Query and uploads: collects query
- Query and uploads → Query endpoint: submits scenes
- Query endpoint → Analysis controller: starts analysis
- Analysis controller → Raster metadata parser: parses rasters
- Analysis controller → Spatial alignment: validates overlap
- Analysis controller → Intent router: classifies intent
- Intent router → Ollama serving: requests routing
- Analysis controller → Analysis tool registry: dispatches tools
- Analysis tool registry → Temporal change: runs change analysis
- Analysis tool registry → Cross-modal analysis: runs joint analysis
- Analysis tool registry → Feature grounding: localizes features
- Analysis tool registry → EO VQA models: answers image query
- Temporal change → Change VQA model: uses model
- Cross-modal analysis → Sensor fusion model: uses model
- Feature grounding → Raster vectorization: vectorizes masks
- Analysis controller → Spectral products: computes indices
- Analysis controller → Execution trace store: records execution
- Execution trace store → PostGIS database: persists traces
- Query endpoint → Analysis workspace: returns analysis
- Analysis workspace → Map results: shows overlays
- Analysis workspace → Trace viewer: shows trace
- Analysis workspace → Report export: exports report
