🪶 A note on how this was written. This article was co-authored with the support of Claude, Anthropic's AI assistant. It draws on the principles and documentation developed while building and running the real-world working examples it describes.

We've all heard it said: AI makes developers ten times faster. It's half true. AI has made writing software dramatically cheaper. It hasn't made running it any cheaper: the patching, the configuration, the certificates, the evidence that it is secure and handles people's data properly. Unless we point the same tools at that half of the job, we simply ship more software and accumulate risk faster.

Over the last few weeks I've been building a small platform with an AI coding agent (Claude Code) to test the alternative. I call it Governed NoOps: the agent does the routine running and keeps the compliance evidence current, and people keep the decisions where a second pair of eyes matters. Below I outline what that looks like, the three principles behind it, and where its limits are. This is the last of five parts: parts 1 to 4 take each idea in turn, and this one brings them together.

If you build on a hosted AI app builder, the platform carries part of this for you: the servers, the certificates, the patching of its own runtime. It doesn't carry what you build on it. The packages your app pulls in, how it controls access to its data, and who can push a change live stay yours. In 2025 a researcher found 170 of 1,645 apps built on Lovable that let anyone read or write their data, because access rules had been left out; Lovable disputed the vulnerability on the grounds that each customer is responsible for their own app's data. The principles below apply whoever hosts you. I self-host on AWS because there every layer is mine to see and to govern. The FCA says the same to regulated firms in its October 2026 review of AI in financial services: they "can outsource AI services, but remain responsible for them".

Building got cheap, running didn't

Every application an AI assistant helps you ship comes with a long tail: dependencies that need patching, configuration that drifts, a privacy notice that should match what is actually logged, audit evidence that was assembled once and never refreshed. None of that got cheaper.

At the same time the threat has moved the other way. Attackers, increasingly with AI help of their own, turn a published vulnerability into an exploit faster than ever, so any vulnerable software is more likely to be found and used, and sooner.

Risk leaders experience this as "more software, same control team". Engineers experience it as toil. But the asymmetry is a choice: the same tools that write the code can maintain and evidence it.

Introducing Governed NoOps

Governed NoOps: the people who own an application hold only its content and its decisions. Hosting, security, upkeep and compliance evidence are provided, enforced and kept current by the platform and its agents.

NoOps isn't new; Forrester's Mike Gualtieri coined it in 2011. It describes the outcome for the application owner, not a claim that no operations happen. In the same way that serverless means you don't have to look after the servers, rather than that there are none, the work still happens. It's done by code and agents, on rules written in advance.

Governed is the part that matters for risk. It means two things: every automated action follows a written policy, and any action that could do serious harm needs a second, independent actor. Plain NoOps outsources operations and hopes; traditional governance has people doing the checks by hand, periodically. This sits in between.

The set-up at a glance

It helps to see the whole thing before the principles. All the work happens in code. I work with Claude Code, either in VS Code or in the browser, and every change it makes goes to GitHub as a pull request. GitHub holds one repository for the platform and one for each site's content, runs the checks, and does the deploying. No agent deploys from a laptop or a chat session: deploys reach AWS only through GitHub Actions, signing in with short-lived credentials issued for each run.

