An agent becomes a different kind of system the moment it can do more than answer. Give it a terminal, a cloud API, a ticketing system, or a deployment tool and its output can change a real environment.
That is where I stop treating the prompt as the main safety mechanism.
A prompt can explain intent. It can tell an agent to be careful. It can ask for confirmation before a destructive operation. But it cannot enforce an allowlist, prove that an approval happened, prevent an unrecognised command from reaching an executor, or tell me whether the claimed outcome exists outside the chat transcript.
Those jobs belong to a control plane.
An agent is a loop, not a clever completion
The useful mental model is not “a chatbot with tools.” It is a loop:
- a model receives a task, context, and the tools it may request;
- it returns a response or a structured request for a tool;
- the runtime decides whether and how to execute that request;
- the result becomes new evidence for the next turn.
Anthropic makes the same distinction in its tool-use documentation: the model requests a client-side tool call, while the application is responsible for executing it. Its engineering guidance describes agents as LLMs using tools from environmental feedback in a loop. It recommends pausing for human feedback at checkpoints or blockers, and using stopping conditions such as a maximum iteration count.
That separation matters. A model can suggest restart_service. It does not get to make a process restart merely by emitting those words. An executor with the right identity and policy has to accept the request.
This is not an argument against prompts. Good instructions make tool selection, planning, and explanations better. They are just the wrong place to put a non-negotiable security or change-management rule.
What a production policy boundary must check
Suppose the prompt says: “Never restart production without approval.” That is a useful instruction, but it remains advice delivered to a probabilistic system. Context can be incomplete. A retrieved document can be misleading. A tool description can be ambiguous. A model can simply make the wrong call.
A production boundary should check rules after the model has made its request:
- Which tools exist for this agent and this task?
- Is the requested argument shape valid for that tool?
- Is the target inside the permitted scope?
- Is the operation read-only or mutating?
- If it mutates state, is there a recorded approval for this exact action?
- Has the run exceeded its time, call, cost, or retry budget?
The prototype below does not implement all of those checks. It only allowlists three tool names, requires that arguments is a JSON object, and checks a demonstration-only boolean before returning a decision. The broader list is the production design target, not a capability claim about the prototype.
Microsoft's guidance on agent identity makes the point directly: do not treat the model as the security boundary. It recommends narrow permissions, separation of read and write actions, and policy checks, approvals, telemetry, and audit logs around the agent.
The practical rule is simple: the model decides what to ask for; the control plane decides what may happen.
A small policy experiment
I built a deliberately small executor to test this boundary. It is not an AI model and it is not a production controller. It is a deterministic policy layer that accepts JSON tool requests on standard input.
The experiment ran with this Docker command:
docker run --rm --read-only --cap-drop ALL \
--security-opt no-new-privileges:true \
--pids-limit 32 --memory 64m --cpus 0.25 --network none \
-i agent-control-plane-rnd:local
Its policy contained three tools:
| Tool | Class | Rule |
|---|---|---|
read_status |
read | allow |
restart_service |
mutation | require explicit approval |
delete_database |
mutation | require explicit approval |
I sent five requests through it. The policy did not try to infer intent from prose. It used a small allowlist and a boolean approval signal.
read_status without approval → allow
restart_service without approval → needs_approval
restart_service with approval=true → allow
delete_database with approval=false → needs_approval
shell, which was not allowlisted → deny
The assertion over the full sequence passed:
verification=PASS
The result is intentionally narrower than a real action pipeline. This program never invokes a downstream executor and never changes an environment. It demonstrates only that its own deterministic decision function returns needs_approval or deny for those inputs. In a real system, the executor must accept only an allow decision produced by a separate policy service, and the integration needs its own test proving that denied requests cannot reach the executor.
The boolean approval signal is deliberately unsafe outside this demonstration. It is not bound to an actor, target, action, expiry, or one-time request identifier. A real approval design needs all of those properties, plus an audit record and an executor identity that cannot bypass the gate.
A success message is not an outcome
Agent transcripts are persuasive. “Deployment completed” sounds final. It is not evidence that the intended deployment became healthy, that traffic reaches the new version, or that a rollback did not leave an older route serving users.
This is where the feedback loop needs ground truth. Anthropic recommends environmental feedback from tool calls or code execution at each step. Its 2026 guidance on agent evaluations distinguishes the transcript from the final state of the environment: an agent may claim a flight was booked while the database shows no reservation.
For infrastructure work, outcome checks depend on the action:
- a GitOps change needs the desired revision plus reconciliation status and workload readiness;
- a restart needs process health plus a user-path or synthetic check where the risk warrants it;
- an access-policy update needs the intended authorization result from both sides of the boundary;
- a database operation needs a bounded query or domain-level invariant, not a cheerful CLI exit message.
The agent should receive that observed result as new context. The operator should receive a trace that makes it possible to reconstruct what happened without reading private payloads or secrets.
Approval is a state transition
A human approval request in the chat is useful only if the executor can verify it. Otherwise it is still a sentence in the model's context.
Treat approval as a state transition with a narrow scope:
planned action
→ policy creates approval request
→ named approver accepts or rejects the exact request
→ policy verifies a valid, unexpired approval
→ executor receives a bounded action
→ outcome is recorded
That design prevents a common failure mode: an agent receives approval for one low-risk restart, then silently applies the approval to a different host or a deletion request later in the conversation.
The record does not need to contain a full prompt or secret-bearing argument. It needs enough identity to answer: who approved which action against which target, under what policy, and what happened after execution.
Evals are part of the control plane too
A policy gate controls individual actions. It does not tell you whether a new prompt, model, tool schema, or routing change made the whole agent worse.
That needs evaluations. Anthropic describes an agent harness as the system that processes inputs, orchestrates tool calls, and returns results; evaluating an agent therefore means evaluating the harness and model together. Its examples include code-based checks for tool calls, parameters, outcomes, transcript properties, latency, and token use.
For an operations agent, I would start with a compact regression suite:
- read-only investigation requests must never produce a mutating tool request;
- an unapproved mutation must stop at the policy gate;
- an approved mutation must target only the approved resource;
- unknown or malformed tool requests must fail closed;
- the run must report an independently observed outcome, not only the model's final prose.
Run those tests when changing the model, prompt, tool definitions, agent harness, or routing layer. They are not a guarantee of safe production behaviour. They are a way to notice that a change broke a contract you had already decided matters.
Make the safe path the easy path
The architecture does not have to be grand. Start with a small tool surface and a clear split between reading and changing state.
A useful minimum looks like this:
- Give the agent a separate identity with least privilege.
- Expose explicit, narrow tools instead of a general shell where possible.
- Validate tool arguments and scopes outside the model.
- Require approval at the policy boundary for mutations.
- Set limits for turns, retries, wall time, and spend.
- Record tool request, policy decision, execution identifier, and observed outcome without retaining secrets by default.
- Build a few regression cases before changing the harness or model route.
Google's agent architecture guidance lists tools, memory, runtimes, and design patterns as separate components of an agentic system. That separation is useful operationally. It lets us ask which component made a decision, which component enforced a boundary, and which component observed the result.
The prompt belongs in that system. It is where intent, context, and judgement begin. It is not where production authority should end.
Sources
- Anthropic, Tool use with Claude.
- Anthropic, Building effective agents, 19 December 2024.
- Anthropic, Demystifying evals for AI agents, 9 January 2026.
- Microsoft Learn, Identity fundamentals for AI agents.
- Google Cloud Architecture Center, Choose your agentic AI architecture components, reviewed 21 April 2026.
- OWASP Gen AI Security Project, OWASP Top 10 for Agentic Applications for 2026.