Inspiration
We are a small company that ships most of its code with AI coding agents. Speed was never the hard part. Trust was: who allowed this change, and when must a person look? We wanted the path after the code is written to be fast by default and gated exactly where it matters.
What it does
Release Desk is a set of GitLab Duo Agent Platform flows and a CI/CD pipeline, all governed by one file: release-desk/autonomy-policy.yml. For each of GitLab's nine lifecycle stages the policy says which agent acts, what it may do alone, and what needs a human approver.
- MR policy reviewer: reviews merge requests against the policy when a person opens one or mentions it, leaves findings and may push small mechanical fixes. When a change touches the files that gate releases, it asks the approver instead.
- Pipeline fixer: when a pipeline fails, it reads the failed job's log and, when the cause is in the code and no fix merge request is open yet, opens one.
- Security remediator: turns scanner findings into fix merge requests, or into an issue with its analysis when the code is in files it may not touch. It cannot dismiss a finding: that tool is not in its toolset.
- Release agent: when the default branch is green on staging, it writes the release notes and the evidence on a release issue and asks a person for the production decision.
- Incident responder: on an incident, it diagnoses the cause and names the rollback target, or says there is none. Only a person rolls back.
Agents act on their own within their rules; a person merges, and staging then deploys on its own. Production is a manual job that a person runs: no flow has a tool to run a job, merge a merge request or approve a deployment. Every agent action ends with an audit note that names the policy rule that allowed it.
We built it around Statusboard, a small new status page for a team's public services: a scheduled pipeline checks the endpoints and republishes the page every 30 minutes.
Autonomy level: Supervised. You approve the outcome, not every step.
How we built it
| Stage | What touches it |
|---|---|
| Plan | the release agent opens a release issue with the evidence and closes it after production |
| Create | the MR policy reviewer reviews merge requests and pushes small fixes |
| Verify | unit tests and policy-check; the pipeline fixer opens fix merge requests |
| Package | the site bundle is kept as a job artifact and a generic package |
| Secure | SAST, Secret Detection and Dependency Scanning; the remediator opens fixes or issues, never dismisses |
| Release | staging deploys on its own; a person runs production; CI creates the GitLab Release |
| Configure | staging, production and status-data environments; the policy file is configuration |
| Monitor | a scheduled health check; the incident responder diagnoses incidents and names the rollback target |
| Govern | CODEOWNERS on the gating files, policy-check on every push, one audit note per agent action |
The five flows run on GitLab's hosted runners with Claude Sonnet through the Duo Agent Platform, each with its own service account and triggers (mention, assign, merge request created, pipeline failed or passed). policy-check fails the pipeline unless all nine stages are present, every rule has an id and every human-gated action names an approver. The audit note has one documented format: CI jobs render it with one small script, and the flows write the same fields themselves. The scripts and the health check have 23 tests in Node's own test runner, all passing.
Challenges we ran into
- The first five agent sessions failed before the agent started. Our flow image (
node:22-alpine) had nocurl, which the flow job needs to install its CLI. We moved the flows to GitLab's default image. - One event, two agents. A single "pipeline passed" event started two remediator sessions, and a rerun made the release agent open a duplicate release issue. The release agent now reuses the open release issue of a commit.
- Tools that refuse. The remediator's vulnerability-issue tool rejected every call with a schema error, so it filed nothing. We gave it a plain issue tool as a fallback, and it filed one issue per finding.
- Limits of a contributor role. Our role cannot set protected environments, change who may override pipeline variables, create a project token, or stop Developers (our agents' service accounts included) from pushing to the default branch. So production is a manual job instead of a protected-environment approval, the scheduled monitor gets its variables from a
workflow:rulesentry, and the incident in our test was opened by us by hand. We say this plainly: the gate is a manual job that no flow has a tool to run, and the rules that agents never push to the default branch or edit the gating files (G1, G4) are kept by the policy and the flows' instructions, not enforced by GitLab.
A design point that helped: the production gate is a manual GitLab job, not a step an agent is asked to skip.
Accomplishments that we're proud of
- Live, on 23 Oct (recorded for our video): a change with a planted bug turned pipeline 2981057357 red at 12:20:11 UTC. The pipeline fixer opened merge request !5 with a one-line code fix at 12:21:15 UTC, 64 seconds later, and the merge request's pipeline 2981062698 passed at 12:21:52 UTC. Asked in a comment, the MR policy reviewer posted 3 diff notes and an audit note with the verdict "changes requested": the fix branch also carries the feature, so the merge request is larger than its description says. MR !5 is still open and not merged: that is a person's decision.
- On 20 Oct: 74 seconds from a red pipeline (2968456655, a change we broke on purpose) to the pipeline fixer's fix merge request !3, and 2 minutes from red to a proven green fix. It changed the code, not the test.
- The release agent wrote the release issue with notes and evidence 2 min 15 s after a green pipeline; the remediator filed its two findings within 3 min 41 s of the scan.
- 9 of 9 lifecycle stages touched in one project.
- 3 owner actions per release: reading the review, merging, and running production. No flow has a tool to merge or to run production.
- 96 seconds from merge to a deployed staging site (median of four merges, 90–98 s).
- Production shipped as GitLab Release v0.51.0 after the manual production job was started from the owner's account.
What we learned
Most of the work was not the prompts. It was deciding, rule by rule, what an agent may do alone, and then making GitLab enforce what our role allowed: toolsets without dangerous tools and a manual production job. Code owners are named for the policy files, but our role could not make their approval required. When a tool or a permission was missing, the right fix was a narrower path, not more trust.
What's next for Release Desk
A protected-environment approval in place of the manual job, a project token so the monitor opens its own incidents, per-team policies, and tests for the policy itself.
Built With
- dependency-scanning
- gitlab
- gitlab-ci
- gitlab-duo-agent-platform
- gitlab-pages
- javascript
- node.js
- sast
- secret-detection
- yaml
Log in or sign up for Devpost to join the conversation.