# Dexorder AI Platform Architecture

## Overview

Dexorder is an AI-powered trading platform that combines real-time market data processing, user-specific AI agents, and a flexible data pipeline. The system is designed for scalability, isolation, and extensibility.

## High-Level Architecture

```
┌─────────────────────────────────────────────────────────────────┐
│                         User Clients                             │
│              (Web, Mobile, Telegram, External MCP)               │
└────────────────────────────┬────────────────────────────────────┘
                             │
                             ▼
┌─────────────────────────────────────────────────────────────────┐
│                          Gateway                                 │
│  • WebSocket/HTTP/Telegram handlers                             │
│  • Authentication & session management                           │
│  • Agent Harness (LangChain/LangGraph orchestration)            │
│    - MCP client connector to user containers                    │
│    - RAG retriever (Qdrant)                                     │
│    - Model router (LLM selection)                               │
│    - Skills & subagents framework                               │
│  • Dynamic user container provisioning                           │
│  • Event routing (informational & critical)                      │
└────────┬──────────────────┬────────────────────┬────────────────┘
         │                  │                    │
         ▼                  ▼                    ▼
┌──────────────────┐  ┌──────────────┐   ┌──────────────────────┐
│ User Containers  │  │    Relay     │   │   Infrastructure     │
│ (per-user pods)  │  │ (ZMQ Router) │   │ • DragonflyDB (cache)│
│                  │  │              │   │ • Qdrant (vectors)   │
│ • MCP Server     │  │ • Market data│   │ • PostgreSQL (meta)  │
│ • User files:    │  │   fanout     │   │ • MinIO (S3)         │
│   - Indicators   │  │ • Work queue │   │                      │
│   - Strategies   │  │ • Stateless  │   │                      │
│   - Preferences  │  │              │   │                      │
│ • Event Publisher│  │              │   │                      │
│ • Lifecycle Mgmt │  │              │   │                      │
└──────────────────┘  └──────┬───────┘   └──────────────────────┘
                             │
              ┌──────────────┴──────────────┐
              │                             │
              ▼                             ▼
    ┌──────────────────┐        ┌──────────────────────┐
    │   Ingestors      │        │    Flink Cluster     │
    │ • CCXT adapters  │        │ • Deduplication      │
    │ • Exchange APIs  │        │ • OHLC aggregation   │
    │ • Push to Kafka  │        │ • CEP engine         │
    └────────┬─────────┘        │ • Writes to Iceberg  │
             │                  │ • Market data PUB    │
             │                  └──────────┬───────────┘
             ▼                             │
    ┌─────────────────────────────────────▼────────────┐
    │                    Kafka                          │
    │  • Durable append log                            │
    │  • Topic-based streams                           │
    │  • Event sourcing                                │
    └──────────────────────┬───────────────────────────┘
                           │
                           ▼
                  ┌─────────────────┐
                  │ Iceberg Catalog │
                  │ • Historical    │
                  │   OHLC storage  │
                  │ • Query API     │
                  └─────────────────┘
```

## Core Components

### 1. Gateway

**Location:** `gateway/`
**Language:** TypeScript (Node.js)
**Purpose:** Entry point for all user interactions

**Responsibilities:**
- **Authentication:** JWT tokens, Telegram OAuth, multi-tier licensing
- **Session Management:** WebSocket connections, Telegram webhooks, multi-channel support
- **Container Orchestration:** Dynamic provisioning of user agent pods ([[gateway_container_creation]])
- **Event Handling:**
  - Subscribe to user container events (XPUB/SUB for informational)
  - Route critical events (ROUTER/DEALER with ack) ([[user_container_events]])
- **Agent Harness (LangChain/LangGraph):** ([[agent_harness]])
  - Stateless LLM orchestration
  - MCP client connector to user containers
  - RAG retrieval from Qdrant (global + user-specific knowledge)
  - Model routing based on license tier and complexity
  - Skills and subagents framework
  - Workflow state machines with validation loops

