Generative AI

AI Agent Governance: How to Govern Coding Agents at Scale

Learn how to govern coding agents at scale by setting sensible access boundaries, preserving decision context, managing permissions over time, and adjusting controls based on operational evidence.

More Agent Autonomy Requires More Control

Bring LLM-powered apps from prototype to production

Discover a collaborative platform where teams work side-by-side to deliver LLM apps safely.

Bring LLM-powered apps from prototype to production

Discover a collaborative platform where teams work side-by-side to deliver LLM apps safely.

Key Takeaways

Coding agent governance needs to account for both what an agent is allowed to access and whether its actions still match the task it was assigned.

Teams should preserve approvals, scope changes, and important control decisions alongside execution traces so they can explain why a run was allowed to proceed.

Access, approvals, and evaluations should be reviewed over time as workflows change and operational evidence shows where controls are still useful.

An engineer working on a service might have Git access, package registry credentials, staging access and a few internal APIs configured locally. Give a coding agent a dependency update in the same environment and it can start with most of that access too, even though it may only need a small part of it.

The agent reads the package, checks where it’s used and runs the tests. One of them fails somewhere else in the repository, so the investigation moves with it. This is generally normal when it comes to older codebases. Files mentioned in the ticket are rarely the only files that matter once debugging starts.

Another engineer working specifically on authentication could be using the same permissions. NIST’s work on software-agent identity starts from a familiar enterprise problem: knowing which identity acted, what it was allowed to do and being able to prove that afterwards.

In this case, authorization isn’t really the disputed part. The run came in as dependency maintenance and is now changing authentication code.

Permissions and task scope

You could try to prevent that by narrowing access much further. Some of it is quite straightforward. There’s no obvious reason for production credentials to be present in a dependency-maintenance environment. Read access can cover more of the repository than write access, and credentials used for one run don’t have to remain valid afterwards.

File access gets awkward much faster since you usually don’t know the complete change surface when the task enters the queue. A test pulls another package into view, an old abstraction turns out to sit behind the failing path, or the useful debugging tool only becomes obvious after the first approach goes nowhere. 

Locking all of that down at intake means somebody has to keep reopening the task as the agent discovers perfectly ordinary things about the repository.

That doesn’t justify giving the run everything available to the engineer either. There’s a useful middle ground in restricting capabilities that clearly have nothing to do with the work without pretending the exact investigation path can be known in advance.

A connected MCP server may expose operations for reading, creating, updating and deleting data even though one workflow only needs to inspect it. Orq.ai’s MCP Gateway can restrict tool access by team and agent, so workflows don’t have to receive the same capabilities simply because they use the same integration. 

The authentication helper is less clean as removing write access might block a legitimate fix, while allowing the edit means the run has moved beyond the work described in the original ticket. Repository permissions alone won’t settle that.

Schema changes and rollout

A dependency update can be nearly finished before a database change appears. The application code has been updated, most of the tests are passing, and one remaining failure comes down to an assumption in the schema. 

Generating the migration isn’t necessarily difficult but shipping it can be.

If the new application version expects a column that doesn’t exist yet, the deployment order matters. Old and new instances may run side by side for a while, so both need to tolerate whatever state the database is in during that period. 

Existing rows might need backfilling, and that creates another ordering problem depending on whether the old application can read the new values and whether the new application can cope before the backfill finishes.

Rollback is where a simple-looking migration can become especially unpleasant. Reverting the application is easy enough until the new version has already written data in a shape the old version doesn’t understand. At that point “rollback” might involve another migration, a data restore or accepting that part of the change isn’t going backwards cleanly.

Stopping the agent before every command wouldn’t help much with any of this. If it has already run the same test suite several times, there isn’t much value in approving one more run. Routine file reads and package installs are similar.

For a migration, review is more useful around:

  • Whether old and new application versions can coexist

  • When the backfill happens

  • What recovery is still possible once the new version has started writing data

An additive column in an internal reporting database might already go through migration tooling the team trusts and has used hundreds of times. Put the same kind of schema edit on a payment path and the risk changes quickly. 

Now it can interact with live transaction data and application versions that can’t all be switched over at once.

For the Factory, we wouldn’t use the presence of SQL as the reason to stop a run. Existing database and deployment tooling can deal with routine cases. Review is more useful where rollout or recovery actually needs somebody to think about it.

What to keep from a run

An incident review three weeks later turns up a Terraform change made by the agent. There’s no shortage of evidence either: the model calls, tool activity, commands, files and timestamps are all in the execution trace.

Why was this run editing Terraform? A full execution trace can make that surprisingly annoying to answer. Long runs leave behind repository searches, file reads, retries, failed commands, package operations, unrelated test failures and several approaches that disappeared before the final diff.