High-level design in three columns. Where work happens: Claude Code (VS Code or the web; branches, fixes, pull requests) and Andy (reviews and merges, confirms staging; uses VS Code, Claude Code, the AWS console and GitHub). GitHub: repositories (aws-platform for infrastructure, one per site for content), Actions (checks on every pull request, deploys with no stored keys), the dependency round (grades updates by CVSS, merges on the clock) and the backup job (weekly, every repository, add-only to locked storage). The AWS account, from loosest to tightest control: sites (staging from any branch, production from main by hand), the platform defined in code (hosting, certificates, DNS, security headers, mail), and the guard rails (roles and permission boundary, audit trail, locked backups), which are changed by hand only, never by a deploy.High-level design in three columns. Where work happens: Claude Code (VS Code or the web; branches, fixes, pull requests) and Andy (reviews and merges, confirms staging; uses VS Code, Claude Code, the AWS console and GitHub). GitHub: repositories (aws-platform for infrastructure, one per site for content), Actions (checks on every pull request, deploys with no stored keys), the dependency round (grades updates by CVSS, merges on the clock) and the backup job (weekly, every repository, add-only to locked storage). The AWS account, from loosest to tightest control: sites (staging from any branch, production from main by hand), the platform defined in code (hosting, certificates, DNS, security headers, mail), and the guard rails (roles and permission boundary, audit trail, locked backups), which are changed by hand only, never by a deploy.
Work flows through GitHub; only the guard rails are changed by hand.

The AWS account has three layers. The platform (hosting, certificates, DNS, security headers and mail) is defined in code and deployed by the pipeline. The sites are the content each site's repository uploads. Around both sit the guard rails: the roles and permission boundary that fence in what any deploy can do, the audit trail and the locked backups. Only I change those, by hand, so the pipeline can't alter the core restrictions.

From idea to live: dev → staging → production

Every change travels the same three steps, and each step is a separate piece of the architecture, not just a label:

Three stages, left to right. Dev: a branch and its pull request, worked on by Claude Code; it gets there when Claude Code opens a pull request; protected by checks on every pull request (tests, security, supply chain and a preview of AWS changes), and nothing deploys from a pull request. Merging leads to Staging: a full copy of each site, built from the same code as production; it gets there automatically on merge to main; protected by its own certificate, bucket and role, so it can't reach production, hidden from search engines, watermarked and smoke tested. Confirming leads to Production: the live site; started by hand once Andy has confirmed staging, from main only; protected by a deploy role only main can use, and a smoke test at the end.Three stages, left to right. Dev: a branch and its pull request, worked on by Claude Code; it gets there when Claude Code opens a pull request; protected by checks on every pull request (tests, security, supply chain and a preview of AWS changes), and nothing deploys from a pull request. Merging leads to Staging: a full copy of each site, built from the same code as production; it gets there automatically on merge to main; protected by its own certificate, bucket and role, so it can't reach production, hidden from search engines, watermarked and smoke tested. Confirming leads to Production: the live site; started by hand once Andy has confirmed staging, from main only; protected by a deploy role only main can use, and a smoke test at the end.
Each stage is its own piece of the architecture, with a gate between.

The link to the architecture is that staging and production are built from the same code, so staging is a faithful rehearsal rather than an approximation. They're separate stacks with separate roles, so a mistake or a compromise in one stays there. The guard rails sit outside this path altogether: they're never deployed by the pipeline at either stage.

⚠️ The production gate is me starting the run, because GitHub's built-in approval step isn't available for private repositories on the free plan. And dependency updates are the one exception to "I confirm staging": the update round takes them to production on their severity clock unless I hold one, because waiting on me would leave known vulnerabilities open for longer.

The platform does the heavy lifting

Each application should hold only what is unique to it. Everything that repeats lives once, in a shared platform defined in code, and is kept current there; this is often called a "paved road". In my case one repository defines everything in AWS (hosting, certificates, DNS, security headers, deploy roles) and each site's repository holds only its content. The platform hosts two sites today, with more joining, and adding the next one costs its content, not another stack to look after.

The upkeep runs itself. Several times a day a scheduled job looks at each identified dependency update and grades it by the most severe vulnerability it fixes (its CVSS score). When an update breaks the build, a scheduled agent session fixes it on its branch, and it may not skip or weaken a test to get there.

A paved road also makes the three Rs of security (Justin Smith, Pivotal) routine: repave, because everything is defined in code and can be rebuilt from it; rotate, because deploys use short-lived credentials issued per run; and repair, the patching below.

