Role Isolation, Approvals, and Independent Validation in Agent Runtimes
That is the shape of the failure I keep seeing in agent systems that look governed and are not. A team writes a planner prompt, a coder prompt, a reviewer…

Key topics
Four roles. Four system prompts. One runtime. One deploy token.
That is the shape of the failure I keep seeing in agent systems that look governed and are not. A team writes a planner prompt, a coder prompt, a reviewer prompt, and a deployer prompt, wires them into the same process, and calls it separation of duties. Then a summarization task picks up injected instructions from a fetched page, walks the tool surface it already had access to, and reaches the deploy credential. No role was violated. Every prompt was obeyed. The boundary was never there.
This article is about where to put authorization, approval, review, and independent validation so that model error has to cross something real before it reaches data, code, or an external system. If you already know what a harness is and how tools are contracted, the one-sentence bridge is this: the harness supplies capability, state, execution, and policy, and this article is about where inside that layer the control points belong.
Why Role Prompts Are Not Boundaries
A profile changes expression and task preference. It does not change the credential, the tool surface, the memory store, or the process the agent runs in.
That distinction is easy to state and easy to violate. When a coding skill, an email skill, a database skill, and a cloud-management skill are mounted on one agent, they share one trust domain. The risk of the composite is the union of the risks of its parts. Each skill's author may have reasoned carefully about that skill's own permissions; once it joins a general agent, it shares fate with everything else mounted there. A task as innocent as "summarize this issue" can be steered into reading files, inspecting environment variables, and calling an external send tool, because the capability was already reachable.
So define a boundary by three observable properties, not by wording:
- Distinct identity. A separate credential or principal. Not a separate persona string.
- Distinct capability set. What the role can actually reach — tools, network egress, filesystem paths, database roles.
- Distinct state ownership. Which memory namespaces, working directories, and artifacts it can read or write.
Then apply the consequence test. If a compromised or merely confused agent in role A can reach role B's capability without a new authorization event, there is no boundary. There is a costume.
I want to be fair to profiles, because they are not useless. They are genuinely good at task framing, output style, and hinting at which subset of tools is relevant. They reduce accidental tool selection and they make traces easier to read. What they cannot do is enforce anything, because enforcement requires a component that the model does not control. A prompt is a request. A credential is a fact.
Knowledge check
Check your understanding
Answer this question before you continue.
Classify Actions Before You Classify Agents
The instinct to assign permissions per agent is backwards. The control belongs to the action's consequence profile, not to the agent's job title.
Classify every reachable action along three axes: reversibility, blast radius, and external visibility. A workable five-class scheme:
| Class | Example | Default control |
|---|---|---|
| Read-only | Fetch a record, list files | Allow, log |
| Reversible internal write | Update a draft, write a scratch artifact | Allow, log, keep undo |
| Irreversible internal write | Drop a table, force-push, delete a branch | Require approval |
| External side effect | Send email, post to a third party, move money | Require approval, often validation |
| Credential or policy change | Rotate a key, widen an IAM role, edit the policy artifact | Deny by default, independent validation |
The same agent can legitimately need zero approval for reads and hard approval for one destructive call. That is not inconsistency; it is the point. Approval policy is per-action-class.
Two rules make this survive contact with production.
First, fail closed. When the classifier errors, when the policy lookup times out, when the reviewer itself fails to produce a parseable decision, the action does not run. Surface timeouts separately from denials so operators can tell "policy said no" from "policy never answered," but block in both cases.
Second, treat the classification as code. It is a policy artifact you maintain, and it drifts the moment someone adds a tool. A new MCP integration arrives with a default class of "unknown," and unknown must not mean allow. Review the classification table the way you review a permission change, because that is what it is.
The honest limit: classification is a maintained artifact, not a setting. If nobody owns the table, the table is fiction within a quarter.
Knowledge check
Check your understanding
Answer this question before you continue.
Four Control Points and Where Each One Belongs
Teams collapse four different mechanisms into one gate called "approval," then wonder why the gate is either useless or unbearable. Separate them.
Authorization answers: does this principal hold this capability at all? It is enforced by the runtime or the downstream system — the IAM policy, the database role, the scoped token. Never by the model's own judgment about whether it should proceed.
Approval is a human or policy decision to permit one specific pending action. Scoped to that action and that run. Not a standing grant.
Review is a second pass over a proposed change before it lands. Useful for quality and intent. Weak as a security control when the reviewer shares the producer's context and credentials, because a shared wrong premise passes review cleanly.
Independent validation is a check performed by a component that does not share the producer's context, memory, or credentials. That separation is the whole mechanism. Without it, you have a second opinion from the same head.
The decision rule: use the cheapest control that matches the consequence class, and escalate to independent validation only where a single undetected error is unrecoverable. Reads get logging. Reversible writes get logging and undo. Irreversible and externally visible effects get approval. Credential and policy changes get independent validation, because those are the actions that can quietly widen everything else.
The Ordering That Makes the Controls Real
Knowing the four mechanisms is not the same as knowing where they sit relative to each other. The common failure is to validate a proposal, then approve it, then execute it — while the arguments, target, or authorization context quietly change in between. A validated proposal is not a safe action. Only an immutable action envelope is.
Here is the ordering I use for a destructive action:
propose immutable action envelope
-> classify action (consequence class)
-> authorize principal + capability
-> independently validate the action and its preconditions
-> obtain approval bound to the envelope
-> re-check authorization, policy version, and freshness
-> commit through an idempotent executor
-> record outcome and compensation path
Three properties of this pipeline matter more than the boxes.
The envelope is immutable. Once proposed, the tool name, arguments, target resource, principal, and policy version are frozen. Any change produces a new envelope and invalidates prior approval. This is what makes approval meaningful: you approved this action, not a category of action.
Authorization is re-checked at commit. The authorization that held when the action was proposed may not hold when it executes. A role change, a revoked token, or a policy update between approval and commit must block the commit. The re-check is cheap; the alternative is a confused-deputy path that no log will explain.
Validation targets the action, not the reasoning. This is the distinction that trips people up. There are two different things you can validate:
- Semantic validation checks the model's claims or plan steps — does this inference follow, is this premise supported. Useful when the reasoning itself is the risk.
- Action validation checks the executable command, target state, policy invariants, and expected diff. This is the default for side-effecting boundaries.
A coherent reasoning chain does not establish that a side effect is safe to commit. A runtime can independently verify that a proposed database change satisfies a schema, respects an invariant, targets the right resource, and matches an expected diff — without ever reading the model's prose. Conversely, a beautifully argued plan can still mutate the wrong row. Validate the action envelope.
Invariant to write into the executor: the executor may commit only the exact approved action envelope, under the same principal and policy version, while its freshness and target preconditions still hold. Stale approvals, mutated arguments, changed diffs, and authorization changes all violate this invariant and must block.
Knowledge check
Check your understanding
Answer this question before you continue.
Designing the Approval Boundary
An approval that is not bound to a payload is theater. "Approve the deploy?" is not an approval event; it is a mood.
Bind every approval to a concrete action: tool name, arguments, target resource, and a hash or identifier over that payload. The approved intent then cannot be replayed with mutated arguments. This matters more than it sounds, because the interesting attacks are not "run something else" — they are "run the thing you approved, with one argument changed."
Scope approvals to a single action in a single run, with an expiry. Standing approvals are a privilege grant wearing an approval's clothes; if you want a standing grant, put it in the authorization layer where it can be reviewed as a permission.
Route by category, not by volume. Keep destructive and credential-touching categories interactive. Auto-decide low-risk categories. Make the routing rule explicit and reviewable, so nobody has to guess why one action prompted and another did not.
When an automated reviewer stands in for a human, be precise about what it is: a policy engine with a model inside. It must fail closed, and its decisions must be logged with the same fidelity as human ones — including the decision rationale or structured evidence the reviewer used, because that is what you will read during the incident. If your system does not retain private reasoning, require the reviewer to emit the evidence it relied on instead.
Implementation trap worth naming: approval checks that sit behind a sandbox or channel-resolution step can be unreachable for some session types. The approval layer then silently never runs, and the system looks compliant because nothing was ever denied. Verify the chain order, not just the configuration.
Independent Validation That Is Actually Independent
Independence is a property of context and credentials, not of model choice. Running the validator on a different model is a nice diversity bonus and a poor substitute for isolation. A validator that shares the producer's transcript inherits the producer's errors, and it will agree with them confidently.
The mechanism that makes validation useful is decomposition. Instead of validating a whole answer, validate atomic premise-to-conclusion steps. If the chain is a → b → c, check a → b and b → c separately. Errors localize, feedback becomes actionable, and the producer can revise a specific step rather than regenerating everything and hoping.
There is a known blind spot, and it is worth stating plainly. A validator that checks logical coherence cannot catch a confidently stated false premise that it also accepts. If an upstream source reports something wrong with high confidence, and the producer reasons soundly from it, the validator sees a valid inference and passes it. Validation catches reasoning drift, not bad inputs. If your failure mode is poisoned retrieval, you need source-level checks, not a smarter validator.
Validator disagreement is a signal, not a verdict. Plan for the case where the producer overrules the validator after re-evaluation — that is a legitimate outcome — and record who overruled whom. An overrule rate that climbs is a measurement, and it tells you either the validator is too strict or the producer has learned to ignore it.
The cost boundary is real: independent validation adds inference and latency proportional to what you validate. Reserve it for irreversible or externally visible outputs. Validating every step of a research loop is how you build a system that is correct, slow, and too expensive to run.
Knowledge check
Check your understanding
Answer this question before you continue.
State, Memory, and Artifact Segregation
Boundaries leak through data more often than through tool calls. Shared memory is a shared trust domain: one agent's poisoned or stale state becomes another agent's premise, and nothing in the tool layer will flag it.
Give each role its own working directory, memory namespace, and artifact store. Pass information across roles through explicit, typed handoffs rather than a common scratchpad. The scratchpad is where isolation goes to die, because it is convenient, and convenience wins every architecture argument that is not enforced.
Artifacts are the durable interface between roles. Version them, attribute them to a producer, and treat a handoff artifact as untrusted input on the receiving side. The receiving role should validate what it was handed, not assume the producer's context.
Cross-boundary reads need the same classification discipline as writes. Exfiltration is a read problem before it is a write problem; the agent that can read the secrets file has already crossed a line, whether or not it ever sends anything.
When not to do this: full process or container isolation per role is overkill for read-only, single-tenant, low-consequence agents. Start with identity and state separation, which is cheap and catches most of the real failures. Escalate to process isolation when a role handles credentials or irreversible effects, and accept the operational weight that comes with it.
Observability, Recovery, and the Audit Trail
The controls only matter if you can prove what happened. Log the boundary event, not just the tool call: who requested, which action class, which control fired, who or what decided, and what the decision was.
Record denials and timeouts as first-class outcomes. A blocked action is evidence about policy, not noise to be filtered out of the dashboard. If your logs only contain successful calls, you have no idea whether the boundary works.
Recovery semantics differ by control, and conflating them produces bad retries:
- An approval denial is a clean stop. Do not retry it.
- A validation rejection is a retry with feedback attached.
- A post-commit failure needs compensation, not rollback, because the effect already left the building.
Duplicate prevention matters specifically at the approval boundary. An approved action retried after a timeout must not execute twice. The approval identifier is the natural idempotency key; use it.
Evaluation question to carry forward: for each boundary, can you reconstruct from logs alone why an action was allowed? If the answer requires reading the code, the boundary is not observable — it is merely present.
A Boundary-Test Matrix
Configuration review tells you what you intended. Adversarial tests tell you what you built. Run these five against one real agent, and tie each to an expected outcome:
| Test | What it exercises | Expected outcome |
|---|---|---|
| Mutate an approved argument after approval | Envelope immutability | Commit blocked; new envelope required |
| Change target state between approval and commit | Freshness and precondition re-check | Commit blocked or revalidated |
| Call a role's tool with another role's credential | Identity and capability separation | Authorization denied |
| Feed a poisoned artifact across a handoff | State segregation and input validation | Receiving role rejects or quarantines |
| Retry an approved action after an ambiguous commit | Idempotency at the approval boundary | Single execution; duplicate suppressed |
If any test passes when it should fail, you have found a boundary that exists only in the diagram. The point of the matrix is not coverage for its own sake; it is to force the enforcement path to fail in front of you, where you can see it.
A Placement Checklist for Your Runtime
Run this against one real agent this week, not against the architecture diagram.
- Enumerate every tool and MCP integration. Assign each an action class and a named control. Anything classified "unknown" is denied until someone classifies it.
- For each boundary, verify the enforcement point sits outside the model's control and cannot be reached around by another role sharing the same runtime.
- Force the failure path. Trigger a policy lookup error, a reviewer timeout, and a malformed approval payload. Confirm the action does not run in all three cases.
- Check that approval payloads are bound to arguments and that a retry after timeout cannot double-execute.
- Pick the single highest-consequence action in the system and add independent validation there first.
One boundary done properly beats five declared in a config file. The config file does not stop anything; the enforcement point does.
My rule, stated as a rule: place a boundary wherever an error is irreversible, externally visible, or credential-touching. Place nothing more than logging everywhere else. Everything between those two positions is ceremony that costs latency and buys the feeling of safety.
The next concrete action: open the live agent you trust most, find its one destructive tool, and write that tool's action class and control into the policy artifact. Then deliberately break the enforcement path — misconfigure the lookup, kill the reviewer, send a malformed approval — and confirm the action is blocked. If it runs, you just found the boundary you thought you had.
Knowledge check
Final check
Finish the article by checking the ideas you just learned.
References
- Agent approvals & security | ChatGPT Learn
- No config path enables exec for agents in isolated sessions — sandbox blocks before exec-approvals · Issue #59720 · openclaw/openclaw · GitHub
- [PDF] IAGENT: A WEB SEARCH FRAMEWORK FOR NOISE ISOLATION ...
- FINOS AI Governance Framework:
- May 17, 2026 Why AI Agents Need Agent-Level Isolation
Research updated Sep 11, 2026