All of that can help when debugging the agent, but it doesn’t necessarily tell you why the run crossed into infrastructure work.

The original assignment matters more here, along with any decision that changed it. If infrastructure work needed an approval, keep what was approved. If a security check had to pass before the run could continue, keep the fact that the requirement applied as well as the result.

That doesn’t mean wrapping every normal test in a new governance system. CI can remain CI. The extra record becomes useful when the Factory relies on a check as a boundary and, months later, the only evidence left is one command buried in a much larger execution log.


An approval might stay on the ticket because that’s already where engineers work, while another team may store the same decision as workflow state. An architecture rule could remain a required CI check.

Where the record lives matters less than whether somebody can later establish what the run was supposed to do, which important boundaries applied and whether any of them changed.

The model transcript is rarely the easiest place to reconstruct that.

How access changes over time

A workflow could start with one repository and a few tools then pick up another repository for a recurring job. An internal API that was originally read-only gets a write operation. One task can’t be completed in staging, so production access is added.

None of those changes has to look noticeably risky on its own, but a few months later the workflow can be carrying permissions that mostly reflect its history rather than what you’d give it if you were setting it up from scratch.

Microsoft’s work on agent identities includes human sponsorship, access reviews, expiry and revocation. Those are familiar identity lifecycle controls, and they fit this problem well. 

If a workflow is retired, its API keys and service identities should go with it. Adding the first production credential is also worth another look, as is giving an existing tool a destructive operation or access to a new category of data.

The same drift can happen when a workflow moves between teams. Something built around one repository, deployment process and set of assumptions gets reused elsewhere because it already works well enough. 

Central and local rules

There’s little reason for every repository to maintain its own approved model-provider list, or for each team to invent separate rules for identity, production credentials and access to sensitive data.

Something labelled database approval might exist because a bad migration can destroy data, because two applications have to move together during rollout, or because of what the data contains rather than anything unusual about the migration itself.

Calling all three database approval makes them look like the same control, even though the reason for each one is different.

A compatibility check can look unnecessary from inside the repository while still protecting a downstream consumer that hasn’t moved in years. The owning team probably knows exactly why that ugly check is still there and a central policy engine only sees the check.

We’d keep the genuinely common controls at the platform level and be much more reluctant to pull this sort of application knowledge out of the service. 


Centralizing it doesn’t remove the dependency on local knowledge. Sometimes it just hides where that knowledge came from.

If several teams independently end up protecting the same thing for the same reason, that’s a good sign the control may belong in the platform instead. Usually you only know that after the pattern has shown up a few times.

When to change the controls

A reviewer gets added because a change feels risky. An evaluation becomes mandatory because it catches something useful during testing. A security check stays near merge because that’s where it already runs. Some of those choices will hold up once the workflow is in regular use, and some won’t.

Reviewers may keep approving the same class of dependency change without asking for anything different. A check near merge might catch the same failure often enough that running it earlier would save a lot of wasted work. Another evaluation might generate plenty of results without having much relationship to the runs that later need rework.

An evaluator can already be configured as a guardrail in Orq.ai. The API makes that explicit in the evaluator configuration:

"guardrail_config": {
  "type": "boolean",
  "value": true,
  "enabled": true,
  "alert_on_failure": false
}

That gives the workflow a concrete control to revisit. If the evaluation is consistently useful, it may deserve to stay in the path or move earlier. If it produces noise without predicting rework, keeping it there just because it was part of the original setup doesn’t buy much.

We’d change the workflow when that evidence starts piling up rather than preserve the original controls because they looked sensible six months ago. A useful check can move earlier, and an approval that has become mostly ceremony can come out. If rework starts climbing afterwards, put it back or look at what changed.

A routine package upgrade and a database migration don’t need to keep the same review path forever.

The history is only useful while the workflow remains broadly comparable. A long stretch of safe staging-only runs says little once somebody adds production credentials, and giving the agent a destructive tool it didn’t have before changes the conditions again.

A Software Factory needs to keep that operational history visible across runs: where people are spending time, where failures or rework are showing up, what the models cost and what happens after a change moves forward.

A team might let routine dependency work run almost unattended while still stopping on schema changes, infrastructure work or anything touching production. Those boundaries can move independently rather than being reduced to one autonomy score.

If you want to see how Orq.ai handles those controls across a Software Factory, book a demo here.

FAQ

What is AI agent governance?

How is coding agent governance different from traditional AI governance?

How much autonomy should a coding agent have?

Sohrab Hosseini image

Sohrab Hosseini

Co-founder (Orq.ai)

About

Co-founder of Orq.ai. Previously led and grew SaaS companies as COO/CTO and worked as a McKinsey associate.

Create an account and start building today.

Create an account and start building today.

Create an account and start building today.

Create an account and start building today.