Most people building software with AI help have never had to decide how fast updates should go in, or even known that updates need applying, and shouldn't have to design a policy from nothing. So the defaults come with their reasons:

Kind of updateDefault waitWhy
Fixes a critical vulnerability (CVSS 9+)None, once tests passPublished holes are exploited within days; better briefly broken than vulnerable and open
Fixes a high one (7–8.9)1 dayStill urgent, but a day lets others find out if the fix itself is broken
Fixes a medium or low one3 daysLower risk, a little more time to catch a bad release
Routine, no known vulnerability14 daysNew releases are occasionally broken or hijacked; most are caught within days, so let someone else find out first
Major version28 days, and tell meIt may break things on purpose

Better briefly broken than vulnerable and open.

— Andy Boura

Waiting protects against bad new code; hurrying protects against known holes in old code. The policy waits by default and hurries only when a known hole is being fixed. A deadline backs it up: a security fix reaches production by its due date even if something else breaks, unless I've explicitly placed a hold - because broken and secure is better than working but hacked.

Propose the default policy with a plain-words reason for each setting, build it so it works once accepted, and mark every speed-versus-safety choice as a proposed default for a person to confirm.

Rule for your agent, from the companion skill

Compliance is generated so it remains evergreen

Evidence assembled by hand is stale the day after it's finished. The fix is to write each fact once, next to the thing it describes, and generate everything else from it.

Every access role in the platform is defined alongside a note of what it is for, what it can do and what it must never do. Every storage bucket and log states whose personal data it holds, why, the lawful basis and how long it is kept. A test fails if a note is missing, or if the stated retention differs from what the infrastructure actually enforces. From those notes the platform generates its access inventory, its record of processing required by UK GDPR Article 30 and its data inventory, and another test fails if any of them is out of date. It is assessed continuously against OWASP ASVS 5.0 and achieves Level 3, the highest. Each site's public trust page is written in plain words from the same reports: this blog's trust centre is one.

Keeping the note beside the code matters for review as much as for accuracy: whoever approves a change to someone's access sees what that access is meant to be for in the same diff. It's the same idea as the evergreen, close-to-the-source documents in Compositional Reporting, applied to compliance evidence instead of status updates.

Keep each annotation in the same file as the resource it describes, generate the reports from them, and add a check that fails when one is missing or a report is out of date.

Rule for your agent, from the companion skill

Manage the agent like a team member and maintain separation of duties

The key lesson I've learned is that none of this is new. Running an agent well takes the same skills as leading a team. In Effective Delegation I described Active Calibration: some decisions a team member owns and tells you about afterwards (Inform), some you work through together (Consult), and some are red lines they always bring to you (Escalate). The agent gets exactly the same treatment. Its instruction file is the "Empower" tactic from The Priority Matrix written down: guidelines and guardrails it can act on, and gates that trigger escalation. Its tests and checks are its definition of done. And briefing it well is Effective Business Writing by another name.

The question that decides each zone isn't "human in the loop or not?". It's: if the actor doing this alone were compromised, or simply wrong, what could it do? Where the answer is serious, a second, independent actor is required. That's separation of duties, with the agent as one of the actors. The FCA's review makes the same point from the other side: human review is a risk-based control, not a box to tick, and a reviewer without the authority, information and escalation route to challenge the output adds little.

