Voultra Grid detects wasted-wind windows on the UK grid, negotiates flexible demand, commits the decision on-chain before execution, and settles rewards for every verified kWh shifted.
Built for the UK AI Agents Lab hackathon (DoraHacks 2272) — Demo Day, 4–5 July 2026, Imperial College London.
What it is: a credible, demoable flexibility-market simulator using live public UK grid data (NESO Carbon Intensity + Elexon Insights) and real agent / on-chain integration points. It is not pitched as balancing the whole UK grid.
Proof it matters today: at time of writing, live Elexon system prices were negative (−£3.96/MWh) with wind at 44.9% — actual curtailment conditions. Voultra Grid's live mode reads that, classifies it as a curtailment window, and dispatches charge_or_shift_load.
cd voultra_grid_hackathon
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
cp .env.example .env
# One end-to-end cycle (deterministic demo, no keys needed)
python -m voultra_grid.cli run-cycle
# Same cycle against live NESO + Elexon data
python -m voultra_grid.cli run-cycle --liveuvicorn voultra_grid.api:app --reload --port 8080- http://127.0.0.1:8080/ — marketing landing page (real UK renewables photography, live telemetry strip pulled from the API on load)
- http://127.0.0.1:8080/app — the dispatch console itself: Dispatch / Agent Chat / Backtest / Audit Log / Network tabs, plus a floating chat widget available on every page
React 18 + Framer Motion (vendored — works fully offline, no CDN, no build step). On the Dispatch tab, toggle Demo / Live, press Run cycle, and watch the pipeline: SENSE → DECIDE → NEGOTIATE → COMMIT → SETTLE alongside a live agent-activity feed and stress trend.
See SETUP.md for full install, configuration, testing, and GitHub push instructions.
pip install -e ".[agents]"
export PYTHONPATH=./src
python agents/asi_one_chat_agent.pyAsk it the judge question: “Can we reduce wasted wind tonight?” It replies with grid snapshot, recommended flex dispatch, selected provider, commit hash, settlement status, and estimated CO₂ avoided.
python agents/fetch_multi_agent_demo.pyGridWatch → FlexProvider → DispatchAgent exchange structured uAgents messages end-to-end (verified locally: agents boot, exchange snapshot/offer messages, and log the hashed decision).
uvicorn voultra_grid.api:app --port 8080→ open the console.- Click Run dispatch cycle → pipeline animates; metrics, market offers (winner ringed), decision + SHA-256 commit hash, settlement rail, audit log.
- Flip to Live NESO + Elexon → run again → real UK grid numbers right now.
python agents/asi_one_chat_agent.py→ ask “Can we reduce wasted wind tonight?” in ASI:One / Agentverse chat.- Show
data/voultra_grid_audit_log.jsonl— append-only commit-before-execute trail. - (Optional, if credentials on hand) show Kaspa TN-10 broadcast and Ethereum impact-event config paths in
.env.
agents/asi_one_chat_agent.py— Chat-Protocol uAgent (ChatMessage,TextContent,ChatAcknowledgement,EndSessionContent, manifest published). Runs on port8001with mailbox enabled by default.- Register on Agentverse: run the agent, open the Agent inspector link it prints, connect via Mailbox in Agentverse — it then becomes discoverable through ASI:One.
agents/fetch_multi_agent_demo.py— three-agent Bureau proving real agent-to-agent architecture.
src/voultra_grid/apex_policy.py— interpretable local dispatch policy. Priority order:- Curtailment window (wind ≥ 35% and system price ≤ £5/MWh, incl. negative) → absorb.
- High stress (≥ 0.70) → charge / shift load.
- Low stress (≤ 0.30) → discharge / reduce load.
- Otherwise hold.
apex_submission/policy.py— standalone, numpy-onlypolicy(challenge, state) -> list[float], robust to changing challenge schemas (recursive key lookup, SoC-constrained charge/discharge on price quartiles). Submit via the Apex CLI.- No leaderboard claims are made anywhere — submit and let the validators score it.
- Every decision is canonicalised (sorted-key JSON) → SHA-256 decision hash → appended to the local JSONL audit log before execution.
- Optional TN-10 broadcast via your own wallet command template — no private keys ever touch this repo:
KASPA_ENABLED=true
KASPA_NETWORK=tn10
KASPA_REST_API_BASE=https://api-tn10.kaspa.org
KASPA_EXPLORER_BASE=https://explorer-tn10.kaspa.org
KASPA_RECIPIENT_ADDRESS=kaspatest:...
KASPA_BROADCAST_COMMAND='kaspa-wallet send --to {recipient} --amount-sompi {amount_sompi} --payload {decision_hash}'Safe by default: with no command supplied, status is local_commit_only and the hash + audit trail are still real.
contracts/ImpactLedger.sol— emitsImpactRecorded(decisionHash, recorder, kWhShifted, co2SavedKg, providerId, timestamp); duplicate hashes rejected.src/voultra_grid/ethereum_impact.py— Web3 adapter callingrecordImpact(...)(compatible with web3.py v6 and v7). Testnet only (Sepolia default,ETH_CHAIN_ID=11155111). Enable withETHEREUM_ENABLED=true+ RPC/key/contract in.env.
- NESO Carbon Intensity API —
/intensity(current gCO₂/kWh + index) and/generation(wind share of the mix). - Elexon Insights API —
/balancing/settlement/system-prices/{date}(settlement system prices). - Both have robust parsing with deterministic demo fallback — the demo never breaks on flaky venue wifi.
- Fetch or simulate a
GridSnapshot(carbon, index, price, wind %, stress score, source notes). - Policy decides
charge_or_shift_load/discharge_or_reduce_load/hold. - Request offers from three simulated flex providers (battery / EV depot / cold storage).
- Choose the best offer on carbon avoided, price, confidence, response time.
- Build the
DispatchDecision(action, kWh, provider, price, value, CO₂ saved, reason). - Hash it (SHA-256 over canonical JSON, excluding the hash field itself).
- Commit to the append-only JSONL audit log → optional Kaspa TN-10 broadcast → optional Ethereum impact event.
- Return the judge-friendly summary.
Value model note: in a curtailment window (charge action, price ≤ £5/MWh) the gross value uses a £70/MWh proxy for avoided NESO constraint payments instead of the near-zero/negative spot price; otherwise gross value = spot price × kWh. Provider payments are subtracted in both cases. Labelled as an estimate everywhere.
These exist to answer the honest questions judges (or you, at 2am before demo day) will ask.
- Hash verification (
POST /verify) — paste any decision JSON back in and it independently recomputes the SHA-256 commit hash and confirms it matches. Live-demonstrates that "commit-before-execute" isn't cosmetic: tamper with one field and the mismatch shows immediately. - Stress-score history (
GET /stress-history) — a small sparkline on the dashboard tracking grid-stress across your recent cycles, so a quiet live-mode moment has visible context. - 24-hour backtest (
GET /backtest?date=YYYY-MM-DD) — replays the exact same policy across a full real day of NESO + Elexon settlement data (48 real half-hourly periods, one HTTP call each, no fabricated numbers) and reports cumulative CO₂ avoided, net value, and how many curtailment windows the policy actually caught that day. Useful to show robustness beyond a single point-in-time snapshot — e.g. 2 July 2026 real data: 12 curtailment windows caught, 343 kg CO₂ avoided, £464.50 value.
| Route | What it returns |
|---|---|
GET /health |
service status + integration modes (Kaspa, Ethereum, agent, data sources) |
POST /run-cycle?demo=true|false |
one full cycle → snapshot, offers, decision, settlement |
GET /last |
most recent cycle result |
GET /providers |
the flex provider roster |
GET /history?limit=N |
tail of the append-only audit log |
GET /stress-history?limit=N |
grid-stress time series from past cycles, for the sparkline |
POST /verify |
recompute and check a decision's SHA-256 commit hash |
GET /backtest?date=YYYY-MM-DD |
replay the policy across a real historical day |
GET /judge-summary |
runs a cycle, returns the judge summary as HTML |
GET / |
the dispatch console |
python -m pytest tests/ -q # 16 testsCovers: decision-hash determinism, canonical JSON stability, all four policy branches (incl. the live curtailment window), flex-market offer generation/selection, Apex policy shape + power constraints + weird-schema survival, every API endpoint end-to-end, hash verification (matching and tampered), stress-history population, and a live backtest against real historical data.
src/voultra_grid/ core: config · models · grid_data · apex_policy · flex_market
settlement · ethereum_impact · orchestrator · api · cli
src/voultra_grid/static/ dispatch console (React + Framer Motion, vendored, offline)
agents/ ASI:One chat agent · three-agent Bureau demo
apex_submission/ numpy-only policy.py for the Apex CLI
contracts/ ImpactLedger.sol
tests/ 13 tests
docs/ console screenshots
- Local / demo: deterministic snapshot, simulated flex providers, local JSONL commit.
- Live: real NESO + Elexon reads (with graceful fallback).
- Testnet: Kaspa TN-10 and Ethereum Sepolia — only with your wallet/RPC in
.env. - Never: private keys in source, mainnet actions, or unverified leaderboard claims.