**Key Features:**
- **Stateless design:** All conversation state lives in user containers or Qdrant
- **Multi-channel support:** WebSocket, Telegram (future: mobile, Discord, Slack)
- **Kubernetes-native:** Uses k8s API for container management
- **Three-tier memory:**
  - Redis: Hot storage, active sessions, LangGraph checkpoints (1 hour TTL)
  - Qdrant: Vector search, RAG, global + user knowledge, GDPR-compliant
  - Iceberg: Cold storage, full history, analytics, time-travel queries

**Infrastructure:**
- Deployed in `dexorder-system` namespace
- RBAC: Can create but not delete user containers
- Network policies: Access to k8s API, user containers, infrastructure

---

### 2. User Containers

**Location:** `sandbox/`
**Language:** Python
**Purpose:** Per-user isolated workspace and data storage

**Architecture:**
- One pod per user (auto-provisioned by gateway)
- Persistent storage (PVC) for user data
- Multi-container pod:
  - **Agent container:** MCP server + event publisher + user files
  - **Lifecycle sidecar:** Auto-shutdown and cleanup

**Components:**

#### MCP Server
Exposes user-specific resources and tools via Model Context Protocol.

**Resources (Context for LLM):**
Gateway fetches these before each LLM call:
- `context://user-profile` - Trading preferences, style, risk tolerance
- `context://conversation-summary` - Recent conversation with semantic context
- `context://workspace-state` - Current chart, watchlist, positions, alerts
- `context://system-prompt` - User's custom AI instructions

**Tools (Actions with side effects):**
Gateway proxies these to user's MCP server:
- `save_message(role, content)` - Save to conversation history
- `search_conversation(query)` - Semantic search over past conversations
- `list_strategies()`, `read_strategy(name)`, `write_strategy(name, code)`
- `list_indicators()`, `read_indicator(name)`, `write_indicator(name, code)`
- `run_backtest(strategy, params)` - Execute backtest
- `get_watchlist()`, `execute_trade(params)`, `get_positions()`
- `run_python(code)` - Execute Python with data science libraries

**User Files:**
- `indicators/*.py` - Custom technical indicators
- `strategies/*.py` - Trading strategies with entry/exit rules
- Watchlists and preferences
- Git-versioned in persistent volume

#### Event Publisher ([[user_container_events]])
Publishes user events (order fills, alerts, workspace changes) via dual-channel ZMQ:
- **XPUB:** Informational events (fire-and-forget to active sessions)
- **DEALER:** Critical events (guaranteed delivery with ack)

#### Lifecycle Manager ([[container_lifecycle_management]])
Tracks activity and triggers; auto-shuts down when idle:
- Configurable idle timeouts by license tier
- Exit code 42 signals intentional shutdown
- Sidecar deletes deployment and optionally PVC

**Isolation:**
- Network policies: Cannot access k8s API, other users, or system services
- PodSecurity: Non-root, read-only rootfs, dropped capabilities
- Resource limits enforced by license tier

---

### 3. Data Pipeline

#### Relay (ZMQ Router)

**Location:** `relay/`
**Language:** Rust
**Purpose:** Stateless message router for market data and requests

**Architecture:**
- Well-known bind point (all components connect to it)
- No request tracking or state
- Topic-based routing

**Channels:**
1. **Client Requests (ROUTER):** Port 5559 - Historical data requests
2. **Ingestor Work Queue (PUB):** Port 5555 - Work distribution with exchange prefix
3. **Market Data Fanout (XPUB/XSUB):** Port 5558 - Realtime data + notifications
4. **Responses (SUB → PUB proxy):** Notifications from Flink to clients

See [[protocol]] for detailed ZMQ patterns and message formats.

---

#### Ingestors

**Location:** `ingestor/`
**Language:** Python
**Purpose:** Fetch market data from exchanges

**Features:**
- CCXT-based exchange adapters
- Subscribes to work queue via exchange suffix (e.g., `.BINANCE`)
- Writes raw data to Kafka only (no direct client responses)
- Supports realtime ticks and historical OHLC

**Data Flow:**
```
Exchange API → Ingestor → Kafka → Flink → Iceberg
                                      ↓
                                  Notification → Relay → Clients
```

---

#### Kafka

**Deployment:** KRaft mode (no Zookeeper)
**Purpose:** Durable event log and stream processing backbone

