A few years ago, the most powerful AI tools in a developer’s workflow helped write code. Today, they can do much more. It’s increasingly common to hand an AI agent a task like:
Read this repository, refactor the authentication service to match the new specification, run the test suite, and open a pull request if everything passes.
The agent reads files, analyzes dependencies, executes commands, modifies code, and interacts with external systems. In many cases, it can complete meaningful chunks of engineering work with minimal supervision. The shift sounds incremental until you realize something important: We’re no longer delegating suggestions. We’re delegating actions.
What’s interesting is that the biggest challenge increasingly isn’t whether agents can perform these tasks. In many cases, they already can. The harder question is whether developers trust them enough to delegate meaningful work. The bottleneck is shifting from capability to confidence.
While reading Srini Sekaran’s recent announcement introducing Docker AI Governance, one statement stood out:
The more I thought about it, the more it felt less like a marketing tagline and more like a useful way to understand what is changing about software development.
The last few years of developer tooling can be viewed as a progression. First, AI tools assisted developers by generating snippets and answering questions. Then, copilots emerged, helping developers complete larger tasks within existing workflows. Now we’re entering the era of agents. Unlike earlier tools, agents don’t just recommend actions. They increasingly perform them. Once software begins taking actions instead of offering suggestions, the governance conversation changes fundamentally.
One thing I’ve noticed while working on AI projects and experimenting with agent-based workflows is how quickly the trust boundary moves.
When I first started using AI tools, I mostly treated them like a second set of eyes. I’d ask questions about a codebase, sanity-check an approach, generate a small piece of code, or help make sense of documentation. The tools were useful, but they weren’t doing anything on their own. Every action still depended on me deciding what happened next. That changed as coding agents became more capable.
Tasks that previously involved copying code between windows increasingly became workflows where an agent could inspect a repository, modify files, run tests, and iterate on failures with minimal supervision. The productivity gains were undeniable, but so was the realization that the agent now had access to the same environment, credentials, and tooling that I did.
As a Docker Captain, this is what makes the current conversation around AI governance so interesting to me. The challenge isn’t simply that models are becoming more capable. It’s that they’re increasingly interacting with real systems rather than generating text in isolation.
Once an agent can execute actions on your behalf, the challenge is no longer just capability. Developers need confidence that the agent will operate within understood boundaries. Governance becomes important not only because it protects systems, but because it helps people trust the systems they are using.
Most developers aren’t worried about whether agents can generate code. They’re worried about whether the agent will operate predictably once it starts interacting with real systems. That hesitation often comes from the fact that our existing trust models were designed around human operators, not autonomous software.
Most enterprise security controls evolved around a relatively simple assumption: humans perform actions and systems enforce controls around those actions. Source code flows through repositories. Changes pass through CI/CD pipelines. Production workloads run inside managed environments. Identity systems determine who can access what. Network controls restrict where workloads can communicate. The security stack works because work typically moves through predictable checkpoints. Organizations know where to observe activity, apply policy, and collect audit trails.
AI agents introduce a different operating model. An agent running on a developer’s machine can inspect repositories, execute commands, install packages, access local files, query APIs, and interact with external tools all within a single session. More importantly, it often does so using the same permissions as the person operating it. From the organization’s perspective, a significant amount of work is shifting outside the systems that were originally designed to govern it. The laptop is no longer just where code is written. It is increasingly where decisions are executed.

