Gating agent tool calls before they run
An agent that can delete a record, send a payment or email a customer needs a check between deciding to do it and doing it. With Jev that check is a Noul question per side effect, asked about the proposed call and its arguments before the tool runs, with a threshold set by what the action would cost if wrong and a human confirmation step in the uncertain band. This page lays out that design, what LangChain's middleware and Openlayer's ToolCallRisk check do, and what Browser-use's Jev Ultrafast shows about a decision model choosing an agent's actions, with Browser-use's own caveat attached.
Published September 22, 2026. Editorial.
Key takeaways
- The gate sits in code between the agent's proposed tool call and the tool, and the agent cannot skip it.
- One Noul per side effect: is this a delete, is this a payment, does this leave the system, does this match what the user asked for.
- Thresholds follow consequence. A read runs at a low threshold, a reversible write at a higher one, and an irreversible action needs a person unless the probability is near certain.
- LangChain's harness middleware blocks risky tool calls before execution, and Openlayer's ToolCallRisk returns approve, escalate or block.
- Browser-use's Jev Ultrafast picks the action and its target in one request; in six alternating runs of one task the median fell from 9.45 to 7.09 seconds, and Browser-use itself limits the claim to that one task.
The moment an agent moves from answering questions to taking actions, the question changes from "was the answer good" to "should this have happened". Our permissions and guardrails for AI agents page covers the permission model: which tools the agent has, what each can touch, and how a person approves the dangerous ones. This page is about the check that runs on each individual call, and what a decision model changes about it.
What it changes is cost and shape. A check that costs a language-model generation per tool call gets turned off when the agent makes 40 calls a task. A check that costs one typed request in TypeSafe's reported 70 to 500 milliseconds [1] can run on every call, and because it returns probabilities rather than prose, the decision rule is a threshold in code.
Where the gate sits
The gate is code between the agent and the tool. The agent proposes a call (a tool name and arguments), the gate builds a state from the proposal plus the context it needs (the user's original request, the tool's description, the argument values), asks Jev a set of questions, and returns one of three outcomes: run, confirm, or block. The tool executes only on run, or on confirm after a person says yes.
Two properties make it a real gate. The agent cannot call the tool any other way, and the gate's decision is code over the probabilities, never a model deciding to skip itself. TypeSafe's design guide's rule applies with full force here: side effects stay in code [2].
LangChain's harness post describes this as a middleware, which is code that runs between the agent framework and the tool. Its example uses Jev to classify a tool call's risk and blocks the call before the tool executes; the post gives no thresholds, only the mechanism [3]. Openlayer's jevals has a ToolCallRisk check that gates tool execution with approve, escalate and block outcomes, and it distinguishes read-only operations from irreversible ones such as refunds, deletions and external messages; it also ships an ExcessiveAgency check for whether the agent exceeded its authorised scope [4]. Both are the same shape as what we build.
A Noul per side effect
The design we use asks one Noul question per kind of consequence, about the proposed call, in one request. The questions are narrow and named, following TypeSafe's guidance that a broad question hides several judgments [2]:
deletes_data: this call would remove or overwrite existing records.
moves_money: this call would charge, refund, transfer or change a balance.
leaves_the_system: this call would send a message, an email or a request to a party outside the application.
matches_request: this call does what the user asked for, with these argument values.
exceeds_scope: this call touches a resource the user did not mention and the task does not need.
The first three are about the tool and its arguments and are often answerable from the tool definition alone, in which case they belong in a lookup table rather than a question; ask the model only where the arguments decide it (an update that sets a field to empty is a delete). The last two are about the relationship between the call and the request, and they are the ones where a decision model is worth using, because they need the sentence read.
A Score question can join them: how severe would the worst outcome of this call be, on a 0 to 3 scale described in words, the same shape as the severity score in TypeSafe's guardrail cookbook [5].
Thresholds by consequence
TypeSafe's confidence page says different actions within one system should be gated at different levels depending on the consequences, and that a read-only operation tolerates lower confidence than a destructive one [6]. For tool calls that becomes a table keyed by the answers above.
A read (fetch a record, search, list): run unless matches_request is below 0.3, in which case confirm.
A reversible write (create a draft, add a tag, update a field with history): run if matches_request is above 0.8 and exceeds_scope is below 0.2; confirm otherwise.
A message that leaves the system (email, notification, external API call): confirm unless matches_request is above 0.9 and exceeds_scope is below 0.1, and block if the severity score is at or above 2.
An irreversible action (delete without history, payment, transfer): confirm always, and block if deletes_data or moves_money is above 0.5 while matches_request is below 0.7. Some teams choose never to run these automatically, and that is a policy decision rather than a threshold.
The numbers are starting points. The tuning signal is the confirmation queue: if a person approves a class of call unchanged every time, the threshold for that class can come down; if a person overturns calls that ran, it goes up. Confidence-gated routing covers the logging and the monthly calibration check that keep that tuning tied to outcomes.
The human step in the uncertain band
The confirm outcome is a message to a person showing the tool, the arguments, the user's request and the probabilities, with approve and reject buttons. Two rules keep it useful.
The person's decision is stored as a label against the state that produced it. That labelled set is what you re-run when the model version changes, and it is how the thresholds get tuned from evidence.
Confirmation is capped. An agent that asks for confirmation on every call has a gate set too high, and a person who approves without reading has a gate that no longer works. Track the approve rate per tool; a rate near 100 percent means the threshold should come down for that tool, and a rate that suddenly drops means something changed in the agent or the model.
How to decide if a feature needs a human in the loop is the shorter piece on when a confirmation step belongs in a product at all.
A decision model choosing the actions: Browser-use's Jev Ultrafast
The gate above checks actions a language model proposed. Browser-use went one step further on 16 September 2026 and had Jev choose the action. Its Jev Ultrafast agent reads a structured table of the controls on the page, each with an index, a control type and a label with its current value, instead of a screenshot, and asks one request that returns both the operation (click, type text, select, scroll, wait, done, or blocked) and the target index; in Browser-use's words, "Two decisions, one network round trip" [7]. Only operations compatible with a target are offered as options, so the model cannot pick an impossible pair.
Browser-use's measurement is six alternating runs of one Google Flights task: median time fell from 9.450 seconds to 7.092 seconds, and browser protocol calls fell from 1,092 to 101 [7]. The README says plainly that this is three repeats of one task on one browser profile and "not a general reliability benchmark". We cite it for the design, and the caveat stays attached to the number. Our AI News item is Browser-use's Jev Ultrafast.
The design is the interesting part for a gate. When the action space is a fixed list and the state is a structured table, the action choice itself is a Choice question with a probability per option, and the same threshold logic that gates a proposed call can gate the choice: a low-confidence click waits for a person, a high-confidence one runs. The "blocked" option in Browser-use's list is the model's way of saying that no action fits, which is the "none of these" case from intent routing.
What the gate does not replace
A decision model reads the proposal and returns probabilities, and enforcement stays with code. The tool still needs a permission check in code that the gate cannot override, argument validation against a schema, and an allowlist of what each tool may touch. TypeSafe's jaggedness page says adversarial content in the state can move the answer [8], and a tool call whose arguments were shaped by text the agent read from a web page or an email is exactly that case, which prompt injection and adversarial input covers. Openlayer's IndirectInjection check, for instructions inside tool results, retrieved documents or emails, exists for the same reason [4].
The gate also needs an audit log: tool, arguments, state hash, model version, every probability, the outcome and, for a confirm, the person and their decision. How to audit an AI agent's tool permissions is the checklist for reading that log.
Where Reveneau fits
Reveneau builds agents with this gate in code between the agent and every tool that has a side effect, with the thresholds in a versioned table and the confirmation labels feeding the eval suite. The suite itself is graded with Jev: whether an agent's trace followed the plan is a Noul question with the rubric in the criteria, and a grade in the uncertain band goes to a person whose label is kept. Evals with Jev describes that setup, and can you trust an AI agent is the argument for why the gate has to be in code rather than in the model's instructions.
Best for
- Agents with tools that delete, pay, or send messages outside the application.
- Teams that want a check on every call at a cost that does not tempt anyone to turn it off.
- Products where a person can confirm the uncertain calls and their decisions can be kept as labels.
Avoid if
- The agent can reach the tool by a path that skips the gate.
- There is no permission check or schema validation in code behind the gate.
- Nobody will staff the confirmation queue, so confirm becomes block or becomes run.
Check before you decide
- Every side-effect tool is reachable only through the gate.
- Each consequence has its own Noul and its own threshold, written in a versioned table.
- The confirmation approve rate is tracked per tool and drives threshold changes.
- The audit log holds the arguments, probabilities, model version and outcome for every call.
Common questions
Where should a tool-call gate sit in an agent?
In code between the agent's proposed call and the tool, on the only path to the tool. The agent proposes a tool name and arguments, the gate builds a state from the proposal and the user's request, asks Jev a set of questions in one request, and returns run, confirm or block. The tool executes only on run or after a person confirms. TypeSafe's design rule applies: side effects stay in code, and the model never decides to skip the gate.
What questions should the gate ask about a proposed tool call?
One Noul per consequence, in one request: deletes_data, moves_money, leaves_the_system, matches_request and exceeds_scope, plus optionally a 0 to 3 severity Score. The first three are often answerable from the tool definition and belong in a lookup table unless the arguments decide them. The last two need the user's sentence read against the call, which is where the decision model is worth using. Keep each question narrow, because a broad question hides several judgments.
What thresholds should gate a delete or a payment?
Confirm always as the starting policy, and block when deletes_data or moves_money is above 0.5 while matches_request is below 0.7. TypeSafe's confidence page says destructive actions need a higher threshold than read-only ones, and some teams decide irreversible actions never run automatically, which is a policy rather than a threshold. Tune from the confirmation queue: a class of call a person approves unchanged every time can have its threshold lowered.
What does LangChain's harness middleware do with Jev?
LangChain's post of 17 September 2026 describes a middleware, code that runs between the agent framework and the tool, which uses Jev to classify a tool call's risk and blocks the call before the tool executes. The post also describes a ModelRouterMiddleware that picks the least costly model able to complete a task. It gives the mechanism and no thresholds, so the numbers on this page are ours and should be tuned from your own confirmation queue.
What does Openlayer's ToolCallRisk check return?
Approve, escalate or block for a proposed tool call, distinguishing read-only operations from irreversible actions such as refunds, deletions and external messaging, per the jevals README. The same library ships ExcessiveAgency, for whether the agent exceeded its authorised scope, and IndirectInjection, for instructions hidden inside tool results, retrieved documents or emails. jevals is MIT-licensed and marked alpha as of 20 September 2026, so read it as a design to copy rather than a dependency to rely on.
What did Browser-use's Jev Ultrafast measure?
Six alternating runs of one Google Flights task, with the median falling from 9.450 seconds to 7.092 seconds and browser protocol calls from 1,092 to 101. The agent reads an indexed table of page controls instead of a screenshot and asks one Jev request that returns both the operation and the target index. Browser-use's own README says this is three repeats of one task on one browser profile and not a general reliability benchmark, so cite the design and state the caveat with it.
Can a decision model choose an agent's action rather than only check it?
When the action space is a fixed list and the state is structured, yes: Browser-use's Jev Ultrafast offers click, type text, select, scroll, wait, done and blocked, restricted to operations compatible with each target, and a Choice question returns the operation and target with a probability per option. The same threshold logic then gates the choice: a low-confidence action waits for a person, a high-confidence one runs, and blocked is the model saying nothing fits.
How should the confirmation step be run so it keeps working?
Show the person the tool, the arguments, the user's request and the probabilities, store their decision as a label against that state, and track the approve rate per tool. A rate near 100 percent means the threshold is too high for that tool and can come down; a rate that drops suddenly means the agent or the model changed. An agent that asks on every call has a gate set too high, and a person who approves without reading has a gate that no longer works.
Does the gate replace permission checks in code?
No. The model reads the proposal and returns probabilities; it enforces nothing. The tool still needs a permission check the gate cannot override, argument validation against a schema, and an allowlist of what it may touch. TypeSafe's jaggedness page says adversarial content in the state can move the answer, and a tool call shaped by text the agent read from a web page or an email is that case, which is why Openlayer ships an IndirectInjection check.
What should the audit log of a gated tool call contain?
The tool name, the arguments, a hash of the state (a short fingerprint of its contents), the model version from the response, every probability returned, the threshold table version, the outcome (run, confirm, block) and, for a confirm, the person and their decision. With those fields a bad action can be traced to a question, a threshold or a model change, and the confirmation labels can be replayed against a new model version before the production pin moves.
How does Reveneau gate tool calls in the agents it builds?
With a gate in code on the only path to every side-effect tool, one Noul per consequence asked in one Jev request, thresholds in a versioned table, and a confirmation step whose labels feed the eval suite. Permission checks, schema validation and allowlists stay in code behind the gate. The suite itself is graded with Jev, so whether an agent's trace followed the plan is a Noul with the rubric in the criteria, and uncertain grades go to a person.
References
- [1] TypeSafe, Introducing System One models and Jev: 70 to 500 ms end to end.
- [2] TypeSafe docs, How to build with System One: keep side effects in code; broad questions hide several judgments behind one answer.
- [3] LangChain, Building a harness with Jev (17 September 2026): a middleware uses Jev to classify risky tool calls and blocks calls before the tool executes; no thresholds given.
- [4] Openlayer, jevals README: ToolCallRisk gates tool execution with approve, escalate and block, distinguishing read-only operations from irreversible actions such as refunds, deletions and external messaging; ExcessiveAgency; IndirectInjection for instructions inside tool results, retrieved docs and emails.
- [5] TypeSafe docs, LLM guardrails cookbook: a 0 to 3 severity score with levels described in words.
- [6] TypeSafe docs, Confidence: different actions within the same system should be gated at different levels depending on the consequences; read-only operations tolerate lower confidence than destructive ones.
- [7] Browser-use, Jev Ultrafast README (16 September 2026): operation and target index chosen in one request from an indexed element table (Two decisions, one network round trip); operations click, type text, select, scroll, wait, done, blocked; six alternating runs of one Google Flights task, median 9.450 s to 7.092 s, protocol calls 1,092 to 101; not a general reliability benchmark.
- [8] TypeSafe docs, Model jaggedness jev-1.13: adversarial content in the state can move the answer.
Related reading
How to audit an AI agent's tool permissions
An agent that can call more tools than its task needs is a permanent risk, and most teams find that out by reading an incident report instead of an audit.
Can you trust an AI agent with real work yet?
An agent that answers a question and an agent that takes an action are not the same risk. Here is how we decide where an agent is ready to act, and where it is not.
What a decision model changes about agent safety
A safety check that answers in under half a second and costs a fraction of a cent can run on every message and every tool call. Here is what that changes for an agent in front of real users, and the one thing it does not change.
More in Safety
Guardrails for an LLM app with one Jev request
A guardrail screens what goes into a language model and what comes out of it. With Jev, each screen is one request carrying a set of named questions (jailbreak, harmful_request, medical_advice, self_harm) and a 0 to 3 severity score, answered in parallel and returned as probabilities. TypeSafe's cookbook routes on two thresholds, 0.35 for review and 0.70 or 0.85 for action, with a precedence order of support, block, review, pass. This page explains the design, why it costs one decision-model request instead of a second language-model call, and how Openlayer's jevals packages the same idea as a security namespace.
Prompt injection and adversarial input: what Jev can and cannot catch
Prompt injection is text that a person or a document puts in front of a model to make it do something other than what the application asked. TypeSafe's page on Jev's known weaknesses says adversarial content in the state can move the answer and that the model does not treat content as hostile by default. So a Jev screen catches some injection and can be fooled by the rest, which makes it one layer of defence. This page covers how to build the state so untrusted text is marked as such, how to write questions that resist manipulation, which checks belong in code regardless, how to test with known attack strings, and what to log so a bypass can be found afterwards.