Inspiration

I lead AI adoption for the internal audit function of a French banking group, and I have audited a group AI architecture. Every agent use case I approve adds compute, and none of it is scheduled: it runs the moment someone files the work.

Most post-code work can wait a few hours. Dependency upgrades, refactors, test matrices and full scans have deadlines in hours or days, not seconds. Meanwhile grids throw clean power away: Spain's day-ahead price was at or below zero for 760 hours between January and September 2025, and Britain paid £363 m to curtail 10 TWh of renewables in 2025.

A supervised workflow has to run while someone is awake to approve it. A hands-off one can follow the wind. I wanted to measure whether autonomy itself is a climate feature.

What it does

Joule Thief treats the backlog of deferrable work as a battery: it charges while the grid is dirty and discharges when clean power is in surplus.

  1. Surge Intake (custom Duo flow, work item created trigger) triages each new issue: priority, kind of work, whether it can wait.
  2. Every 30 minutes Cloud Scheduler ticks the dispatcher on Cloud Run. It plans the backlog with OR-Tools CP-SAT on the grid's marginal signal (day-ahead prices, NESO, WattTime), under each issue's deadline.
  3. @grid, the electricity grid with a seat at code review, explains every hold and release on the issue with numbers. Critical work never waits, and @grid logs what urgency cost.
  4. When the window opens, the dispatcher starts the Surge Worker flow through the Flows API (hands-off: no user prompts). Claude Haiku 4.5 explores, Claude Sonnet 5.5 implements, and the MR gets a label the model cannot remove (enforced tool option).
  5. The MR pipeline measures joules per request (GitLab metrics report) and carbon blame per source line. The Carbon Reviewer flow is woken only by a regression or an edit to a hot line. Scanners run. Auto-merge merges when every gate passes.
  6. The main pipeline signs a carbon receipt (in-toto, Sigstore keyless from GitLab OIDC), refuses to deploy without a valid one inside the budget, deploys a Cloud Run canary, and promotes it only if it is not hungrier per request than production.
  7. joule shipped posts the carbon balance on the issue. When a pipeline fails, the Retry Guard flow (pipeline trigger) reads the logs, never retries a deterministic failure, and files a Surge Request.

It ran on 9 October 2026, untouched. I filed #3 "Dashboard comparison is slow" at 08:37 UTC. At 09:00 @grid released it into a −3.0 €/MWh surplus (11 gCO₂/kWh on the margin). At 09:04 the Surge Worker opened !1; the energy check measured /api/compare going from 2.88 to 0.42 J per request (−85 %); at 09:08 it merged itself. At 12:02 it was live on Cloud Run as v0.1.25, and the issue carried its "Shipped" note with a within-budget, Sigstore-signed carbon receipt.

How I built it

  • GitLab Duo Agent Platform: 4 custom flows (public in the AI Catalog), 2 custom agents, triggers (work item, pipeline failed with a status filter, reviewer assigned, mention), the Flows API, model_tags routing, enforced tool options, coding_environment: none for API-only flows, agent-config.yml, and an MCP server for Duo Agentic Chat, IDE and CLI. Every flow is validated in CI against GitLab's own flow schema.
  • GitLab CI/CD: 9 stages, merge request pipelines, JUnit and metrics reports, SAST, secret detection, dependency and container scanning, environments, releases, auto-merge, interruptible pipelines, feature flags, schedules.
  • Google Cloud: Cloud Run in europe-north1 (scale to zero), Artifact Registry with cleanup, Workload Identity Federation (no keys), Secret Manager, Cloud Scheduler, Cloud Storage for shared OpenTofu state, and a Cloud Function that unlinks billing at €5. GitLab Duo itself ran on Claude models on Vertex AI.
  • Code: Python, standard library first; OR-Tools CP-SAT; EcoLogits; Cloud Carbon Footprint coefficients; free data from Energy-Charts, NESO and Open-Meteo. Deterministic first, LLM last: every number the system writes comes from code.

Challenges I ran into

  • My own gate cried wolf. After the agent's MR merged, the canary energy gate blocked the deploy three times. Each block filed an incident, and the agents picked them up. The cause was the gate's own measurement: a cold canary against a warm production, then a single noisy sample on Cloud Run. The gate now measures interleaved warm blocks and blocks only when every canary block is above production's median (production against itself: 0.48 vs 0.51 J/request).
  • GitLab's flow validator is stricter than the spec. It rejects max_cycles, so I vendored GitLab's schema into the tests and moved token discipline into narrow toolsets and fixed step lists.
  • Averages mislead. Finland is 39 g/kWh on average and about 785 g/kWh on the margin. Scheduling on averages moves load into hours that only look clean.

Accomplishments that I'm proud of

  • A full hands-off loop on a real project, from issue to production, with every step linked.
  • The carbon dividend of autonomy, measured on real grids. Same backlog, same deadlines:
Grid Supervised vs run-now Hands-off vs run-now Dividend Late (supervised / hands-off)
Great Britain, Sep–Oct 2026 −17.9 % −24.9 % 6.9 % 10 / 0
Spain, spring 2025 −26.5 % −34.2 % 7.8 % 22 / 0
Spain, summer 2025 −20.5 % −30.6 % 10.2 % 29 / 0
  • Over five seeded backlogs the dividend is positive in all 15 runs, and a wrong price model still cuts 22–39 %.
  • The agents' own footprint, measured from every session's checkpoint: intake 2 LLM calls, a Surge Worker 20–23 calls and about 5.5 Wh.

What I learned

Autonomy pays a climate dividend only if the agent may wait. And a carbon tool must measure itself: once the agents ran for real, a small code change with provider-hosted models moved about 2 Wh of CI, below the break-even where scheduling pays for its own accounting. The gains come from heavy CI and from inference that can be scheduled.

What's next

GitLab Duo Self-Hosted or region-pinned models so inference can be scheduled too; the grid-window CI/CD Catalog component for projects that want the scheduling without agents; WattTime MOER for more US regions.


Built With

  • claude
  • cosign
  • ecologits
  • fastapi
  • gitlab
  • gitlab-ci
  • gitlab-duo-agent-platform
  • gitlab-duo-flows
  • google-artifact-registry
  • google-cloud
  • google-cloud-functions
  • google-cloud-run
  • google-cloud-scheduler
  • google-secret-manager
  • in-toto
  • model-context-protocol
  • opentofu
  • or-tools
  • python
  • sigstore
  • vertex-ai
  • workload-identity-federation
Share this project:

Updates

Submission history