Technology Stack

Complete inventory of technologies powering the AESOP platform, organized by architectural layer and service ownership.

Shared (all services) aesop_intell aesop_modelisation aesop_simulation LAYER 5 — FRONTEND HTMX Server-rendered HTML WebSocket (Channels) LAYER 4 — GEOSPATIAL H3 Hexagonal Tiling django-leaflet Leaflet.js LAYER 3 — FRAMEWORKS Django 5.x Django REST Framework Django Channels Daphne LAYER 2 — PROCESSING Celery Workers sentence-transformers NumPy / SciPy Mistral AI / Anthropic LAYER 1 — INFRASTRUCTURE PostgreSQL Redis Apache AGE ext. pgvector ext. MarkItDown processes runs on renders delivers MODELISATION-SPECIFIC Propagation Algorithms (custom)

Full Dependency Inventory

Technology Version Service(s) Purpose Limitation / Note
PostgreSQL 16.x All Primary relational database for all three services Requires AGE and pgvector extensions compiled separately
Apache AGE 1.5.x All Graph database extension for PostgreSQL; stores actor/relationship networks Must match PostgreSQL major version; not available in managed cloud PostgreSQL
pgvector 0.7.x intell Vector similarity search for semantic embeddings IVFFlat index requires periodic retraining; HNSW index uses more memory
Redis 7.x All Celery broker, cache backend, Channels layer Single-threaded; large simulation payloads may bottleneck
MarkItDown latest intell Converts uploaded documents (PDF, DOCX, PPTX) to Markdown for LLM ingestion Microsoft library; quality varies by document complexity
Django 5.1.x All Web framework, ORM, admin, authentication Synchronous ORM; async views available but ORM calls still block
Django REST Framework 3.15.x All REST API serialization, viewsets, inter-service HTTP calls Adds overhead vs raw Django views for internal-only APIs
Django Channels 4.x simulation WebSocket support for real-time simulation turn updates Requires Daphne or uvicorn ASGI server instead of gunicorn
Daphne 4.x simulation ASGI server for Django Channels WebSocket connections Less battle-tested than gunicorn for pure HTTP workloads
Celery 5.4.x All Distributed task queue: OSINT pipelines, propagation, turn execution Task chains can stall if a worker crashes mid-chain; no built-in resumption
sentence-transformers 3.x intell Generate text embeddings for semantic search and deduplication Model loading is slow (~2s cold start); keep worker warm
NumPy / SciPy 1.26.x / 1.13.x simulation Matrix operations for influence scoring and propagation calculations Large matrices may require chunking for memory-constrained environments
Mistral AI API intell LLM for entity extraction, summarization, and analytical briefs Rate-limited; no local fallback; API costs scale with volume
Anthropic (Claude) API intell Alternative LLM provider for analysis tasks Same cloud-dependency constraints as Mistral
H3 4.x (h3-py) All Uber's hexagonal hierarchical spatial index; zone tiling and neighbor queries Hex edges cause slight area distortion at poles; not an issue at operational latitudes
django-leaflet 0.30.x All Django integration for Leaflet map widgets Tightly coupled to Leaflet version; must keep in sync
Leaflet.js 1.9.x All Interactive map rendering in the browser Tile provider required (OpenStreetMap default); no offline mode without tile cache
HTMX 2.x All Declarative AJAX: partial page updates without a JS framework Complex client-side state (drag-and-drop, rich editors) still needs vanilla JS
Propagation Algorithms custom modelisation Cascade influence propagation across graph networks Custom implementation; no external library — must be maintained in-house

Key Technology Choices

Why Apache AGE?

Apache AGE adds openCypher graph queries directly inside PostgreSQL. This eliminates the need for a separate Neo4j server, reducing operational complexity from two database engines to one. Actor networks, influence relationships, and faction hierarchies are modeled as graph vertices and edges while still joining against relational tables (scenarios, turns, zones) in the same transaction.

  • + Single database process to operate, back up, and monitor
  • + ACID transactions span both relational and graph data
  • - Not available on managed PostgreSQL (AWS RDS, Cloud SQL)
  • - Smaller ecosystem than Neo4j; fewer query optimizations

Why H3 Hexagonal Tiling?

Uber's H3 system tiles the globe into hexagonal cells at multiple resolutions. Unlike square grids, hexagons provide uniform adjacency (every cell has exactly 6 neighbors at equal distance), making influence propagation calculations symmetric and predictable.

  • + Uniform area per cell — no latitude distortion like square grids
  • + Built-in multi-resolution: zoom from country-level (res 3) to city-block (res 9)
  • + Fast neighbor ring calculations via h3.grid_ring()
  • ~ Pentagons exist at each resolution (12 total) but never at operational latitudes

Why Celery for Simulation?

The AESOP simulation engine runs in discrete turns, where each turn involves multiple sequential phases (OODA loop: Observe, Orient, Decide, Act). Celery task chains model this naturally: each phase is a task, chained so output flows to the next. Long-running propagation calculations execute on worker processes without blocking the Django web server.

  • + Task chains model OODA phases as sequential steps
  • + Horizontal scaling: add workers for heavier simulation loads
  • + Redis broker shared with Django cache — no extra infrastructure
  • - No built-in task resumption if a worker crashes mid-chain

Why HTMX over React?

AESOP's UI is server-rendered with Django templates. HTMX adds dynamic behavior (partial updates, form submissions, lazy loading) through HTML attributes rather than a JavaScript framework. This avoids a separate JS build pipeline, keeps the team in Python/Django, and reduces client-side complexity.

  • + No Node.js, no webpack/vite, no npm dependencies
  • + Django templates remain the single source of truth for UI
  • + Progressive enhancement: pages work without JavaScript
  • - Rich client interactions (map overlays, drag-drop) still need vanilla JS

Why Django Channels for Simulation?

The multiplayer simulation requires real-time push to all connected players when a turn resolves. HTTP polling would introduce latency and unnecessary load. Django Channels provides WebSocket support within the Django ecosystem, using the same authentication, middleware, and ORM. When a Celery task completes a turn, it publishes the result to a Channels group, and every connected player receives the update instantly.

  • + Native Django integration — same auth, same session, same ORM
  • + Channel groups map naturally to simulation rooms
  • + Celery workers can publish directly to channel layers via Redis
  • - Requires Daphne ASGI server instead of standard gunicorn
  • - WebSocket connection scaling needs careful Redis channel-layer tuning
Service color coding: Technologies colored purple are shared infrastructure used by all three AESOP services. Blue technologies are exclusive to aesop_intell (intelligence/OSINT), green to aesop_modelisation (MIDAS graph modeling), and amber to aesop_simulation (multiplayer wargame). This mapping drives deployment decisions: only the simulation server needs Daphne, only the intell service needs GPU-capable workers for embeddings.