Skip to content
advanced

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…

Published 2026-09-11Updated 2026-09-1215 min read
A professional workspace featuring computers and analytical graphs on a monitor, symbolizing modern business environment.
A professional workspace featuring computers and analytical graphs on a monitor, symbolizing modern business environment. Photo by Kampus Production on Pexels.

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.

A team gives planner, coder, reviewer, and deployer roles separate system prompts, but they run in one process with the same credential, tool surface, and memory. What is the best conclusion?
Scenario Interpretation

Focus: Distinguish an enforceable role boundary from a prompt-defined persona by evaluating identity, capabilities, and state ownership.

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:

ClassExampleDefault control
Read-onlyFetch a record, list filesAllow, log
Reversible internal writeUpdate a draft, write a scratch artifactAllow, log, keep undo
Irreversible internal writeDrop a table, force-push, delete a branchRequire approval
External side effectSend email, post to a third party, move moneyRequire approval, often validation
Credential or policy changeRotate a key, widen an IAM role, edit the policy artifactDeny 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.

A single agent can fetch records, update a draft, and rotate a key. Which policy best follows the article's classification approach?
Comparison Reasoning

Focus: Select control intensity from an action's consequence profile rather than from the agent's job title.

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

A left-to-right flow shows an agent proposing an immutable action envelope, followed by consequence classification, authorization, independent validation, approval bound to the envelope, and a final commit gate. A side branch from any failed check leads to blocked action; the commit gate leads to an idempotent executor and an audit record.
Approval is meaningful only when it is bound to an immutable action envelope and every authorization, validation, and freshness check still passes at commit.

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.

Which execution rule makes an approval meaningful for a destructive action?
Comparison Reasoning

Focus: Apply the action-envelope invariant by identifying the required relationship among validation, approval, authorization, and commit.

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.

Which statement correctly describes independent validation?
Misconception Check

Focus: Explain why context and credential separation, rather than merely model diversity, is required for independent validation.

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:

TestWhat it exercisesExpected outcome
Mutate an approved argument after approvalEnvelope immutabilityCommit blocked; new envelope required
Change target state between approval and commitFreshness and precondition re-checkCommit blocked or revalidated
Call a role's tool with another role's credentialIdentity and capability separationAuthorization denied
Feed a poisoned artifact across a handoffState segregation and input validationReceiving role rejects or quarantines
Retry an approved action after an ambiguous commitIdempotency at the approval boundarySingle 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.

  1. Enumerate every tool and MCP integration. Assign each an action class and a named control. Anything classified "unknown" is denied until someone classifies it.
  2. 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.
  3. 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.
  4. Check that approval payloads are bound to arguments and that a retry after timeout cannot double-execute.
  5. 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.

An action is approved, but an operator changes its target argument before the executor commits it. According to the article, what should happen?
Question 1 of 2Scenario Interpretation

Focus: Predict the enforcement outcome of mutating an approved action before commit and identify the required recovery behavior.

A runtime's policy lookup times out while a reviewer fails to produce a parseable decision for a destructive action. What should the runtime do?
Question 2 of 2Scenario Interpretation

Focus: Choose fail-closed and control-specific recovery behavior when policy or validation components fail.

Related sites

Build the foundations behind advanced AI systems

Use LearnLLMFast for practical LLM application foundations and LearnPyFast for the Python mechanisms that support implementation work.

LLM tutorialstutorial

LearnLLMFast

Practical LLM tutorials for builders who want to understand prompting, workflows, agents, and AI applications.

LLMAIBuilders
Visit LearnLLMFast
Python tutorialstutorial

LearnPyFast

Beginner-friendly Python tutorials, examples, and learning paths for practical programming foundations.

PythonProgrammingBeginners
Visit LearnPyFast

Keep exploring

Related AI engineering tutorials

Continue with adjacent system layers, implementation patterns, and current AI engineering ideas.