Complete reference for all environment variables and configuration options.
All configuration is managed through the .env file in the project root.
Type: String Description: API key for ENTSO-E Transparency Platform Get it from: https://transparency.entsoe.eu/
Type: String
Description: European electricity market bidding zone code
Default: AT (Austria)
Valid values: AT, DE, FR, NL, CH, BE, ES, IT, etc.
Example: BIDDING_ZONE=DE
Common Codes:
AT- AustriaDE- GermanyFR- FranceNL- NetherlandsCH- SwitzerlandBE- BelgiumES- SpainIT- Italy
Full list: https://transparency.entsoe.eu/content/static_content/Static%20content/web%20api/Guide.html#_areas
Choose ONE of the following provider configurations:
Type: String Description: API key for Cerebras Cloud Get it from: https://cloud.cerebras.ai/
Type: String
Description: Model ID to use for orchestrator
Valid values: Any model ID from Cerebras API
Example: CEREBRAS_MODEL=model-name
Check the dashboard for available models - it automatically fetches and displays all models from your provider's API.
Type: String
Description: OpenAI API key
Format: Starts with sk-
Get it from: https://platform.openai.com/api-keys
Type: String
Description: Provider identifier
Value: openai
Example: LLM_PROVIDER=openai
Type: URL
Description: OpenAI API base URL
Value: https://api.openai.com
Example: LLM_API_BASE=https://api.openai.com
Type: String
Description: OpenRouter API key (reuses OpenAI variable name)
Format: Starts with sk-or-
Get it from: https://openrouter.ai/keys
Type: String
Description: Provider identifier
Value: openrouter
Example: LLM_PROVIDER=openrouter
Type: URL
Description: OpenRouter API base URL
Value: https://openrouter.ai/api
Example: LLM_API_BASE=https://openrouter.ai/api
Type: String
Description: Model ID from OpenRouter catalog
Format: provider/model-name
Example: CEREBRAS_MODEL=provider/model-name
Browse available models: https://openrouter.ai/models
Type: String
Description: Not required for local LLMs
Value: not_required_for_local
Example: LLM_API_KEY=not_required_for_local
Type: String
Description: Provider identifier
Value: custom
Example: LLM_PROVIDER=custom
Type: URL
Description: Local Ollama API endpoint
Default: http://localhost:11434
Docker: http://host.docker.internal:11434
Example: LLM_API_BASE=http://localhost:11434
Type: String
Description: Ollama model name
Example: CEREBRAS_MODEL=model-name:tag
Check available models:
ollama listFor providers not explicitly listed above:
Type: String Description: API key for your LLM provider
Type: String
Description: Provider identifier for logging
Options: cerebras, openai, anthropic, openrouter, custom
Example: LLM_PROVIDER=custom
Type: URL
Description: Base URL for OpenAI-compatible API
Example: LLM_API_BASE=https://api.yourprovider.com
Type: Path
Description: Working directory for orchestrator execution
Default: /app/agentic-hems (in Docker)
Auto-detected: Uses script directory if not set
Example: HEMS_WORK_DIR=/app/agentic-hems
Note: Set automatically in Dockerfile, usually don't need to change
Type: Path
Description: Path to Python virtual environment (local development only)
Default: Not set (no venv activation)
Docker: Not used (dependencies installed globally in container)
Example: VENV_PATH=/path/to/your/venv
Note: Optional. Only set this if you're running locally and want to activate a specific virtual environment
For research reproducibility, the system supports two methods to ensure consistent price data across experiments.
Fetch prices for a specific historical date from ENTSO-E:
from tools import get_electricity_prices
# Lock to specific date (still makes API call)
prices_data = get_electricity_prices(date="2025-10-15")Use case: Running systematic evaluations on the same price profile while ensuring data freshness from ENTSO-E API.
Use pre-saved price data without API calls:
from tools import get_electricity_prices
# Use cached file (no API call)
prices_data = get_electricity_prices(use_cached_prices=True)Use case: Offline testing, exact reproducibility, or when ENTSO-E API is unavailable.
File: test_prices_reference.json (included in repository)
Contains day-ahead electricity prices from 2025-10-15, allowing researchers to:
- Reproduce exact experimental conditions
- Compare results across different models on identical price data
- Benchmark against known optimal solutions
- Work offline without ENTSO-E API access
The MILP baseline optimizer (milp-baseline/optimizer.py) automatically uses test_prices_reference.json for consistent comparison against the same price profile.
To create a new reference price file from a specific date:
from tools import get_electricity_prices
import json
# Fetch prices for specific date
prices_data = get_electricity_prices(date="2025-10-15")
# Save as reference
with open('test_prices_reference.json', 'w') as f:
json.dump(prices_data, f, indent=2)Recommendation: Document the date in your research notes and update the date in this documentation when creating new reference files.
These are set in code, not in .env. Modify api.py to change:
# In api.py
app.run(
host='0.0.0.0', # Bind to all interfaces
port=5001, # API port
debug=True # Debug mode (disable in production)
)# In api.py
limiter = Limiter(
get_remote_address,
app=app,
default_limits=["200 per day", "50 per hour"], # Global limits
storage_uri="memory://",
strategy="fixed-window"
)
@app.route('/api/run/stream', methods=['POST'])
@limiter.limit("20 per minute") # Endpoint-specific limitModify to adjust limits:
default_limits: Global rate limits@limiter.limit(): Per-endpoint limits
# In api.py
CORS(app) # Allow all origins (development)
# Production
CORS(app, origins=['https://yourdomain.com'])# In api.py
# Orchestrator execution timeout (subprocess.run and process.wait calls)
timeout=300 # 5 minutes
# Model API fetch timeout (requests.get in get_models function)
timeout=10 # 10 secondsDashboard settings are in dashboard.html. No environment variables needed.
Models are fetched dynamically from provider API. To set default:
// In dashboard.html
const DEFAULT_MODEL = 'your-model-id';// In dashboard.html
const examplePrompts = [
{
category: "Single Appliance",
prompts: [
"Schedule my dishwasher for tomorrow",
// Add your own examples here
]
}
];Settings in orchestrator_agent_react.py:
max_iterations = 15 # Maximum ReAct loop iterationsPrevents infinite loops. Currently hardcoded in the run() method of orchestrator_agent_react.py. Increase for complex multi-step tasks by modifying the value in the orchestrator's main loop.
Set via environment variable (passed from API):
model = os.getenv('CEREBRAS_MODEL_OVERRIDE') or os.getenv('CEREBRAS_MODEL')Dashboard sets CEREBRAS_MODEL_OVERRIDE dynamically based on user selection.
SYSTEM_PROMPT = """
You are an expert HEMS orchestrator...
"""Defines agent behavior and reasoning style.
Fixed at 15-minute intervals (96 slots per 24 hours):
SLOTS_PER_HOUR = 4
SLOTS_PER_DAY = 96Changing resolution requires:
- Update ENTSO-E data fetching
- Update scheduling algorithms
- Update visualization (dashboard)
Not recommended unless necessary for research.
All executions saved to data/runs/ directory (organized by model):
data/runs/
└── model-name/
├── run_20251017_153045.json
├── run_20251017_154132.json
└── ...
Clean old runs:
find data/runs/ -type f -mtime +30 -delete # Delete files >30 days oldFor analysis in spreadsheet tools (Excel, Google Sheets), export all run data to CSV:
python export_results_to_csv.pyGenerates two files:
scheduling_evaluation.csv- Appliance scheduling runs with optimality metricsanalytical_query_evaluation.csv- Analytical query runs (price analysis, time queries)
Key columns in scheduling_evaluation.csv:
model- LLM model usedappliance_id- Which appliance was scheduledrecommended_slot- Agent's recommended start slotcost- Total energy cost (EUR)total_tokens- Tokens used (orchestrator + specialist agent)success- Whether run completed successfullyiterations- Number of ReAct iterations
Use case: Compare model performance, track success rates, analyze token efficiency across experiments.
Enable verbose logging:
# In api.py
app.run(debug=True) # Flask debug mode
# In orchestrator
import logging
logging.basicConfig(level=logging.DEBUG)ENTSOE_API_KEY=your_entsoe_key
BIDDING_ZONE=AT
CEREBRAS_API_KEY=your_cerebras_key
CEREBRAS_MODEL=model-nameENTSOE_API_KEY=your_entsoe_key
BIDDING_ZONE=DE
OPENAI_API_KEY=your_openai_key
LLM_PROVIDER=openai
LLM_API_BASE=https://api.openai.com
CEREBRAS_MODEL=model-nameENTSOE_API_KEY=your_entsoe_key
BIDDING_ZONE=AT
LLM_API_KEY=not_required_for_local
LLM_PROVIDER=custom
LLM_API_BASE=http://localhost:11434
CEREBRAS_MODEL=model-name:tagCheck configuration validity:
# Test ENTSO-E connection
curl "https://web-api.tp.entsoe.eu/api?securityToken=$ENTSOE_API_KEY&documentType=A44&in_Domain=10YAT-APG------L&out_Domain=10YAT-APG------L&periodStart=202501010000&periodEnd=202501020000"
# Test LLM provider
curl http://localhost:5001/api/models
# Test full flow
curl -X POST http://localhost:5001/api/run/stream \
-H "Content-Type: application/json" \
-d '{"prompt": "Schedule dishwasher for tomorrow", "model": "your-model-id"}'-
"No API key found"
- Check
.envfile exists - Verify no spaces around
= - Restart services after changes
- Check
-
"Model not found"
- Check model ID is correct
- Try fetching
/api/modelsto see available models
-
"ENTSO-E connection failed"
- Verify API key is activated
- Check bidding zone code is valid
See Troubleshooting Guide for detailed solutions.
-
Separate Dev/Prod Configs
.env.development .env.production
-
Use Comments
# Day-ahead price API ENTSOE_API_KEY=your_key_here # Active until 2026-01
-
Version Control
- Commit
.env.example(with placeholders) - Never commit
.env(actual keys)
- Commit
-
Validate on Startup
- Check required variables exist
- Test API connections
- Log configuration summary
- Full setup guide: SETUP.md
- Troubleshooting: TROUBLESHOOTING.md
- GitHub Issues: https://github.com/redaelmakroum/agentic-ai-hems/issues