Inspiration
The code is the easy part. You finish the feature in an afternoon, then spend two days on everything downstream: the review, the security sign-off, the release notes, the deploy that works on the third try, the five tabs you keep open to watch it all. That downstream part is what "Life After Code" is about, and it's where our evenings go. So the question we actually wanted answered was blunt: how much of it can the GitLab Duo Agent Platform take off our hands — not advise us on, take?
What it does
DevFlow is a command center for the part of the job that starts after you push. It's a Next.js dashboard on a FastAPI backend, wired to your real GitLab account, with a workflow builder for stringing the steps together.
The engine underneath is an autonomous ship flow on the GitLab Duo Agent Platform. Three agents run it:
Inspector is the one that can say no. It reads the merge request and looks for the things that would actually hurt an agent platform — a token getting stored or logged, step-up auth skipped, an OAuth scope quietly widened. It reports what it finds and hands off. It never pulls the trigger itself.
Builder does a readiness pass: will this package cleanly, will the container build and the Model Registry entry go through. A quick yes-or-no before anything moves.
Shipper is the one with its hands on everything. If Inspector and Builder both clear it, Shipper takes the change the rest of the way with nobody in the loop — merges to main, builds the container, registers the model, cuts the release, flips a feature flag, deploys to Cloud Run, smoke-tests the live URL, and writes up a scorecard. It has exactly one rule it won't break: fail closed. A credential or step-up-auth flag from Inspector and it stops dead. And it never dresses up a result it didn't get.
We didn't mock this. We pointed it at a real merge request that added a GitLab pipeline-health endpoint, and watched it go: diff read, change cleared, merged, and all eight pipeline stages green — container in the Container Registry, a new version in the Model Registry, Release v0.1.22 out the door with an auto-collected evidence file, a feature flag set, and the service live on Cloud Run with the smoke test passing. The scorecard didn't paper over the two non-blocking dependency warnings either; it listed them.
How we built it
The agent layer is three custom agents and one flow (flow-registry v1 YAML), all published public to the AI Catalog so anyone can reuse them. Shipper is the supervisor; Inspector and Builder run under it as subagents. All three are on Claude Sonnet through Vertex.
The app is Path B. We took an MIT-licensed project we already had, brought it into GitLab, and put it live — Next.js 16 on standalone output and a FastAPI backend baked into one container, with a real GitLab connection that checks a token against the API and pulls back your actual projects, pipelines, and MRs.
The pipeline is where the downstream work actually lives. Eight GitLab CI stages: tests; SAST and secret detection; a secret sweep; a kaniko container build; a Model Registry push over the MLflow-compatible API; a tagged Release; a feature flag; the Cloud Run deploy; and a smoke test against the URL that came back. The agents kick it off and read the real job traces as they land — the runners do the heavy lifting, the agents decide and report.
Every GitLab surface DevFlow uses
The goal was to lean on the whole platform, not camp in one feature:
- AI > Agents: Inspector, Builder, Shipper, each with its own scoped GitLab toolset (Get Merge Request, Read Files, Grep, Run Command, Create MR Note), on Claude Sonnet via Vertex.
- AI > Flows: one autonomous flow, DevFlow Autonomous Ship — Shipper supervising the other two, fail-closed on credential and step-up-auth defects.
- AI > Catalog: all four items public and reusable.
- AI > Triggers and Sessions: a service account on composite identity, kicked off by a mention, an assignment, or a fresh MR; every run is a Session with the full tool-call log.
- Secure: Semgrep SAST, Secret Detection, a blocking secret sweep, and a dependency audit on production deps that's allowed to warn without failing.
- Build: the eight-stage pipeline; the container is built with kaniko and pushed to the Container Registry.
- Model Registry: every ship registers a fresh model version through the MLflow-compatible API.
- Releases: a tagged Release is cut on its own, carrying an evidence file of exactly what went out.
- Feature Flags: a release flag is created and driven through the Feature Flags API.
- Deploy to Cloud Run:
gcloud run deployputs the service up; the verify stage smoke-tests it. - Operate > Environments: the production environment and its deploy history are filled in by the flow's own service account — these deploys came from the agent, not a person clicking.
- Code > Merge Requests: the whole thing hangs off a real MR; Shipper does the merge over git, because the composite token can push but not merge through the API.
- App integration: the live GitLab connection validates a token and pulls real data, and other tools reach in through an Auth0 Token Vault so no agent ever touches a raw credential.
Challenges we ran into
Three stick out. First, autonomy with a hard floor: the whole pitch is "no human gate," but a DevOps tool that ships anything would be a liability, so the harder design work went into fail-closed — getting Inspector's credential and step-up-auth checks precise enough that Shipper can be trusted to run unattended and still slam the brakes on the one class of defect that matters. Second, a scoping bug early on: Inspector flagged a clean change because of a problem that was already sitting in main, so we taught it to judge only what the diff itself brings in. Third, that merge wall — the composite-identity token can push but returns 403 insufficient_scope on an API merge, so Shipper merges over git instead. Threaded through all of it: the agents only ever report what the diff and the job traces actually say, so there's no invented green and no URL nobody read.
Accomplishments we're proud of
It ships for real, to a live Cloud Run service, not a demo stub. It reaches across the whole downstream stack — Model Registry, Feature Flags, Releases — instead of stopping at build-and-deploy like most "CI/CD bots." And when it's unsure, it stops and says so, warnings and all, rather than guessing green.
What we learned
The interesting decision wasn't "can it be autonomous" — it was "should it be, here." For a command center whose whole value is speed, hands-off with a non-negotiable fail-closed rule earns its keep. For code where a wrong call is expensive, you'd want a person at the gate. What surprised us is that the platform treats that as a dial, not a fork: the same building blocks let one flow run unattended and another stop and ask. The autonomy level is a design input, not something you're stuck with.
What's next
- Encrypt the stored GitLab token at rest — the flow raised this one on itself.
- More flows: dependency-bump triage, incident rollback, release-note drafting.
- Make the readiness rollup smarter about an in-flight pipeline versus a finished green one.
Built With
- auth0-token-vault
- ci/cd
- claude-(anthropic)
- docker
- fastapi
- gitlab
- gitlab-duo-agent-platform
- google-cloud-run
- kaniko
- mlflow
- next.js
- python
- semgrep
- sqlite
- typescript
Log in or sign up for Devpost to join the conversation.