A multi-agent AI system for monitoring, analyzing, and predicting Harmful Algal Blooms (HABs) across German lakes. Agents communicate via Google's A2A (Agent-to-Agent) protocol, making them independently deployable and interoperable.
+-----------------+
| Orchestrator | :10000
| (A2A Server) |
+--------+--------+
|
+--------------+--------------+
| | |
+--------v--+ +------v-----+ +-----v------+
| HOMOGEN | | CALIBRO | | VISIOS |
| :10001 | | :10002 | | :10003 |
+-----+------+ +------+-----+ +-----+------+
| | |
+--------+---------+--------------+
|
+-----v------+
| PREDIKT |
| :10004 |
+------------+
Pipeline stages: HOMOGEN (harmonize data) -> CALIBRO + VISIOS (parallel) -> PREDIKT (forecast) -> Risk Fusion
| Agent | Role |
|---|---|
| HOMOGEN | Harmonizes raw lake data from CSV, Excel, and API sources into standardized parquet |
| CALIBRO | Calibrates Sentinel-2 satellite data for chlorophyll-a and turbidity indices |
| VISIOS | Detects HABs visually from lake images using EXIF metadata and color analysis |
| PREDIKT | Predicts bloom probability using ensemble ML (Random Forest + Gradient Boosting) |
| Orchestrator | Chains agents via A2A, fuses results into calibrated risk scores |
- Python 3.10+
- A Google Gemini API key
# Clone and install
git clone <repo-url> && cd ERAY_HEIDELBERG
pip install -r requirements.txt
# Configure environment
cp .env.example .env
# Edit .env and set GEMINI_API_KEYOption A: All agents via A2A (recommended)
python -m swim.launcherThis starts all 5 A2A servers (HOMOGEN, CALIBRO, VISIOS, PREDIKT, Orchestrator) on ports 10000-10004.
Option B: CLI for a single lake
python main.py --lake Bodensee --horizon 7 --a2aOption C: REST API
python -m swim.api.endpoints
# Then:
curl -X POST http://localhost:8000/pipeline \
-H "Content-Type: application/json" \
-d '{"location": {"lake": "Bodensee"}, "horizon_days": 7}'Option D: Streamlit dashboard
streamlit run streamlit_app.py| Endpoint | Method | Auth | Description |
|---|---|---|---|
/ |
GET | No | Service info |
/health |
GET | No | Health check |
/metrics |
GET | No | Prometheus metrics |
/lakes |
GET | No | List available lakes |
/drift |
GET | No | Data drift detection status |
/errors |
GET | No | Error tracking summary |
/predict |
POST | Yes | Single-lake prediction |
/pipeline |
POST | Yes | Full SWIM pipeline |
/auth/token |
POST | Yes | Generate JWT token |
/rag/upload |
POST | Yes | Upload document to knowledge base (PDF/TXT/CSV) |
/rag/query |
POST | Yes | Query RAG knowledge base |
/rag/stats |
GET | Yes | Knowledge base statistics |
Set SWIM_API_KEYS (comma-separated) and/or SWIM_JWT_SECRET in .env. When neither is set, auth is disabled (dev mode).
# API key
curl -H "X-API-Key: your-key" http://localhost:8000/predict ...
# JWT
curl -H "Authorization: Bearer <token>" http://localhost:8000/predict ...cd docker
docker compose up --buildServices: orchestrator (:10000), homogen (:10001), calibro (:10002), visios (:10003), predikt (:10004).
swim/
agents/
homogen/ # Data harmonization agent
calibro/ # Satellite calibration agent
visios/ # Visual image analysis agent
predikt/ # ML prediction agent
orchestrator/ # A2A orchestrator + risk fusion
main_agent/ # Direct-call controller (non-A2A)
api/ # FastAPI REST gateway
cli/ # Command-line interface
data_processing/ # ETL, cleaning, drift detection
observability/ # Structured logging, metrics, error tracking
rag/ # RAG knowledge base (embeddings, retrievers, file ingestion)
shared/ # Auth, config, paths, alerting, rate limiting
utils/ # Visualization, file management helpers
workflows/ # Per-agent workflow definitions
data/
raw/ # Raw source data
harmonized/ # Standardized parquet output
reference/ # Static lookup tables (geocoding, etc.)
external/ # Large third-party datasets — see data/external/README.md
db/ # SQLAlchemy models, schema, ingestion
config/ # Environment settings + schema ontology
deployment/ # Kubernetes manifests, Prometheus config
docker/ # Dockerfiles + compose
docs/ # Architecture, metrics, PROVENANCE.md
notebooks/ # Research notebooks (results retracted — see PROVENANCE.md)
scripts/ # Utilities, incl. audit_data_provenance.py
tests/ # Unit tests (133 passing)
models/ # Trained model artifacts (.pkl, git-ignored)
config.yaml # Central configuration
- A2A Protocol: Each agent is a standalone A2A server with its own AgentCard, discoverable at
/.well-known/agent.json - Risk Fusion: Multi-strategy probability extraction, precision-weighted combination, and uncertainty quantification that propagates inter-agent disagreement. Note: the isotonic calibrator requires ≥20 outcome-labelled samples to fit and falls back to a fixed heuristic curve without them — in the absence of ground-truth outcomes it has never actually been calibrated.
- Data Drift Detection: KS test + PSI against a stored training reference; on drift the forecast widens its own uncertainty rather than blocking. Known defects are tracked in
docs/PROVENANCE.md. - Prometheus Metrics:
/metricsendpoint with request counts, latencies, active pipelines, risk gauges - Security: JWT + API key auth, per-IP rate limiting, input sanitization (prompt injection, SQL injection, XSS)
- Alerting: Email + Slack notifications on critical risk levels
- SQLite Persistence: Pipeline run history, agent memory, task tracking
- RAG Knowledge Base: Document upload (PDF/TXT/CSV), vector embeddings (Google GenAI + fallback TF-IDF), cosine-similarity retrieval, and automatic context injection into agent queries at orchestration time. Built-in retrievers for EU/German water quality policy, climate data, and historical reports
Central config in config.yaml. Environment variables override config values:
| Variable | Purpose |
|---|---|
GEMINI_API_KEY |
Google Gemini LLM key (required) |
SWIM_API_KEYS |
API key auth for REST gateway |
SWIM_JWT_SECRET |
JWT signing secret |
SWIM_LLM_MODEL |
Override LLM model |
SWIM_LOG_LEVEL |
Log level (INFO/DEBUG) |
PREDIKT_MODEL_TYPE |
ensemble / lstm / sarima / rule_based |
pip install pytest pytest-asyncio
pytest tests/ -v| Lake | Region | Trophic Status |
|---|---|---|
| Bodensee | Baden-Wurttemberg/Bavaria | Oligotrophic |
| Chiemsee | Bavaria | Mesotrophic |
| Starnberger See | Bavaria | Oligotrophic |
| Ammersee | Bavaria | Mesotrophic |
| Muritz | Mecklenburg-Vorpommern | Eutrophic |
SWIM serves as the engineering testbed for research on "Agentic AI for Multi-Modal Earth Observation" — investigating whether specialized, communicating agents outperform monolithic models for environmental monitoring.
The Phase 1–3 predictive results previously reported here (AUROC 0.814 all-features, 0.850 satellite-only, the feature-dropout robustness curves, the agentic-vs-monolithic comparison, and the
p < 0.05significance tests) are retracted. They are not valid measurements.The research notebooks were developed against synthetic stand-in data, and the real sources held in this repository were never substituted in before those numbers were written up. A provenance audit found the stand-in labels internally inconsistent (categorical bloom status statistically independent of bloom probability; 1,240 "probabilities" greater than 1; label uncorrelated with cyanobacteria density at r = −0.013), the satellite metadata physically impossible (112 configurations, incl. Sentinel-2 reporting surface temperature — it carries no thermal instrument), and the satellite join duplicating each observation ~3.5× across the train/test boundary.
Full analysis: docs/PROVENANCE.md · Reproduce:
python scripts/audit_data_provenance.pyThe platform engineering, the A2A architecture, and the Sentinel-2 extraction code (NDWI/NDCI from L2A via Earth Engine) are unaffected. The real data needed to run the study properly is present — see below.
| RQ | Question | Status |
|---|---|---|
| RQ1 | Does agent specialization improve robustness under sensor failure? | Open — awaiting valid data |
| RQ2 | Does inter-agent communication improve predictions? | Open — awaiting valid data |
| RQ3 | How should the orchestrator resolve agent conflicts? | Open — awaiting valid data |
| Source | Scale |
|---|---|
| EEA Bathing Water Directive 1990–2023 | 2,074 German lake bathing sites · 53,289 site-years · real coordinates · 1,856 sites with ≥15 yrs |
| LUBW Baden-Württemberg water quality | Real state agency monitoring export |
| GEMStat / UN GEMS-Water | Real station series with quality flags |
| Sentinel-2 L2A via Earth Engine | NDWI, NDCI, turbidity proxy — retrievable per site coordinate |
Planned design, and its stated limitations, in docs/PROVENANCE.md.
Research notebooks: notebooks/research_package/ — retained for method reference only; their reported metrics are invalid.
See docs/PROGRESS.md for engineering progress.
MIT