Loading
feat: #3586020 Per-tool approval mode with loop pause-resume
Closes #3586020
What this does
Adds a per-tool Approval mode setting on the agent form:
- Pre-approved: the tool runs without a human gate.
- Approve once per run: the first call asks; later calls to the same tool in the run are trusted.
- Always needs approval: every call asks.
Default differs from the issue
The issue proposes Always needs approval as the default for unconfigured tools. This MR defaults to Pre-approved instead (ToolApprovalMode::DEFAULT), so existing agents and callers that don't handle JOB_AWAITING_APPROVAL yet keep working after the update. Switching the default is a one-line change; happy to do it, possibly with an update hook that sets the mode explicitly on existing agents, if maintainers prefer fail-safe.
Loop integration
- When a queued tool call needs approval, the tool is not executed and the run returns
AiAgentInterface::JOB_AWAITING_APPROVAL. This happens before the loop counter moves, so waiting costs no loop. ToolApprovalAwareInterface(implemented byAiAgentEntityWrapper) exposesisAwaitingApproval(),getPendingToolApprovals(),getToolApprovals(),approveToolCall($handle)andrejectToolCall($handle, $reason). The caller decides, then runs the agent again to resume.- A rejected call is reported to the model as a tool message, so it can choose another action and the chat history stays valid for providers.
- Works for looped, non-looped and streamed runs.
Events
AgentToolApprovalRequestEvent: subscribers can allow, reject or require approval for a call, with a reason.AgentToolApprovalDecisionEvent: dispatched when a call is approved or rejected.
Tests
- Kernel:
AiAgentToolApprovalTest - Functional:
AiAgentToolApprovalModeFormTest
Edited by Gianfranco Fedele