**Topics:**
- Raw market data streams (per exchange/symbol)
- Processed OHLC data
- Notification events
- User events (orders, alerts)

**Retention:**
- Configurable per topic (default: 7 days for raw data)
- Longer retention for aggregated data

---

#### Flink

**Deployment:** JobManager + TaskManager(s)
**Purpose:** Stream processing and aggregation

**Jobs:**
1. **Deduplication:** Remove duplicate ticks from multiple ingestors
2. **OHLC Aggregation:** Build candles from tick streams
3. **CEP (Complex Event Processing):** Pattern detection and alerts
4. **Iceberg Writer:** Batch write to long-term storage
5. **Notification Publisher:** ZMQ PUB for async client notifications

**State:**
- Checkpointing to MinIO (S3-compatible)
- Exactly-once processing semantics

**Scaling:**
- Multiple TaskManagers for parallelism
- Headless service for ZMQ discovery (see [[protocol#TODO: Flink-to-Relay ZMQ Discovery]])

---

#### Apache Iceberg

**Deployment:** REST catalog with PostgreSQL backend
**Purpose:** Historical data lake for OHLC and analytics

**Features:**
- Schema evolution
- Time travel queries
- Partitioning by date/symbol
- Efficient columnar storage (Parquet)

**Storage:** MinIO (S3-compatible object storage)

---

### 4. Infrastructure Services

#### DragonflyDB
- Redis-compatible in-memory cache
- Session state, rate limiting, hot data

#### Qdrant
- Vector database for RAG
- **Global knowledge** (user_id="0"): Platform capabilities, trading concepts, strategy patterns
- **User knowledge** (user_id=specific): Personal conversations, preferences, strategies
- GDPR-compliant (indexed by user_id for fast deletion)

#### PostgreSQL
- Iceberg catalog metadata
- User accounts and license info (gateway)
- Per-user data lives in user containers

#### MinIO
- S3-compatible object storage
- Iceberg table data
- Flink checkpoints
- User file uploads

---

## Data Flow Patterns

### Historical Data Query (Async)

```
1. Client → Gateway → User Container MCP: User requests data
2. Gateway → Relay (REQ/REP): Submit historical request
3. Relay → Ingestors (PUB/SUB): Broadcast work with exchange prefix
4. Ingestor → Exchange API: Fetch data
5. Ingestor → Kafka: Write OHLC batch with metadata
6. Flink → Kafka: Read, process, dedupe
7. Flink → Iceberg: Write to table
8. Flink → Relay (PUB): Publish HistoryReadyNotification
9. Relay → Client (SUB): Notification delivered
10. Client → Iceberg: Query data directly
```

**Key Design:**
- Client subscribes to notification topic BEFORE submitting request (prevents race)
- Notification topics are deterministic: `RESPONSE:{client_id}` or `HISTORY_READY:{request_id}`
- No state in Relay (fully topic-based routing)

See [[protocol#Historical Data Query Flow]] for details.

---

### Realtime Market Data

```
1. Ingestor → Kafka: Write realtime ticks
2. Flink → Kafka: Read and aggregate OHLC
3. Flink → Relay (PUB): Publish market data
4. Relay → Clients (XPUB/SUB): Fanout to subscribers
```

**Topic Format:** `{ticker}|{data_type}` (e.g., `BTC/USDT.BINANCE|tick`)

---

### User Events

User containers emit events (order fills, alerts) that must reach users reliably.

**Dual-Channel Design:**

1. **Informational Events (XPUB/SUB):**
   - Container tracks active subscriptions via XPUB
   - Publishes only if someone is listening
   - Zero latency, fire-and-forget

2. **Critical Events (DEALER/ROUTER):**
   - Container sends to gateway ROUTER with event ID
   - Gateway delivers via Telegram/email/push
   - Gateway sends EventAck back to container
   - Container retries on timeout
   - Persisted to disk on shutdown

See [[user_container_events]] for implementation.

---

## Container Lifecycle

### Creation ([[gateway_container_creation]])

```
User authenticates → Gateway checks if deployment exists
                  → If missing, create from template (based on license tier)
                  → Wait for ready (2min timeout)
                  → Return MCP endpoint
```

**Templates by Tier:**
| Tier | Memory | CPU | Storage | Idle Timeout |
|------|--------|-----|---------|--------------|
| Free | 512Mi | 500m | 1Gi | 15min |
| Pro | 2Gi | 2000m | 10Gi | 60min |
| Enterprise | 4Gi | 4000m | 50Gi | Never |

---

### Lifecycle Management ([[container_lifecycle_management]])

**Idle Detection:**
- Container is idle when: no active triggers + no recent MCP activity
- Lifecycle manager tracks:
  - MCP tool/resource calls (reset idle timer)
  - Active triggers (data subscriptions, CEP patterns)

**Shutdown:**
- On idle timeout: exit with code 42
- Lifecycle sidecar detects exit code 42
- Sidecar calls k8s API to delete deployment
- Optionally deletes PVC (anonymous users only)

**Security:**
- Sidecar has RBAC to delete its own deployment only
- Cannot delete other deployments or access other namespaces
- Gateway cannot delete deployments (separation of concerns)

---

## Security Architecture

### Network Isolation

**NetworkPolicies:**
- User containers:
  - ✅ Connect to gateway (MCP)
  - ✅ Connect to relay (market data)
  - ✅ Outbound HTTPS (exchanges, LLM APIs)
  - ❌ No k8s API access
  - ❌ No system namespace access
  - ❌ No inter-user communication

- Gateway:
  - ✅ k8s API (create containers)
  - ✅ User containers (MCP client)
  - ✅ Infrastructure (Postgres, Redis)
  - ✅ Outbound (Anthropic API)

---

### RBAC

**Gateway ServiceAccount:**
- Create deployments/services/PVCs in `sandbox` namespace
- Read pod status and logs
- Cannot delete, exec, or access secrets

**Lifecycle Sidecar ServiceAccount:**
- Delete deployments in `sandbox` namespace
- Delete PVCs (conditional on user type)
- Cannot access other resources

---

### Admission Control

All pods in `sandbox` namespace must:
- Use approved images only (allowlist)
- Run as non-root
- Drop all capabilities
- Use read-only root filesystem
- Have resource limits

See `deploy/k8s/base/admission-policy.yaml`

---

## Agent Harness Flow

The gateway's agent harness (LangChain/LangGraph) orchestrates LLM interactions with full context.

```
1. User sends message → Gateway (WebSocket/Telegram)
   ↓
2. Authenticator validates user and gets license info
   ↓
3. Container Manager ensures user's MCP container is running
   ↓
4. Agent Harness processes message:
   │
   ├─→ a. MCPClientConnector fetches context resources from user's MCP:
   │      - context://user-profile
   │      - context://conversation-summary
   │      - context://workspace-state
   │      - context://system-prompt
   │
   ├─→ b. RAGRetriever searches Qdrant for relevant memories:
   │      - Embeds user query
   │      - Searches: user_id IN (current_user, "0")
   │      - Returns user-specific + global platform knowledge
   │
   ├─→ c. Build system prompt:
   │      - Base platform prompt
   │      - User profile context
   │      - Workspace state
   │      - Custom user instructions
   │      - Relevant RAG memories
   │
   ├─→ d. ModelRouter selects LLM:
   │      - Based on license tier
   │      - Query complexity
   │      - Routing strategy (cost/speed/quality)
   │
   ├─→ e. LLM invocation with tool support:
   │      - Send messages to LLM
   │      - If tool calls requested:
   │         • Platform tools → handled by gateway
   │         • User tools → proxied to MCP container
   │      - Loop until no more tool calls
   │
   ├─→ f. Save conversation to MCP:
   │      - mcp.callTool('save_message', user_message)
   │      - mcp.callTool('save_message', assistant_message)
   │
   └─→ g. Return response to user via channel
```

**Key Architecture:**
- **Gateway is stateless:** No conversation history stored in gateway
- **User context in MCP:** All user-specific data lives in user's container
- **Global knowledge in Qdrant:** Platform documentation loaded from `gateway/knowledge/`
- **RAG at gateway level:** Semantic search combines global + user knowledge
- **Skills vs Subagents:**
  - Skills: Well-defined, single-purpose tasks
  - Subagents: Complex domain expertise with multi-file context
- **Workflows:** LangGraph state machines for multi-step processes

See [[agent_harness]] for detailed implementation.

---

## Configuration Management

All services use dual YAML files:
- `config.yaml` - Non-sensitive configuration (mounted from ConfigMap)
- `secrets.yaml` - Credentials and tokens (mounted from Secret)

**Environment Variables:**
- K8s downward API for pod metadata
- Service discovery via DNS (e.g., `kafka:9092`)

---

## Deployment

### Development

```bash
# Start local k8s
minikube start

# Apply infrastructure
kubectl apply -k deploy/k8s/dev

# Build and load images
docker build -t dexorder/gateway:latest gateway/
minikube image load dexorder/gateway:latest

# Port-forward for access
kubectl port-forward -n dexorder-system svc/gateway 3000:3000
```

---

### Production

```bash
# Apply production configs
kubectl apply -k deploy/k8s/prod

# Push images to registry
docker push ghcr.io/dexorder/gateway:latest
docker push ghcr.io/dexorder/sandbox:latest
docker push ghcr.io/dexorder/lifecycle-sidecar:latest
```

**Namespaces:**
- `dexorder-system` - Platform services (gateway, infrastructure)
- `sandbox` - User containers (isolated)

---

## Observability

### Metrics (Prometheus)
- Container creation/deletion rates
- Idle shutdown counts
- MCP call latency and errors
- Event delivery rates and retries
- Kafka lag and throughput
- Flink checkpoint duration

### Logging
- Structured JSON logs
- User ID in all agent logs
- Aggregated via Loki or CloudWatch

### Tracing
- OpenTelemetry spans across gateway → MCP → LLM
- User-scoped traces for debugging

---

## Scalability

### Horizontal Scaling

**Stateless Components:**
- Gateway: Add replicas behind load balancer
- Relay: Single instance (stateless router)
- Ingestors: Scale by exchange workload

**Stateful Components:**
- Flink: Scale TaskManagers
- User containers: One per user (1000s of pods)

**Bottlenecks:**
- Flink → Relay ZMQ: Requires discovery protocol (see [[protocol#TODO: Flink-to-Relay ZMQ Discovery]])
- Kafka: Partition by symbol for parallelism
- Iceberg: Partition by date/symbol

---

### Cost Optimization

**Tiered Resources:**
- Free users: Aggressive idle shutdown (15min)
- Pro users: Longer timeout (60min)
- Enterprise: Always-on containers

**Storage:**
- PVC deletion for anonymous users
- Tiered storage classes (fast SSD → cheap HDD)

**LLM Costs:**
- Rate limiting per license tier
- Caching of MCP resources (1-5min TTL)
- Conversation summarization to reduce context size

---

## Development Roadmap

See [[backend_redesign]] for detailed notes.

**Phase 1: Foundation (Complete)**
- Gateway with k8s integration
- User container provisioning
- MCP protocol implementation
- Basic market data pipeline

**Phase 2: Data Pipeline (In Progress)**
- Kafka topic schemas
- Flink jobs for aggregation
- Iceberg integration
- Historical backfill service

**Phase 3: Agent Features**
- RAG integration (Qdrant)
- Strategy backtesting
- Risk management tools
- Portfolio analytics

**Phase 4: Production Hardening**
- Multi-region deployment
- HA for infrastructure
- Comprehensive monitoring
- Performance optimization

---

## Related Documentation

- [[protocol]] - ZMQ message protocols and data flow
- [[gateway_container_creation]] - Dynamic container provisioning
- [[container_lifecycle_management]] - Idle shutdown and cleanup
- [[user_container_events]] - Event system implementation
- [[agent_harness]] - LLM orchestration flow
- [[m_c_p_tools_architecture]] - User MCP tools specification
- [[user_mcp_resources]] - Context resources and RAG
- [[m_c_p_client_authentication_modes]] - MCP authentication patterns
- [[backend_redesign]] - Design notes and TODO items
