Inspiration
AI agents are starting to hold real production credentials — a support bot with Stripe write access, a reports bot with database read access — and those credentials are usually long-lived, broadly scoped, and reviewed like a password: once, by hand, at setup. A single prompt injection then has the blast radius of that standing credential, not of the one task the agent was asked to do. Scoping tokens tighter is the obvious fix; the part nobody builds is what happens after the policy exists — policies are code, and a one-line YAML change can silently hand hundreds of agents a new privilege in a diff a human reviewer skims in four seconds.
What it does
Agent Keyring mints 60-second scoped tokens from YAML-declared policies — mint → use → review → drill. A policy engine enforces resource, action, TTL, justification, rate limit, and per-request constraints (like a dollar cap on a refund), and every mint, verify, revoke, and denial lands in a hash-chained, tamper-evident audit log. The hero isn't the broker — it's three GitLab Duo-powered gates that keep policy changes honest: Blast-Radius explains a policy diff's blast radius in plain English and blocks merges above a risk threshold; Scope-Fuzz replays real adversarial requests that used to be denied against the new policy and blocks on any flip to allow; Breach-Drill runs on a schedule, proving revocation actually works end-to-end rather than trusting that it does. An MCP server also lets GitLab Duo itself mint or revoke tokens through plain-language chat, so judges can try it themselves.
How we built it
Python/FastAPI service, SQLite with a hash-chained audit log, HMAC-signed tokens (a thin adapter so swapping in Cloud KMS is a one-file change). The review work runs through GitLab Duo exclusively — no direct model-provider API calls anywhere in the codebase; a deterministic rule-based verdict is the fallback when Duo isn't reachable, never a different provider. The three gates run both as real GitLab CI/CD jobs (.gitlab-ci.yml) and as GitLab Duo Custom Flows (Flow Registry v1). Full GitLab security stack enabled (SAST, Secret Detection, Dependency Scanning, Container Scanning). Deployed to Cloud Run via Cloud Build and Secret Manager. The demo video is code-driven — Remotion compositions replaying real captured gate output as typed animation, narrated with free neural TTS, spliced with actual Playwright-recorded browser footage of the live dashboard (real mints and denials happening on camera, not staged).
Challenges we ran into
GitLab's raw Duo chat-completions REST API turned out to be internal-use-only on GitLab.com, so the CI-job path had to be built with a deterministic fallback from day one rather than assuming Duo access. Two real bugs surfaced only once we opened actual merge requests against the live GitLab pipeline: the python:3.11-slim CI image has no git binary at all, which crashed both gates before they could even load a policy; and GitLab's MR pipelines check out a detached HEAD with no local branch named main, which silently made the "old" policy look nonexistent and produced false verdicts — fixed by preferring GitLab's own CI_MERGE_REQUEST_DIFF_BASE_SHA over branch-name resolution. We also had to retrofit the whole review path to never touch a model-provider API directly, which meant rewriting the LLM client, the flow YAMLs' model blocks, and every doc and narration line that assumed otherwise.
Accomplishments that we're proud of
The production /mint endpoint and the Scope-Fuzz adversarial replay call the exact same evaluate_mint() function — there's no second implementation to drift. We verified the gates on real GitLab infrastructure, not just locally: a deliberately risky policy MR gets blocked (10/10, real diff, real pipeline run), and a genuinely safer one gets approved (2/10) — confirmed from live job logs, not assumed. The audit chain's tamper-evidence is checkable with one HTTP call. And the demo video is honest: real terminal output, real browser recording, real CI/CD stage names, all under three minutes.
What we learned
Policies-as-code is the last mile of least-privilege for AI agents, and static diffing plus adversarial replay catches the subtle stuff human review misses — the "this change quietly removed the rate limit on a write scope" kind of broadening. We also learned not to trust a CI pipeline until you've actually watched it run: two of our real bugs were invisible in local testing and only showed up in GitLab's actual detached-HEAD, git-less container environment.
What's next for KeyRing
Swap HMAC for Cloud KMS asymmetric signing. Build the Shadow-Rollout agent (dual-run a new policy against mirrored traffic before promoting it). Add a Sealed-Audit Verifier publishing chain heads to a write-only Cloud Logging sink for external transparency. Run the custom-flow YAMLs through GitLab's own Flow Creator agent for full component-level validation now that Custom Flows is confirmed enabled on the project.
Built With
- agent
- ci/cd
- duo
- flows
- gitlab
Log in or sign up for Devpost to join the conversation.