Repository navigation
Add an example of a decision model approving an agent's tool calls - #74697
Merged
Merged
Conversation
A HandleDeferredToolCalls handler asks a decision model whether each call that needs approval may run. A confident allow runs it, a confident deny refuses it, and anything else, including a judge that cannot be reached, goes to AgentOperator's existing per-tool approval pause.
vatsrahul1001
approved these changes
Oct 14, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
With per-tool approval (#73586), a support agent allowed to refund orders asks a person about every refund, and most refunds are routine. This adds an example Dag and a section in the tool-approval guide where a decision model answers "may this call run without a person?" for each call that needs approval. A confident
allowruns the call. A confidentdenyrefuses it, and the agent is told, as after a Reject. Everything else goes to the existing approval pause: areviewanswer, low or missing confidence, a judge that cannot be reached, and any call to a tool already refused earlier in the run.It adds no operator or parameter. The handler is pydantic-ai's
HandleDeferredToolCallscapability, passed throughcapabilities=. It sees each call waiting for approval with its validated arguments and resolves the ones it is sure about; pydantic-ai returns the rest asDeferredToolRequests, whichAgentOperatoralready pauses on.Why not the
.approval_required()function. It is typed as a synchronousCallable[..., bool], so it cannot await a model call. The guide says when that function is still the right tool: a limit you can write down, such as refunds over $50, needs no model. The model is for whether the call fits the request: the right order, an amount the customer's problem supports, an action somebody asked for.Hard limits stay in code. The refund cap is the tool's
args_validator, which pydantic-ai runs before the call is marked for approval, so an over-limit refund goes back to the agent without the model or a person being asked about it.I ran the judge once against TypeSafe Jev 1.13.0 on 12 proposed calls: routine refunds, a wrong order, a wrong amount, an account closure nobody asked for, and two calls where the arguments or the request argued for their own approval. Every call that should not run got
denyat confidence 0.70 or higher, withallowprobability at most 0.01. Two of the three routine refunds came backreview, so its misses send work to a person rather than letting a bad call through. That is one pass with no repeats, so the guide tells readers to set the bar from their own agent's calls instead of quoting these numbers.Gotchas:
pydantic-ai-slim2.46+ (forUseEnumMemberDocstrings). The test module skips below both.{pr_number}.significant.rst, in airflow-core/newsfragments. You can add this file in a follow-up commit after the PR is created so you know the PR number.