Skip to content

The Action Boundary

The tool surface gives each action somewhere for a control to attach. This topic is what attaches there.

Module 1 classified actions by blast radius. Module 2 made the point that a limit expressed in a prompt is a hope rather than a requirement. Here both become a specific set of enforcement points, organised around one rule.

Every argument the model supplies is untrusted input.

Note the precision. The claim is not that the model is adversarial — it is that its arguments arrive from a probabilistic process, influenced by content you do not control, and they must therefore be treated the way you treat anything arriving from outside your trust boundary.

That reframing is useful because it tells you what to do. You already know how to handle untrusted input: validate against an allowlist rather than a blocklist, resolve identifiers to a canonical form, confine them to a permitted scope, and reject anything that escapes it. All of that is prerequisite knowledge from the security material this guide assumes; what is new is noticing that it applies here.

A blocklist is not sufficient, and the reason is familiar: you are enumerating what you can think of, against a generator that will produce things you did not. An allowlist enumerates what is permitted, which is a set you actually know.

graph LR
  M["Model<br/><i>requests an action</i>"] --> G1["Tenant scope<br/><i>from the session,<br/>never from arguments</i>"]
  G1 --> G2["Allowlist and<br/>limit checks"]
  G2 --> G3["Confirmation<br/><i>if the tier requires it</i>"]
  G3 --> G4["Idempotency key<br/><i>issued here, not<br/>by the model</i>"]
  G4 --> A["Action executes<br/>+ audit record"]

  classDef m fill:#5B8FB9,stroke:#4A7A9E,stroke-width:2px,color:#ffffff
  classDef gate fill:#E8A33D,stroke:#C4832A,stroke-width:2px,color:#ffffff
  classDef act fill:#7D9A4E,stroke:#5F7A38,stroke-width:2px,color:#ffffff
  class M m
  class G1,G2,G3,G4 gate
  class A act

Four gates, all outside the model. The model’s job ends at “requests an action” — everything after that is your code, and none of it can be expressed as an instruction.

Tenant scope comes from the session. The single most important rule in a multi-tenant system. The customer whose data may be touched is established by the authenticated session, never by an argument the model supplied. A loop that can pass a customer identifier is a loop that can be talked into passing a different one — and the content it reads includes historical tickets written by strangers, which Module 2 labelled untrusted for exactly this reason.

Allowlist and limits. Which operations exist, which values are permitted, what the ceiling is. Enforced here, in code, as configuration — not as a sentence in a prompt. The test from Module 2 applies: if satisfying the requirement depends on the model behaving well, it is not a requirement.

Confirmation, where the tier requires it. The blast-radius classification decides which actions proceed unaided, which notify after the fact, which need a human first, and which are forbidden entirely. The decision is a business one with named owners; the enforcement is yours.

Idempotency keys are issued by your code. A retried action must not become a second action — a retried credit is a second credit. The key must be generated by the harness and tied to the logical intent, because a model asked to supply one may supply a fresh one on the retry, which defeats the entire mechanism.

Least privilege, and credentials the model cannot reach

Section titled “Least privilege, and credentials the model cannot reach”

Each tool should carry only the authority it needs. A documentation search tool has no business holding credentials that can move money; a credit tool has no business being able to read other customers’ records. This is ordinary least privilege, applied per tool rather than per service.

The sharper requirement concerns secrets. A credential must never be reachable by the model — not in its context, not in a file in a sandbox it can read, not in an error message a tool returns. The safe pattern is substitution at the boundary: the tool call references a credential by name and your infrastructure supplies the actual value on the way out, so the secret exists in the request your code makes and never in anything the model sees.

The same caution applies to any persistent store the loop can write to. If the system keeps notes across sessions, that store must never hold secrets, must be scoped per tenant, and must be treated as data the model wrote — which is to say, untrusted on the way back in.

The fourth tier from Module 1 deserves defending, because it tends to erode.

Some actions should be unavailable to the system entirely: not gated, not confirmable, simply absent from the tool surface. Anything contractual. Anything touching permissions or access. Anything irreversible with a wide blast radius. The argument for absence rather than gating is that a gated capability is one configuration change away from being ungated, usually under deadline pressure, usually by someone who does not know why the gate was there.

An action that does not exist cannot be enabled by accident.

Every gate adds latency to the action path, and the confirmation gate adds a human’s response time, which is measured in minutes rather than milliseconds. That is a direct trade against the deflection target: an action requiring confirmation is not deflected, it is assisted.

That trade is the real content of the oversight decision, and it is not yours alone to make. The compliance owner decides what must be gated; whoever owns the financial exposure decides the limits; the team receiving the confirmations decides what volume is liveable. Your job is to make the trade explicit and get the three of them to agree on it — the Module 2 elicitation work, arriving at a decision with money attached.

The rubric requires every action classified by required oversight, with reasoning tied to blast radius. The table above is the shape; your version needs the enforcement point and the credential scope per row, because those are what make the classification real rather than aspirational.


→ That closes Section 1: one agent, bounded, with a surface you can police. Next, what happens when someone proposes several. — Multi-agent topologies