AI Architecture7 min read•

Allow, Deny or Ask: Gating Agent Actions on Your Content With a Decision Model

An autonomous agent with write access to your CMS is a fast way to corrupt production.

An autonomous agent with write access to your CMS is a fast way to corrupt production. The failure mode is concrete: an agent asked to "tidy up outdated pages" issues a delete against a live legal disclosure, or a translation agent overwrites a scheduled release because nothing told it the document was mid-review. Give a large model a catalog of eighty tools and free rein, and the expensive question is not whether it can act but whether it should, on this document, right now, unattended.

The reframe in this guide is that "allow, deny, or ask" is a decision, not a generation. You do not need a frontier model writing a paragraph of reasoning to gate an action. You need a fast, calibrated verdict over a fixed option set, with a confidence value that decides whether the verdict runs on its own or waits for a human. A new class of tool, the System One decision model (TypeSafe's Jev, released 15 September 2026, is the first), does exactly this and nothing else.

The catch is that a gate is only as good as the state you hand it. That is a content-modelling problem before it is an AI problem, and it is why the topic sits here. Sanity, the AI Content Operating System, stores document type, workflow status, release membership, locale, and ownership as queryable fields, so you can hand a typed model the exact facts a gating question turns on instead of a wall of rendered HTML.

Illustration for Allow, Deny or Ask: Gating Agent Actions on Your Content With a Decision Model
Illustration for Allow, Deny or Ask: Gating Agent Actions on Your Content With a Decision Model

What does it mean to gate an agent action with a decision model?

Gating an agent action means intercepting a proposed action before an expensive model or an irreversible operation runs, and returning one of a fixed set of verdicts: allow, deny, or ask a human. A decision model like Jev is built for exactly this shape. You pass it state (the proposed action plus the context that makes it safe or unsafe) and a typed question you define in code, and it returns a winner from your option set, a probability for every option, and a confidence value. It writes no prose, no rationale, and no code. It answers and stops.

This matters because the alternative, asking a generative model to reason out whether an action is permitted, is slow, costs real money per call, and produces free text you then have to parse and trust. A gate runs on the hot path of every agent action, so latency and cost compound. TypeSafe reports Jev at 70 to 500 milliseconds end to end and $0.042 per million input tokens, with output free, though every one of those figures is self-reported and has not been independently reproduced.

The honest boundary is that a decision model guarantees format, not correctness. Because the valid verdicts are fixed by the schema before the call, an off-schema or malformed answer is structurally impossible. That is a real property, but it does not mean the model returns the right verdict. Jev can return a confident, schema-valid "allow" on an action that should have been denied. So the verdict is a filter that decides what runs automatically and what escalates, not a substitute for the judgement of the person who owns the content.

Catalog shrinking versus action gating: two shapes of the same problem

Tool gating shows up in two distinct shapes, and it helps to keep them separate. The first is catalog shrinking. When an agent has eighty tools, the model that picks among them is slower, more expensive, and more error-prone than one choosing among eight. A Choice question over tool groups solves this: the decision model reads the task and returns which group of tools is relevant, so the downstream agent sees a short, relevant list rather than the whole catalog. This is a routing decision. It rarely needs a human in the loop because picking the wrong group usually just means the agent asks again.

The second shape is action gating, and this is where the stakes live. Here the question is a Choice of allow, deny, or ask-a-human over a proposed action the agent has already decided to take. The state is the action plus the context: what document, what operation, what workflow status. The verdict decides whether the action proceeds. Best practice on a Choice is to include an explicit option for "nothing fits" so the model can decline rather than pick the closest wrong answer, and here "ask-a-human" plays that role naturally.

The two shapes have different tolerance for error. Catalog shrinking is recoverable and can run on thin confidence. Action gating on a destructive operation is not, and the confidence bar should rise with the cost and irreversibility of a mistake. Treating both as "tool gating" and applying one threshold to both is a common way to get burned. Separate the routing decision from the permission decision, and set thresholds independently.

How do you gate content actions like edit, translate, publish, and delete?

You gate a content action by judging two things together: the action type and what the document is. An agent that edits, translates, publishes, or deletes documents is not doing one uniform kind of work. Editing a draft in a sandbox dataset is low stakes. Publishing a change to a live legal page, or deleting a document that a scheduled release depends on, is not. The gate needs both axes, the operation and the target, to return a sensible verdict.

Concretely, the state you hand the decision model describes the proposed action and the document it targets: the operation (edit, translate, publish, delete), the document type, its workflow status, whether it belongs to an in-flight release, its locale, and who owns it. The typed question is a Choice: allow, deny, or ask. A translate action on a draft blog post in a non-production dataset can return a confident allow. A delete on a published document of type legalPage returns deny or, at minimum, ask. And "ask" should route to a specific person, the owner of that content, not a generic queue nobody watches.

The decision model does not know your policy; you encode it in the question and, more importantly, in the state you choose to pass. This is the load-bearing point of the whole pattern. The verdict is a function of what the model can see. If the state omits that a document is part of a Content Release under review, the gate cannot protect it. If the state carries that field, a single Choice question can hold the line on every write an agent proposes, in tens of milliseconds, before any expensive generation runs.

Why structured content is what makes the gate reliable

The quality of a typed judgement depends entirely on the state it is handed, which makes gating a content-modelling problem before it is an AI problem. Jev works against a 32,000-token state budget. You can spend that budget on a wall of rendered HTML, in which case the model has to infer whether a page is a legal document from markup, or you can spend it on the exact fields the question turns on. Structured content lets you pass document type, workflow status, release membership, locale, and ownership as explicit values rather than guesses reconstructed from a rendered page.

There is a second, subtler advantage. A content schema already defines answer spaces. Enumerated fields, references to taxonomy documents, content types, and workflow states are Choice sets that exist before anyone writes a prompt. If your schema says a document's status is one of draft, in-review, approved, or published, that enum is the option list for a status-aware gating question. You are not inventing an option set and hoping it matches reality; you are reading it off the model you already maintain.

This is where Sanity's architecture earns its place in the pattern. In Sanity, GROQ lets you query for precisely the fields a gating question concerns and hand them over as state, and Portable Text preserves the structure of rich text so a block or annotation survives being passed to a model rather than collapsing into markup. Content Lake real-time subscriptions mean a gate can re-judge the moment a document changes, and Functions can run a gating check as a serverless hook on the path to publish. Because AI is wired into the data model, the editor, and the delivery layer rather than bolted on as a plugin, the fields a decision needs and the surfaces that act on the verdict live in the same platform.

How do you set confidence thresholds for auto versus human review?

You set confidence thresholds by tying them to the cost and irreversibility of a wrong verdict, and by validating them against reviewed labels before you trust them. Jev returns a verdict plus a confidence value, and the pattern is confidence-gated routing: the answer says what to do, and the confidence decides whether it is safe to do automatically. A high-confidence allow on a reversible edit runs unattended. A low-confidence anything escalates.

The threshold is not one number. It rises with the stakes. A translate action on a draft might auto-run at moderate confidence because the blast radius is small and the change is easy to revert. A publish to a live page demands a much higher bar, and a delete of anything in production should escalate regardless of confidence, because no probability justifies an irreversible action on real content. A probability is a filter, not evidence; treat it as deciding who reviews, not as proof the verdict is correct.

Two operational rules keep this honest. First, calibrate thresholds against a set of decisions you have reviewed by hand, so you know what a given confidence actually buys you in your domain rather than assuming the model's numbers map onto your risk. Second, never convert a timeout or a rate limit into a high-confidence default. If the decision model does not answer, the action does not silently proceed; it escalates. The escalation cascade is the whole design: the decision model handles the confident majority at volume, and a frontier model or a human handles the uncertain minority. That is how you get speed on the common case without gambling on the dangerous one.

Auditing, versioning, and the injection caveat you cannot design away

A decision model returns a verdict with no rationale, so "why was this action denied?" has no answer from the model itself. For content operations that touch regulated or legally sensitive material, that is a governance problem you solve with surrounding telemetry, not with the model. Log the full response for every gating decision: the verdict, the probability over each option, the confidence, and, critically, the exact state the model saw. An audit of a decision that came with no reason has to reconstruct the inputs, so the inputs are the record.

Versioning is part of the same discipline. Pin the versioned model ID rather than a floating latest route, log the model reported in each response so you can prove which version judged which action, and version your question definitions alongside application code. When your taxonomy or tool list changes in production, and it will, the option set a gate uses changes with it, so a question definition is code and belongs in the same review and release process. In Sanity, document history and Content Releases give you the content-side half of this record: what the document was when the gate saw it, and which release it belonged to.

The caveat you cannot design away is prompt injection. When attacker-controlled text sits inside the state, for example user-submitted content an agent is about to publish, injected instructions can flip an allow into a deny or the reverse. A decision model shrinks what an attacker can make your system do, from arbitrary actions down to your fixed option set, but it does not make hostile state safe. Treat untrusted text in state as untrusted, keep it separated from your policy framing, and remember the gate is only ever as good as the state and the option set behind it.