Figure 1. Traditional security governs workflow checkpoints. Agent governance must account for execution at runtime.
A coding agent doesn’t need to wait for a pull request before interacting with a codebase. It can analyze and modify files long before a change reaches a repository. It can access credentials available to the local environment. It can connect to external services using the same permissions available to its operator.
Consider a common scenario: an agent is asked to investigate why an integration test is failing. To debug the issue, it might inspect configuration files, generate temporary scripts, install additional dependencies, execute diagnostic commands, and repeatedly rerun the test suite before a human ever reviews the result. None of these actions are unusual, but they illustrate how much activity can now occur directly within the developer’s environment. This doesn’t make agents inherently unsafe. It does mean that many existing security assumptions deserve a second look.
One common response is to rely on instructions. Tell the agent not to access sensitive files. Tell the agent not to call external services. Tell the agent not to perform risky actions. These instructions are useful, but they are fundamentally different from enforcement. A prompt can influence behavior. A runtime can restrict behavior. That distinction becomes increasingly important as agents gain more autonomy. Security has traditionally been strongest when controls exist below the application layer. Filesystem permissions don’t suggest restrictions; they enforce them. Network policies don’t ask whether traffic should be blocked; they block it. The same principle applies to AI agents. If an organization wants confidence in what an agent can and cannot do, those guarantees ultimately need to exist at the layer where actions are actually executed.
When I simplify the problem, most agent activity falls into two categories. The first is execution. Agents read files, modify code, install software, execute commands, and open network connections. The second is tool usage. Agents interact with external systems through APIs, integrations, and MCP tools. These might include GitHub, Jira, cloud platforms, internal services, communication tools, or customer systems. Both paths create tremendous value. Both paths can also introduce risk. Governing only one of them leaves a blind spot. An organization might carefully control external tool access while overlooking what an agent can execute locally. Or it might secure local execution while providing broad access to external systems. Effective governance requires visibility and control across both surfaces.
The question for many organizations is no longer whether AI agents will be adopted, but how they can be adopted responsibly. That decision is already being made in engineering teams around the world because the productivity gains are real. The more important question is how organizations can embrace agent autonomy without sacrificing visibility, accountability, and control. Just as importantly, developers need confidence that they understand those boundaries. The easier it is to understand what an agent can access, execute, and modify, the easier it becomes to incorporate agents into everyday workflows. Traditional security models were built around infrastructure boundaries. Agent governance increasingly requires runtime boundaries.
These questions are quickly becoming infrastructure questions, not merely AI questions. Because if AI agents are becoming active participants in software delivery, then the environments they operate in deserve the same level of attention that we have historically given to production systems.
The laptop is no longer just where software gets written. Increasingly, it’s where software acts. And that’s why “your laptop is the new prod” feels less like a prediction and more like a description of where modern development is already headed. The real challenge isn’t simply giving agents more autonomy. It’s creating environments where developers feel comfortable using that autonomy. Because the future of agentic development may depend less on what agents are capable of doing and more on what developers are willing to trust them to do.
In Part 2, we’ll explore what governance looks like at the runtime layer and why isolation, policy enforcement, and controlled tool access are becoming foundational building blocks for agentic systems.
Open-weight models and data sovereignty take center stage as Palantir challenges frontier model companies over ownership, security, and competitive risk. Nvidia's NeoCloud backstop and SoftBank's NeoCloud plans aim to expand GPU access and reshape infrastructure financing for AI builders. KPMG, Stripe, and academic research document a surge in solopreneurship as AI lowers startup activation costs and enables solo founders to scale revenue rapidly.
The AI Daily Brief helps you understand the most important news and discussions in AI.
Subscribe to the podcast version of The AI Daily Brief wherever you listen: https://pod.link/1680633614
Get it ad free at http://patreon.com/aidailybrief
Learn more about the show https://aidailybrief.ai/
To take AI beyond automation into true intelligence, we need to include empathy.
In this post, I want to discuss a real danger we may face with AI agents, drawn from a specific interaction I witnessed on LinkedIn.
Recently, on a post where someone was presenting ideas about “intelligent” AI agents, the author claimed that if a customer fails to pay a SaaS subscription, the system will block access, trigger an automatic charge and apply a late fee, all without any human intervention. This was promoted as something futuristic and advanced.
I saw a disaster waiting to happen, especially considering that the same outcome could be achieved without AI, if that were ever desirable.
There are many situations that can lead to a missed payment. What happens, for example, if the client’s assistant falls ill and cannot process the payment? What if they had a medical emergency and no one took over the task in time? What if the invoice never arrived? What if the client is going through a temporary hardship, but has been a loyal customer for years? Does that count for nothing? Where is the human element in the consumer relationship?
These are not far-fetched hypotheticals. They have happened with my own SaaS customers.
Automation without humanity is oppression at scale.
We could easily implement the AI agent’s suggestion and follow the same path: missed payment, blocked account and a fine applied. But is this the right approach?
My background in neuroscience and communication reshaped how I think about the human side of technology-driven processes. That plus some life experiences lead me to consider the broader context:
A genuinely intelligent AI agent does not block first and ask questions later. It recognizes patterns. Has this client always paid on time? Then the delay probably has a reason. The system could send an empathetic notification before taking any action. It could offer a courtesy window. It could escalate the issue to a human when the situation is ambiguous. An intelligent agent could prioritize retaining a client, which is often worth far more than punishing a late payment.
For those building AI agents: before you automate punishment, automate empathy. Your system will reflect your values. If you build without considering the person on the other side, you could be constructing a scalable injustice machine, one capable of generating damages that could exceed any original problem the AI was trying to address.
Technology without empathy is not innovation. It is regression with a polished interface.
We are at a moment where the architecture and design decisions we make today will shape how millions of people are treated by systems over which they have no control.
And to help avoid building oppressive and unjust machines, we need to cultivate empathy and uphold our organizations’ principles, with the greater purpose of serving people rather than merely extracting value from them.
Some time ago, I discussed how to extract the function pointer from the control flow guard check. I gave the code for LdrpValidateUserCallTarget, but there’s another version of the function that combines the validation with a call. I assume this version exists because after validating a function pointer, you nearly always call it, so you may as well combine the two operations.
But this does mean that the calling convention has to change, because the registers need to be set up for the final call, meaning that the parameters to the combined validate-and-call cannot overlap with registers used by the calling convention. (Sound familiar?)
Here’s an x86-64 version.
mov r11, [ntdll!....]
mov r10,rax
shr r10,9
mov r11,qword ptr [r11+r10*8]
mov r10,rax
shr r10,3
test al,0Fh
jne @1
bt r11,r10
jae @2
jmp rax
@1: btr r10,0
bt r11,r10
jae @3
@2: or r10,1
bt r11,r10
jae @3
jmp rax
@3: xor r10d, r10d
jmp bad
Let’s put this side-by-side with the validate-only version:
| Validate only | Validate and call |
|---|---|
mov rdx,qword ptr [ntdll!....]
mov rax,rcx
shr rax,9
mov rdx,qword ptr [rdx+rax*8]
mov rax,rcx
shr rax,3
test cl,0Fh
jne @1
bt rdx,rax
jae @2
ret
@1: btr rax,0
bt rdx,rax
jae @3
@2: or rax,1
bt rdx,rax
jae @3
ret
@3: mov rax,rcx
xor r10d,r10d
jmp bad
|
mov r11, [ntdll!....]
mov r10,rax
shr r10,9
mov r11,qword ptr [r11+r10*8]
mov r10,rax
shr r10,3
test al,0Fh
jne @1
bt r11,r10
jae @2
jmp rax
@1: btr r10,0
bt r11,r10
jae @3
@2: or r10,1
bt r11,r10
jae @3
jmp rax
@3:
xor r10d, r10d
jmp bad
|
The logic is the same; the functions merely use different registers.
The validate-only version receives the address in rcx and uses rax and rdx as scratch registers. The validate-and-call version receives the address in rax and uses r10 and r11 as scratch registers. (There’s also a small change when a bad pointer is detected: The validate-and-call version already has the bad pointer in the rax register, so it doesn’t have to do anything to move it there.)
The validate-and-call version shifts its parameter and scratch registers to those not used by the x86-64 Windows calling convention, so that it can finish with a jmp rax to jump to the validated function with all function parameters intact.
For AArch64, the story is similar.
| Validate only | Validate and call |
|---|---|
adrp xip0,ntdll!....
ldr xip0,[xip0,#0x598]
lsr xip1,x15,#6
tst x15,#0xF
ldrb wip1,[xip0,xip1]
ubfx xip0,x15,#3,#3
bne @2
lsr xip1,xip1,xip0
tbz wip1,#0,@3
@1: ret
@2: and xip0,xip0,#-2
lsr xip1,xip1,xip0
tbz wip1,#0,@4
@3: tbnz wip1,#1,@1
@4: mov xip0,#0
b @5
@5: b bad
|
adrp xip0,ntdll!....
ldr xip0,[xip0,#0x598]
lsr xip1,x9,#6
tst x9,#0xF
ldrb wip1,[xip0,xip1]
ubfx xip0,x9,#3,#3
bne @2
lsr xip1,xip1,xip0
tbz wip1,#0,@3
@1: br x9
@2: and xip0,xip0,#-2
lsr xip1,xip1,xip0
tbz wip1,#0,@4
@3: tbnz wip1,#1,@1
@4: mov xip0,#1
mov x15,x9
b bad
|
Again, the code sequences are the same; it’s just the register usage. (And the code sequence when a bad call is detected.) The validate-only version takes the address in x15, whereas the validate-and-call version takes the address in x9. (Both use xip0 and xip1 as scratch registers.) And the validate-and-call version finishes with a b r9 to jump directly to the validated address instead of returning.
Again, you can extract the bad pointer from the thing that is shifted. For x86-64 validate-and-call, it’s rax, and for Aarch64 validate-and-call, it’s r9.
The post The other kind of control flow guard check: The combined validate and call appeared first on The Old New Thing.