Add tool approval integration for Vercel AI adapter - #3771
Closed
bendrucker wants to merge 6 commits into
Closed
Conversation
When agent run result contains DeferredToolRequests with approvals, emit ToolApprovalRequestChunk for each tool call requiring human approval. Uses tool_call_id as both approval_id and tool_call_id.
- Use event.result.response instead of all_messages() - Set finish_reason to error in on_error - Remove tool approval emission (defer to separate PR) - Update test snapshots for finishReason field
- Add ToolApproval types (ToolApprovalRequested, ToolApprovalResponded) - Add approval field to all tool part types - Emit ToolApprovalRequestChunk when DeferredToolRequests is returned - Add deferred_tool_results property to extract approval responses - Add tests for tool approval request emission and extraction
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.
Adds tool approval integration for the Vercel AI adapter, enabling human-in-the-loop workflows with the AI SDK.
This PR builds on #3760 and implements the basic plumbing for tool approval. The integration is functional for emitting approval requests and parsing approval responses, but does not yet automatically wire up the full flow.
Changes
ToolApprovalRequestedandToolApprovalRespondedtypes to represent approval stateapprovalfield to allToolUIPartandDynamicToolUIPartvariantsToolApprovalRequestChunkwhen agent returnsDeferredToolRequestsdeferred_tool_resultsproperty onVercelAIAdapterto extract approval responses from incoming tool partsextract_deferred_tool_results()class method for parsing approvalsHow It Works
Approval Request (server → client):
requires_approval=TrueDeferredToolRequestsVercelAIEventStream.handle_run_result()emitstool-approval-requestchunkApproval Response (client → server):
approvalfield with{id, approved, reason?}SubmitMessageincludes tool parts with approval responsesVercelAIAdapter.deferred_tool_resultsextracts these intoDeferredToolResultsOpen Questions
1. Automatic vs Manual Integration
Currently, users must manually wire up the deferred tool results:
Question: Should
run_stream()automatically useself.deferred_tool_resultswhen not explicitly provided? This would make the integration seamless but less explicit.2. Approval ID Tracking
We generate a UUID for
approval_idinToolApprovalRequestChunk, but the AI SDK uses this ID to track the approval lifecycle. TheToolApprovalResponded.idfield should match the originalapproval_id.Question: Do we need to store/track these approval IDs to validate they match on response? Currently we don't validate this.
3. ToolOutputDeniedChunk
The
ToolOutputDeniedChunktype exists but isn't emitted anywhere. In Pydantic AI, denied tool results flow as regularToolReturnPartwith the denial message as content.Question: Should we emit
ToolOutputDeniedChunkwhen the deferred tool result is aToolDenied? This would require tracking which tool calls were denied through the agent run.4. Message History Handling
When continuing with deferred tool results, the message history needs to include the original messages. Currently the adapter's
messagesproperty processes all incoming messages, but:Question: Should tool parts with pending approvals (only
ToolApprovalRequested, notToolApprovalResponded) be filtered out or handled specially when building message history?Testing
ToolApprovalRequestChunkemission whenrequires_approval=Truetool is calledextract_deferred_tool_results()covering approved, denied, and no-approval casesReferences