Add tool approval example: agent, backend, UI, and E2E tests#226
Add tool approval example: agent, backend, UI, and E2E tests#226sethconvex merged 9 commits intomainfrom
Conversation
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This stack of pull requests is managed by Graphite. Learn more about stacking. |
commit: |
c70a594 to
ef701ff
Compare
f46cd2c to
0c83dae
Compare
8f636a7 to
9a18c30
Compare
52b4b56 to
ffb13f8
Compare
9a18c30 to
dc6edb1
Compare
ffb13f8 to
3953862
Compare
dc6edb1 to
8bcb7bd
Compare
3953862 to
4e8cd39
Compare
8bcb7bd to
1a12002
Compare
4e8cd39 to
2bfbdd6
Compare
972fcde to
b5e37ec
Compare
Merge activity
|
Example implementation of the tool approval flow: - Approval agent with a delete_file tool that requires approval - Backend functions: sendMessage, submitApproval, handleApprovalDecision - React UI component with approve/deny buttons and denial reason input - E2E tests exercising approve and deny flows through usageHandler Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove the generateId override in startGeneration that caused all AI SDK internal IDs (approval IDs, tool execution IDs, message IDs) to be identical. The pending message is already linked via the explicit pendingMessageId parameter in addMessages. Document that approveToolCall/denyToolCall append at the end of the thread, so intervening messages between tool calls and approvals may cause provider errors (e.g., Anthropic's tool_use/tool_result adjacency requirement). Recommend disabling chat input while approvals are pending. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Prevents users from sending messages that would interleave between tool calls and their approval responses, which can cause errors with providers that require tool_use/tool_result adjacency (e.g. Anthropic). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Approval responses are now positioned at the same order as the original approval request by looking up the parent message ID. This preserves tool_call/tool_result adjacency even when the user sends messages between the tool call and the approval decision. Also updates the example default prompt to trigger two approval-requiring tool calls (deleteFile + transferMoney) for a better demo. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When multiple tools need approval in the same step, the old approach continued generation after each individual approval, causing the unapproved tools to re-emit duplicate approval cards. Now: submitApproval only saves the decision (returns messageId), and the frontend triggers continuation only when all pending approvals are resolved via a useEffect watching hasPendingApprovals. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The AI SDK's collectToolApprovals() only examines the last tool message for approval responses. When multiple approvals are saved as separate messages (one per approveToolCall/denyToolCall call), earlier approvals are invisible to the SDK, causing Anthropic to reject the request with "tool_use ids found without tool_result blocks". Fix: mergeApprovalResponseMessages() combines consecutive tool messages containing tool-approval-response parts into a single message before passing to the SDK. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Cast tool message content to the expected shape to avoid TS2339
("approvalId does not exist on type") from the union type.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…roval test - Clone content array before .push() to avoid mutating original messages - Add multi-tool approval E2E test (two tools needing approval in one step) - Rename _finishStreamId to finishStreamId (was misleadingly prefixed as unused) - Document order assumption in getApprovalRequestMessageId Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
b5e37ec to
700fab9
Compare

Summary
Example implementation demonstrating the tool approval flow from #222:
example/convex/agents/approval.ts):delete_filetool withneedsApproval: trueexample/convex/chat/approval.ts):sendMessage,submitApproval,handleApprovalDecisionexample/ui/chat/ChatApproval.tsx): Approve/Deny buttons with denial reason input, type-safe approval helpersexample/convex/approval.test.ts): Approve and deny flows through usageHandlerTest plan
🤖 Generated with Claude Code