Inspiration
Everyone now has AI that writes code. Almost nobody has automated the expensive, risky part that comes after the commit: review, security scanning, compliance evidence, packaging, release, monitoring, and rollback — plus the paper trail that proves it all happened. That gap is exactly what GitLab's "life after code" theme points at. We wanted to show a repo that a human only ever touches by filing an issue — and the next time they look, the change is live and documented, with a machine that refused to ship anything unsafe.
What it does
Relay is a hands-off DevSecOps conductor built on the GitLab Duo Agent Platform. Mention the Relay flow on an issue and it:
- Plans the change and posts the plan on the issue.
- Creates a branch + merge request with the code and tests.
- Verifies with pytest + coverage.
- Secures: Bandit (SAST), pip-audit (deps), gitleaks (secrets) in CI; the security review agent reviews the diff and commits minimal fixes for high/critical findings.
- Governs: generates a CycloneDX SBOM and runs a deterministic policy gate that blocks the release on any high SAST finding, any vulnerable dependency, or coverage below 85%.
- Packages a non-root container image.
- Releases every Relay branch to an ephemeral review environment, then monitors its health.
- Merges the MR, but only when the gate allowed it and the review deploy is healthy.
- Promotes the merged image to production: the gate is re-checked, the image is deployed and health-checked, and it rolls back automatically to the last-known-good production image (ledger kept in the CI cache) if the check fails.
- Reports: the flow reads the pipeline's verdict, deploy, monitor and rollback results back through the GitLab API and posts a review report and a production report on the original issue.
The product being shipped is mdsafe, a small but real "safe Markdown → HTML"
microservice — chosen because it has a genuine security surface (XSS, javascript:
links) so the security stage has real work to do, not a toy.
How we built it
- GitLab Duo Agent Platform custom flow (
.gitlab/duo/relay-hands-off.flow.yaml, flow-registry v1, published to the AI Catalog): planner → implementer → security reviewer → govern/release reporter. The reporter never runs scanners itself: it reads the CI pipeline's deterministicpolicy_gateverdict (reports/policy.json) and the conductor's deploy/monitor/rollback artifacts viagitlab_api_get. - A runnable orchestrator (
relay/orchestrator.py) is the deterministic engine behind the flow: idempotent (state keyed by commit SHA, never double-deploys), fail-closed governance, real failure handling, and automatic rollback. The same engine runs in CI and locally, so behavior is identical. - Deterministic tools (
relay/tools/):policy_check.py,monitor.py,rollback.py,audit_trail.py— plain, unit-tested Python. No model decides whether to ship. - GitLab CI/CD (
.gitlab-ci.yml): verify → secure → govern → package → release, with the conductor job deploying every Relay branch to a review environment, health-checking it and rolling back automatically. - 56 automated tests (including CI-config tests for the promotion path), 92% coverage on the demo run, including failure paths: policy fail-closed on missing/malformed reports, unhealthy-deploy rollback, idempotent re-runs, and renderer XSS edge cases.
Challenges we ran into
- Making "autonomous" trustworthy. Letting an LLM decide to deploy is a non-starter. We split responsibility: agents decide what to change; deterministic, unit-tested gates decide whether it ships. The gate is fail-closed — a missing scan report is itself a block, so you can't bypass it by not producing a report.
- Idempotency. Agent retries and pipeline re-runs must not double-deploy or spam the issue. We key run state and the audit comment to the commit SHA, so re-runs skip finished stages and update the same comment instead of duplicating it.
- A real renderer bug. Writing security tests surfaced a genuine bug: inline code spans were being re-parsed for bold/italic. We fixed it with placeholder protection — a nice example of the security stage earning its keep.
Rollback that actually triggers. The monitor failing automatically restores the last-known-good image from a release ledger and re-probes; we test this path.
Agents in a sandbox can't verify anything themselves. The Duo sandbox has no package index, so an in-flow
pip install pytestfails. We moved all verification into CI and made the flow read CI's verdict through the API. That's more trustworthy anyway, because the agent can't fake a passing gate.Merging without a merge permission. The Duo session token can't call the merge API (403 insufficient_scope). Relay merges with a plain
git merge --no-ffpushed tomain; GitLab marks the MR merged, andmain's pipeline re-gates before production.Long-running sessions. Waiting on CI inside one session sometimes hit websocket drops. Pipeline triggers don't fire for pipelines that service accounts create, and
start_flowlaunches catalog flows as chat agents. So the final design polls in short 15-second steps and reports in the same session.
Accomplishments we're proud of
- A genuinely hands-off loop you can run end-to-end locally (
scripts/demo_hands_off.sh) — no hand-waving. - Nine DevSecOps lifecycle stages covered (see
docs/STAGES.md). - Trust-by-design: every automated decision is deterministic and auditable.
What we learned
Autonomy in DevSecOps is less about smarter agents and more about crisp, verifiable gates around them. The agent is the author; the pipeline is the editor that never sleeps.
What's next for Relay
- Swap the ephemeral CI environments for a real target (Cloud Run for the GCP bonus) behind
deploy.sh. - Publish the flow to the GitLab AI Catalog so any project can adopt it.
- Add deploy targets (Cloud Run, k8s) behind the same
deploy.shcontract. - A "progressive autonomy" dial: start Assisted, graduate to Hands-off as trust builds.
- SCI-based carbon accounting per run (a path to the Most Environmentally Impactful prize).
See it run
A real hands-off run on GitLab.com: issue #11 → Duo session 9344062 → MR !10 →
review pipeline 2939863072 (review deploy healthy) → auto-merge
(commit 9056ad8) → main pipeline 2939873454 → promote_production
healthy → report on #11: PROMOTED-TO-PRODUCTION.
A human only filed the issue and mentioned the flow.
Log in or sign up for Devpost to join the conversation.