DEV Community

Cover image for Don't Give AI Agents Root. Let Them Open Pull Requests.
Andrey Lesnikov
Andrey Lesnikov

Posted on

Don't Give AI Agents Root. Let Them Open Pull Requests.

Would I give an AI agent root access to a production Kubernetes cluster? No. Would I let it open pull requests? Gladly.

That sounds like a contradiction until you look at where the real control point in a GitOps setup sits. It isn't the cluster. It's the path a change takes before it reaches the cluster.

The idea that clicked for me

Earlier this month Mauro Morales, a CNCF Ambassador, published Don't give AI agents root. Make them propose the next system state. on the CNCF blog. His core argument is simple: an agent should inspect the current state of a system and propose the next one. It should not apply that state itself. The proposal goes through the same software factory every human change goes through: review, CI, tests, build, signing, release, deployment.

One line from his post stuck with me: if you give an agent root and expect a well-written AGENTS.md to prevent an unrecoverable mistake, you are fooling yourself. The model is nondeterministic. You can't guarantee the outcome, so you have to guarantee the path instead.

His post focuses on the operating system layer and immutable hosts. I want to look at the same principle from the Kubernetes and GitOps side, because for many platform teams the boundary already exists. We just don't always enforce it properly for bots.

GitOps already drew the line

If you run Argo CD or Flux, this model is almost boring. The rule is already there: what is not in Git does not end up in the cluster. The controller reconciles toward the desired state in the repository, and drift gets corrected.

So the safe shape for an agent looks like this:

  • Read access to metrics, logs, events and the manifests in Git, so it can diagnose problems.
  • Write access to a branch, so it can propose a change as a pull request.
  • Nothing else. No cluster-admin, no kubectl apply against production, no direct access to the sync controller.

The agent becomes one more contributor. Its change is a diff that a human can read, CI can test and policy can reject. If it's wrong, you close the PR. If it was merged and turns out wrong, you revert a commit, and you know exactly which commit and which identity introduced it.

That traceability is the part people underestimate. It's not only about stopping bad changes. It's about knowing afterwards what changed, when and who or what proposed it.

The gap: "root with a few extra steps"

Here is the point from Mauro's post that I think matters most: the agent's identity may propose, but it must not approve, merge, or change the pipeline. Otherwise you have just replaced root with root plus a few extra steps.

This is exactly where real setups tend to fall short. A common pattern looks like this:

  1. Someone creates a bot account or a GitHub App for the agent.
  2. Setting up fine-grained permissions takes time, so it gets admin on the repository "for now".
  3. Branch protection has an exception for that account, or the bot can approve its own PRs through a second token.
  4. The pipeline definition lives in the same repo, and the bot can edit it.

At that point the PR flow is theater. The agent can propose a change, approve it, merge it and adjust the CI job that was supposed to catch it. Argo CD then faithfully syncs whatever landed on main. The cluster is protected by GitOps in theory and wide open in practice.

What I check in a setup like this

None of this needs new tooling. It's mostly configuration you probably already have, applied consistently to non-human identities:

  • Separate identity per agent. No shared tokens with humans or other automation, so the audit trail means something.
  • Branch protection without bypass for bots. Required reviews from humans, required status checks, no admin override for the agent account.
  • No self-approval. The identity that opened a PR can't be the one that approves it, and there is no second token lying around that makes that possible.
  • Pipeline files are protected. Changes to CI definitions, Argo CD Application objects or policy files go through CODEOWNERS with a human owner.
  • Short-lived, scoped credentials. The agent's read access to observability data should expire and be limited to what it needs.
  • Policy in CI fails closed. If a policy check can't run or can't decide, the result is "not approved", never a silent green.

The last point deserves extra emphasis. A gate that passes when it has missing data is not a gate. For agent-proposed changes that matters even more, because the volume of proposals can grow much faster than the attention of the reviewers.

Where this leaves us

I don't think the answer is to keep agents out of production work. They are useful for reading signals, correlating logs and proposing a fix, especially when a tired on-call engineer would be doing it at 3 a.m. The answer is to give them the same contract every engineer on the team already has: you can suggest anything, and the system decides what gets applied.

GitOps gave us that contract years ago. The job now is to make sure the bot account actually lives under it, instead of quietly sitting above it because it was quicker to set up that way.

So I'll ask the same question I asked on LinkedIn: how much is an agent allowed to do in your production environment today, honestly?

Top comments (0)