NOTQIN IEIA (Industrial Energy Intelligence Agent)
1. Project Summary
An agentic AI system that investigates energy anomalies in Moroccan textile factories — cross-referencing siloed data sources (energy logs, maintenance records, shift schedules), computing real MAD-priced action scenarios using ONEE tariff rates, checking downstream cascade effects, and evaluating CBAM + buyer compliance. Not a chatbot — a reasoning agent that chooses its investigation path autonomously.
2. Architecture
React Frontend (Vite + Recharts)
│ POST /investigate (streaming SSE)
↓
FastAPI + Middleware (CORS, Helmet headers, JWT auth, rate-limiting)
│
↓
Claude API (anthropic SDK — multi-turn tool-use loop)
│ 8 agent tools
↓
┌─────────────────────────────────────────────────────────┐
│ Energy Data Tool → CSV (dev) / InfluxDB (prod) │
│ Maintenance Logs Tool → JSON source / PostgreSQL │
│ Schedule Data Tool → Shift schedules + ONEE periods │
│ Scenario Computation → YAML templates + safe_eval │
│ Downstream Effects Tool → Machine process dependencies │
│ Compliance Evaluator → CBAM + buyer (H&M, Inditex) │
│ Reliability Tool → Failure mode analysis, risk │
│ Report Generator → PDF/Excel export, audit trail │
└─────────────────────────────────────────────────────────┘
↓
PostgreSQL 16 (SQLAlchemy + Alembic)
├── investigations, production_runs, maintenance_logs
├── scenarios_computed, compliance_checks, audit_log
└── 10+ additional domain tables
Observability:
├── Prometheus client (HTTP metrics, rate-limit rejections, login attempts)
├── OpenTelemetry (distributed spans)
└── Structured JSON logs (error/warn/info/debug)
3. Real Tech Stack
| Layer | Technology |
|---|---|
| Language | Python 3.11+ |
| API Framework | FastAPI 0.115 |
| LLM | Claude API (Anthropic SDK — not LiteLLM) |
| Database | PostgreSQL 16 + SQLAlchemy + Alembic |
| Cache/State | Redis 5+ |
| Data | Pandas 2.1, PyYAML 6.0 |
| Streaming | sse-starlette 1.8 (Server-Sent Events) |
| Auth | PyJWT 2.8 + scrypt password hashing |
| Observability | Prometheus client + OpenTelemetry API/SDK |
| Testing | pytest 8 + in-memory SQLite |
| Frontend | React + Vite + Recharts |
Total backend: 151 Python files
4. What Is Built
The Agent Loop
The IEIA agent:
- Receives anomaly description from user (e.g., “MTX-007 consumption +23% in March”)
- Decides which data sources to query and in what order
- Queries energy logs → identifies pattern (gradual vs spike vs shift-correlated)
- Cross-references maintenance logs → finds “non-OEM bearing installed Feb 15”
- Checks schedule data → confirms peak-hour overlap
- Runs scenario computation → generates 3 MAD-priced options
- Checks downstream effects → warns that MTX-007 load shift affects dye cooling
- Evaluates compliance → flags CBAM exposure + H&M energy target breach risk
- Generates streamed reasoning via SSE → final PDF/Excel report
8 Agent Tools
| Tool | Function | Data Source |
|---|---|---|
query_energy_data | Energy readings per machine + period | CSV (dev) / InfluxDB (prod) |
query_maintenance_logs | Search maintenance history by machine/date | JSON / PostgreSQL |
query_schedule_data | Shift schedules, ONEE peak periods | Config/DB |
compute_scenarios | MAD-priced action scenarios (YAML templates) | root_causes.yaml |
check_downstream_effects | Machine→process dependency cascade | Config map |
evaluate_compliance | CBAM exposure + buyer targets | Regulatory config |
assess_reliability | Failure mode analysis, risk scoring | Failure taxonomy |
generate_report | PDF/Excel export | Report engine |
Scenario Template Engine
Root cause templates in backend/config/root_causes.yaml:
mechanical:
detection_hints: ["gradual drift", "bearing", "wear"]
scenario_template: "Immediate: ${replace_cost} MAD, Delay: ${delay_cost} MAD"
scheduling:
detection_hints: ["spike during 17–22h", "multiple machines"]
scenario_template: "Rebalance shifts: savings ${monthly_savings} MAD/month"Factory Data Model (Synthetic — Textile Mill)
- 8 looms (MTX-001 to MTX-008)
- ONEE tariff: ~0.80 MAD/kWh off-peak, ~1.20 MAD/kWh peak (17h–22h)
- Downtime cost: ~2,000 MAD/hour (lost production)
- CO₂ grid factor: ~0.5 tCO2/MWh (Morocco ONEE 2026)
- Dependencies: MTX-007→Dye Bath→Cooling→MTX-003 (cascade effects)
Demo Scenarios (Documented)
- Cement exporter (15,000t/year to Spain): Default CBAM exposure €405K/year → €230K (estimated) → €180K (verified MRV)
- Fertilizer conglomerate (80% EU): Scope 2 emissions + Morocco grid factor (0.7 tCO2/MWh)
- Small steel workshop (Excel data): Industry benchmarks + IoT recommendation
Key Design Patterns
- Pluggable data sources:
DATA_SOURCE=csv|influxat startup; tests use monkeypatch - Safe templating: custom
safe_eval(noeval(), no external deps) for scenario math - Repository pattern: all SQL in
backend/repositories/*_repo.pyas@staticmethods - Context composition: system prompt built from time_context + roles + scenario taxonomy
- Auth seam: self-rolled JWT + scrypt; single
Depends(get_current_user)— easy Keycloak swap - Resilience:
retry_call()with exponential backoff + jitter for Claude API - Rate limiting: per-user token-bucket, Redis-ready for multi-instance
- Audit: all user actions logged (login, register, investigate, feedback)
Database Schema (10+ tables)
investigations, production_runs, maintenance_logs
scenarios_computed, compliance_checks
audit_log, feedback_log
5. Current Status
Wave-driven delivery — Wave 0 through Wave 20 complete
Last commit: Apr 23, 2026 (frontend updates)
Test coverage: 159+ unit tests covering every subsystem
What works:
- Full agent loop (streaming SSE from Claude to browser)
- All 8 tools implemented and tested
- PostgreSQL persistence with Alembic migrations
- JWT auth on all protected endpoints
- Prometheus metrics + OpenTelemetry tracing
- Rate limiting + audit trail
- PDF/Excel report generation
- React frontend with reasoning stream display + scenario comparison
Pending:
- Full InfluxDB integration (data source exists, needs production NOTQIN connection)
- Kubernetes manifests (not generated for IEIA)
- Multi-factory support (currently single textile mill)
- WebRTC for live expert annotations (future)
6. Relationship to Ecosystem
| Component | Relationship |
|---|---|
| NOTQIN Core | Data source: InfluxDB notqin_derived bucket |
| NOTQIN Agent | Sibling: Agent handles regulatory/strategic view, IEIA handles operational investigation |
| NOTQIN Physics | Planned integration: IEIA should call physics-service for “is this recommendation physically sound?” |
| NOTQINVR | Future: IEIA maintenance logs feed NOTQINVR Module D repair procedures |
7. Next Actions
- Connect IEIA to live NOTQIN InfluxDB in production mode
- Add multi-factory support (factory profile per investigation session)
- Integrate with notqin-physics for physics-informed scenario validation
- Generate Kubernetes manifests for IEIA deployment
- Migrate auth from self-rolled JWT to Keycloak (only
auth/dependencies.pychange needed) - Write IEIA product case study for Personal Brand