-
-
Software Carbon Intensity per release (GSF SCI v1.1.0), about 0.56 gCO2e
-
Kairos Autopilot: six custom GitLab Duo flows run the post-code lifecycle
-
Kairos Triage turns a new issue into testable acceptance criteria and starts the build
-
Kairos Review Gate blocks a merge request on the exact line; the fixer repairs it
-
verify:production fails and autopilot:rollback restores the last good release
Inspiration
Kairos is a small app that tells a household in Greece when to run the washing machine or charge the car, from the day-ahead electricity price and the weather. It had tests and a demo, but every change still needed a person to review it, merge it, deploy it, check it and clean up when it broke. We wanted to see how far GitLab Duo Agent Platform can take a real project from "issue opened" to "running in production" with nobody in the middle, inside the limits every participant has (the Developer + AI role), and to make the pipeline follow the app's own idea: do heavy work when the grid is clean.
What it does
- Triage, build, review in one flow. Opening an issue starts Kairos Triage, three agents in one GitLab Duo flow: a triage agent on the small model writes testable acceptance criteria (or closes duplicates and answered questions), a builder implements them with tests and opens the merge request with auto-merge already armed, and a separate read-only reviewer writes a SHIP or BLOCK verdict for that exact commit.
- A review gate the pipeline enforces. Every merge request a person pushes is reviewed by Kairos Review Gate against the project rules (time zones, 15-minute slots, units, offline mode, bilingual text, files the image must contain), with notes on the exact lines. The
autopilot:gatejob passes only on SHIP for the pipeline's own commit, and GitLab auto-merge does the merge; any new push disarms it, so a verdict can never ship a newer commit. - Fixes. A red pipeline starts Kairos Pipeline Fixer: it reproduces the failure in a clone, fixes code or test, runs the suite, pushes and re-arms auto-merge; its own reviewer agent judges the new commit. Two attempts, then it asks for a person.
- Release on clean power. Releases leave on a train every 30 minutes. The train ships main when it differs from production, waiting (at most 12 hours) for a cleaner hour on the Greek grid; reverts and security fixes leave at once. Replayed on September 2026, that halves the grid intensity at release for an around-the-clock autopilot (271 to 136 gCO2eq/kWh).
- Deploy, verify, roll back. A release is an OCI artifact tagged
productionin the GitLab registry; Flux on our Athens cluster follows the tag.verify:productionchecks that the new build is live and answers fast; if not,autopilot:rollbackmoves the tag back to the last good release and waits until the site serves it. Kairos Incident Responder then writes the incident (impact, UTC timeline, the diff lines that caused it) and opens the revert, which its reviewer checks and the next train ships immediately. - Security. A daily dependency audit at the Greek solar peak turns a published CVE into a "Security:" merge request through the same loop.
- Tell people, and measure. Kairos Release Notes posts "Shipped in " with the verification result and the release's Software Carbon Intensity on every merge request and issue, and keeps a release log. Each release computes its SCI (Green Software Foundation SCI v1.1.0); a typical release on GitLab's hosted runners: 0.56 gCO2e (E 0.84 Wh x 579 g/kWh + M 0.08 g), estimated from CPU time with Cloud Carbon Footprint coefficients and calibrated against a power sensor on our Athens node.
How we built it
- Six custom flows in the GitLab AI Catalog (flow registry v1, ambient), created, enabled and wired to their triggers through the GraphQL API (
aiCatalogFlowCreate,aiCatalogItemConsumerCreate), each with only the tools it needs; multi-agent flows (worker plus reviewer component); small models for triage and notes; API-only flows skip the clone. - GitLab CI/CD on hosted runners: merge request checks (tests, SAST, secret detection, pip-audit, the verdict gate), a release train schedule, release pipelines (Python matrix, image build, container scanning, deploy, verify, SCI, GitLab release, rollback), a daily security scan.
- Identities without tokens: people set intent (an issue, or a push with
merge_request.merge_when_pipeline_succeeds); flow service accounts act on merge requests and arm auto-merge with their own pushes;CI_JOB_TOKENpublishes images, the deploy artifact and releases; Flux pulls. No personal token is stored in the project. - SCI on hosted runners from CPU time and Cloud Carbon Footprint coefficients, calibrated against the package power sensor of our own Athens node.
Challenges
- The Developer + AI role has no project tokens and flows have no merge tool, and quick actions in agent notes are not executed. Auto-merge armed by whoever pushes, plus a CI job that reads the verdict, turned out to be enough.
- GitLab starts flows only for a person's actions, and a flow cannot start another flow in this group. So the flows that change code carry their own reviewer agent, and releases run in a schedule a person owns, which keeps the release flows firing whoever merged.
- Honest carbon numbers: the hosted runners sit in South Carolina, so the Greek-grid timing does not lower their footprint; we say so, measure them with a published method, and found that a verification job waiting on an idle VM was most of a release's energy.
Accomplishments
- Real end-to-end runs in the public project on 18 October (links in
docs/EVIDENCE.md): an issue became a reviewed, merged change in 2.4 minutes; a broken merge request was blocked, fixed by the fixer and merged in 4.1 minutes; a bad release was rolled back while the old build kept serving, and the incident write-up and the revert were done and merged 2.3 minutes after the rollback; a published CVE in a dependency became a merged security fix 2.7 minutes after the scan. Five releases, all with an SCI line, all through the release train. - A real incident on 19 October: after the app moved to its public address, Cloudflare answered the verifier's default client with 403, so
verify:productionsaw production as unreachable and rolled the release back. Kairos Incident Responder judged a prose-only change an implausible cause and flagged incident #6 for a person instead of reverting; the fix (!9, a named User-Agent plus a test) passed Kairos Review Gate with SHIP and auto-merged, closing the incident. - Agent work for all of it: 46 GitLab Credits for 17 flow sessions.
- Every agent decision is a note, a commit on a branch or an issue anyone can audit.
What we learned
- The useful boundary for autonomy is not "can the agent do it" but "can someone audit it afterwards and can a stale decision ever act": binding verdicts to a commit and letting GitLab's auto-merge disarm on every push gave us that for free.
- The biggest carbon cost in a small pipeline is waiting, not computing.
What's next
- Use Kairos's own price-and-weather planner for the release train (one scheduler for washing machines and pipelines).
- A self-hosted runner in Athens so the Greek-grid timing lowers the runner energy too, measured with the power sensor.
- Publish the six flows as reusable AI Catalog items for any Flux-deployed project.
AI-assisted, human-directed.
Built With
- cloud-carbon-footprint
- docker
- energy-charts
- fastapi
- flux
- gitlab-ai-catalog
- gitlab-ci
- gitlab-duo-agent-platform
- green-software-foundation-sci
- kubernetes
- oci
- python
Log in or sign up for Devpost to join the conversation.