Three zones, from least to most control. Inform, automation acts alone and reports after in one email: merge dependency updates by CVSS band after checks pass, promote them to production on the same clock, fix failing checks without skipping a test, regenerate compliance reports. Consult, the agent proposes and Andy approves before it happens: every other change arrives as a pull request that Andy merges, and production deploys only after Andy confirms staging. Escalate, human only, the agent stops and tells Andy: accept a risk with Andy's words quoted, deploy the account, audit and backup stacks by hand, change the agent's rules, CI, trust root or the update round, widen anyone's access. Underneath all three: only a human moves the line between zones.Three zones, from least to most control. Inform, automation acts alone and reports after in one email: merge dependency updates by CVSS band after checks pass, promote them to production on the same clock, fix failing checks without skipping a test, regenerate compliance reports. Consult, the agent proposes and Andy approves before it happens: every other change arrives as a pull request that Andy merges, and production deploys only after Andy confirms staging. Escalate, human only, the agent stops and tells Andy: accept a risk with Andy's words quoted, deploy the account, audit and backup stacks by hand, change the agent's rules, CI, trust root or the update round, widen anyone's access. Underneath all three: only a human moves the line between zones.
Nothing acts alone where it could change the rules.
  • Inform: the update round merges dependency updates on their clock once checks pass and sends one short report when anything changed; the agent fixes failing checks and regenerates the reports.
  • Consult: every other change arrives as a pull request that I merge, and production follows only once I've confirmed staging.
  • Escalate: only I accept a risk, and the record quotes my words. The account, audit and backup infrastructure is deployed by me, by hand. The automation refuses to merge anything that changes the agent's own rules, its CI, the trust root or the merge automation itself, or that widens anyone's access.

These aren't just habits. The roles the automation uses are fenced in by AWS permissions: they can deploy hosting, DNS and certificates, but they can't touch the audit trail, the account's own roles and policies, or the backups. Only I, signing in by hand, can change those.

Two design points are worth drawing out. First, the rules that govern the agent can't be changed by the agent alone; otherwise the autonomous zone can widen itself. Second, recovery doesn't trust the actor it recovers from: a weekly backup goes to locked storage, written by a role that can only add to it, so a compromised source account can't erase it.

Never merge a change to your own rules, CI, access policies or the automation that merges for you; propose it, and stop for a person.

Rule for your agent, from the companion skill

The limits and compromises of this approach

There are four trade-offs to mention:

  1. The autonomous zone trusts upstream. An update can merge without a person, so a poisoned package is a real path in. The 14-day wait on routine updates, actions pinned to exact commits and a supply-chain check in CI narrow it. Critical fixes skip the wait by choice. There is also defence in depth, with security checks on every change.
  2. Some rules are instructions, not permissions. Where I can, a rule is enforced by a role's privileges, so the agent simply can't break it. Some rules can't be put that way, such as when to stop and ask, so they're instructions in the agent's file, and an instruction can be misread. The checks and the second actor catch much of that, but not all of it, which is why I turn an instruction into a permission wherever I can.
  3. Generated evidence proves consistency, not correctness. It shows the documents match the code; it doesn't show the code is right. Independent testing still matters.
  4. It's NoOps for the owner, not no operations. Someone builds and keeps the platform, the agent's runs cost money, and the two-actor checks take a person's time. I chose the schedules by weighing cost against benefit and may need to adjust them if real-world threats change.

Here the second actor is me. In an organisation it's a different person or team, which maps directly onto the four-eyes controls you already run. It also speaks to the gap I was quoted on in the State of AI in Security & Development 2026 report, the lack of clarity over who is accountable when AI-generated code causes an incident: every action has a named, accountable actor, and the agent is never the only one on anything that matters.

In summary

  1. Point the AI at running and evidencing, not just building. If it only writes code, risk grows as fast as output.
  2. Write the facts once, next to the code, and generate everything else. Compliance stays current because it can't drift.
  3. Calibrate the agent like a new team member. Inform, Consult, Escalate, with a second actor on anything that could change the rules or widen access.

If you'd like your own agent to work this way, I've published the rules as a companion Claude Code skill under CC BY 4.0 (licence). It proposes the default policy above with its reasons, builds the automation behind a switch that you turn on, and never changes its own rules. Please read it before you adopt it: it's advice for you to review, not instructions for an agent to fetch and follow. That said, if you're currently doing nothing, please use it as it is.

I hope you find this helpful. I'm keen to hear how others are approaching it, so do let me know how you get on.