Skip to content

Conversation

@shrey150
Copy link
Contributor

@shrey150 shrey150 commented Dec 24, 2025

why

  • Previously, we auto-approved all safety checks for CUA models
  • There are cases in which the caller wants to have the human approve/deny the request
  • Therefore, we should allow the handler to pass through any safety checks

what changed

  • Added support for safety checks and safety confirmations, which have a handler to intercept requests

test plan

  • Performed a risky request on a banking site and observed a safety check pop up

Summary by cubic

Adds safety confirmation support for OpenAI and Google CUA so risky actions can be reviewed and approved by a user. Defaults to auto-acknowledge when no handler is provided.

  • New Features
    • Added SafetyCheck, SafetyConfirmationResponse, and SafetyConfirmationHandler types.
    • Added onSafetyConfirmation to AgentExecuteOptions.callbacks for non-streaming CUA agents; streaming not supported and V3 prevents using it on non-CUA agents.
    • OpenAICUAClient now requests confirmation for pending_safety_checks and sets acknowledged_safety_checks when approved.
    • GoogleCUAClient now requests confirmation for safety_decision and sets safety_acknowledgement when approved.
    • v3CuaAgentHandler wires the handler to CUA clients via setSafetyConfirmationHandler.

Written for commit 657fafc. Summary will update automatically on new commits.

@changeset-bot
Copy link

changeset-bot bot commented Dec 24, 2025

🦋 Changeset detected

Latest commit: 657fafc

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
@browserbasehq/stagehand Patch
@browserbasehq/stagehand-evals Patch
@browserbasehq/stagehand-server Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 5 files

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Dec 24, 2025

Greptile Summary

This PR adds safety confirmation support for OpenAI and Google CUA models, allowing callers to intercept and approve/deny risky actions instead of auto-approving all safety checks.

Key Changes

  • Type Definitions: Added SafetyCheck, SafetyConfirmationResponse, and SafetyConfirmationHandler types with comprehensive documentation
  • OpenAI CUA: Implemented handleSafetyConfirmation to process pending_safety_checks and set acknowledged_safety_checks based on user response
  • Google CUA: Implemented handleSafetyConfirmation to process safety_decision and set safety_acknowledgement based on user response
  • Handler Integration: V3CuaAgentHandler passes callbacks.onSafetyConfirmation through to CUA clients via setSafetyConfirmationHandler
  • Validation: Added check in prepareAgentExecution to prevent non-CUA agents from using onSafetyConfirmation callback
  • Auto-acknowledge Fallback: Both implementations auto-acknowledge when no handler is provided, maintaining backward compatibility

Implementation Quality

The implementation is well-structured and follows existing patterns in the codebase. Safety confirmation logic is consistently handled across both providers, with proper logging and error handling. Unit tests cover the core logic paths including acknowledgement, rejection, and auto-acknowledgement scenarios.

Confidence Score: 5/5

  • This PR is safe to merge with no identified issues
  • The implementation is clean, well-tested, and maintains backward compatibility through auto-acknowledgement. The safety confirmation feature is properly scoped to CUA agents only with appropriate validation. Code follows existing patterns, includes comprehensive type definitions, and has unit test coverage for the core logic.
  • No files require special attention

Important Files Changed

Filename Overview
packages/core/lib/v3/types/public/agent.ts Added SafetyCheck, SafetyConfirmationResponse, and SafetyConfirmationHandler types with clear documentation and examples. Added onSafetyConfirmation to AgentExecuteCallbacks and appropriate unavailability markers for streaming mode.
packages/core/lib/v3/agent/OpenAICUAClient.ts Added safety confirmation handler support for OpenAI CUA. Handles pending_safety_checks by requesting user confirmation or auto-acknowledging. Implementation correctly handles both success and error paths.
packages/core/lib/v3/agent/GoogleCUAClient.ts Added safety confirmation handler support for Google CUA. Handles safety_decision by requesting user confirmation or auto-acknowledging. Correctly converts safety decisions to SafetyCheck format.
packages/core/lib/v3/handlers/v3CuaAgentHandler.ts Added setSafetyConfirmationHandler method that delegates to CUA clients. Handler is set at the start of execute() from callbacks.onSafetyConfirmation.
packages/core/lib/v3/v3.ts Added validation to prevent non-CUA agents from using onSafetyConfirmation callback. The check correctly throws an error for DOM mode agents while allowing CUA agents to use the callback.

Sequence Diagram

sequenceDiagram
    participant User
    participant V3CuaAgentHandler
    participant CUAClient as OpenAICUAClient/GoogleCUAClient
    participant Provider as OpenAI/Google API
    participant Handler as SafetyConfirmationHandler

    User->>V3CuaAgentHandler: execute(options with callbacks.onSafetyConfirmation)
    V3CuaAgentHandler->>V3CuaAgentHandler: setSafetyConfirmationHandler(callback)
    V3CuaAgentHandler->>CUAClient: setSafetyConfirmationHandler(callback)
    
    V3CuaAgentHandler->>CUAClient: execute task
    CUAClient->>Provider: send request
    Provider-->>CUAClient: response with pending_safety_checks/safety_decision
    
    alt Handler is set
        CUAClient->>Handler: call handler(safetyChecks)
        Handler-->>User: prompt for confirmation
        User-->>Handler: approve/deny
        Handler-->>CUAClient: {acknowledged: true/false}
        alt User approved
            CUAClient->>Provider: send acknowledged_safety_checks/safety_acknowledgement
        else User denied
            CUAClient->>Provider: continue without acknowledgement
        end
    else No handler set
        CUAClient->>CUAClient: auto-acknowledge
        CUAClient->>Provider: send acknowledged_safety_checks/safety_acknowledgement
    end
    
    Provider-->>CUAClient: final response
    CUAClient-->>V3CuaAgentHandler: agent result
    V3CuaAgentHandler-->>User: return result
Loading

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

5 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

@seanmcguire12
Copy link
Member

@greptileai

@seanmcguire12 seanmcguire12 changed the title Add safety confirmation support for OpenAI + Google CUA [feat]: add support for safety confirmation callback for OpenAI + Google CUA Dec 24, 2025
@seanmcguire12 seanmcguire12 merged commit e021674 into main Dec 24, 2025
20 checks passed
miguelg719 pushed a commit that referenced this pull request Dec 27, 2025
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and the packages will
be published to npm automatically. If you're not ready to do a release
yet, that's fine, whenever you add more changesets to main, this PR will
be updated.


# Releases
## @browserbasehq/[email protected]

### Patch Changes

- [#1461](#1461)
[`0f3991e`](0f3991e)
Thanks [@tkattkat](https://github.com/tkattkat)! - Move hybrid mode out
of experimental

- [#1433](#1433)
[`e0e22e0`](e0e22e0)
Thanks [@tkattkat](https://github.com/tkattkat)! - Put hybrid mode
behind experimental

- [#1456](#1456)
[`f261051`](f261051)
Thanks [@shrey150](https://github.com/shrey150)! - Invoke page.hover for
agent move action

- [#1473](#1473)
[`e021674`](e021674)
Thanks [@shrey150](https://github.com/shrey150)! - Add safety
confirmation support for OpenAI + Google CUA

- [#1399](#1399)
[`6a5496f`](6a5496f)
Thanks [@tkattkat](https://github.com/tkattkat)! - Ensure cua agent is
killed when stagehand.close is called

- [#1436](#1436)
[`fea1700`](fea1700)
Thanks [@miguelg719](https://github.com/miguelg719)! - Fix auto-load key
for act/extract/observe parametrized models on api

- [#1439](#1439)
[`5b288d9`](5b288d9)
Thanks [@tkattkat](https://github.com/tkattkat)! - Remove base64 from
agent actions array ( still present in messages object )

- [#1408](#1408)
[`e822f5a`](e822f5a)
Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - allow for
act() cache hit when variable values change

- [#1472](#1472)
[`638efc7`](638efc7)
Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - fix: agent
cache not refreshed on action failure

- [#1424](#1424)
[`a890f16`](a890f16)
Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - fix:
"Error: -32000 Failed to convert response to JSON: CBOR: stack limit
exceeded"

- [#1418](#1418)
[`934f492`](934f492)
Thanks [@miguelg719](https://github.com/miguelg719)! - Cleanup handlers
and bus listeners on close

- [#1430](#1430)
[`bd2db92`](bd2db92)
Thanks [@shrey150](https://github.com/shrey150)! - Fix CUA model
coordinate translation

- [#1465](#1465)
[`51e0170`](51e0170)
Thanks [@miguelg719](https://github.com/miguelg719)! - Add media
resolution high provider option to gemini 3 hybrid agent

- [#1431](#1431)
[`05f5580`](05f5580)
Thanks [@tkattkat](https://github.com/tkattkat)! - Update the cache
handling for agent

- [#1432](#1432)
[`f56a9c2`](f56a9c2)
Thanks [@tkattkat](https://github.com/tkattkat)! - Deprecate cua: true
in favor of mode: "cua"

- [#1406](#1406)
[`b40ae11`](b40ae11)
Thanks [@tkattkat](https://github.com/tkattkat)! - Add support for
hovering with coordinates ( page.hover )

- [#1407](#1407)
[`0d2b398`](0d2b398)
Thanks [@tkattkat](https://github.com/tkattkat)! - Clean up page methods

- [#1412](#1412)
[`cd01f29`](cd01f29)
Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - fix: load
GOOGLE_API_KEY from .env

- [#1462](#1462)
[`a734fca`](a734fca)
Thanks [@shrey150](https://github.com/shrey150)! - fix: correctly pass
userDataDir to chrome launcher

- [#1466](#1466)
[`b342acf`](b342acf)
Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - move
playwright to optional dependencies

- [#1440](#1440)
[`2987cd1`](2987cd1)
Thanks [@tkattkat](https://github.com/tkattkat)! - [Feature] support
excluding tools from agent

- [#1455](#1455)
[`dfab1d5`](dfab1d5)
Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - update
aisdk client to better enforce structured output with deepseek models

- [#1428](#1428)
[`4d71162`](4d71162)
Thanks [@tkattkat](https://github.com/tkattkat)! - Add "hybrid" mode to
stagehand agent

## @browserbasehq/[email protected]

### Minor Changes

- [#1459](#1459)
[`abb3469`](abb3469)
Thanks [@monadoid](https://github.com/monadoid)! - Added building of
binaries

- [#1457](#1457)
[`5fc1281`](5fc1281)
Thanks [@monadoid](https://github.com/monadoid)! - First changeset for
stagehand-server

- [#1469](#1469)
[`d634d45`](d634d45)
Thanks [@monadoid](https://github.com/monadoid)! - Bump to test binary
builds

### Patch Changes

- Updated dependencies
\[[`0f3991e`](0f3991e),
[`e0e22e0`](e0e22e0),
[`f261051`](f261051),
[`e021674`](e021674),
[`6a5496f`](6a5496f),
[`fea1700`](fea1700),
[`5b288d9`](5b288d9),
[`e822f5a`](e822f5a),
[`638efc7`](638efc7),
[`a890f16`](a890f16),
[`934f492`](934f492),
[`bd2db92`](bd2db92),
[`51e0170`](51e0170),
[`05f5580`](05f5580),
[`f56a9c2`](f56a9c2),
[`b40ae11`](b40ae11),
[`0d2b398`](0d2b398),
[`cd01f29`](cd01f29),
[`a734fca`](a734fca),
[`b342acf`](b342acf),
[`2987cd1`](2987cd1),
[`dfab1d5`](dfab1d5),
[`4d71162`](4d71162)]:
    -   @browserbasehq/[email protected]

## @browserbasehq/[email protected]

### Patch Changes

- [#1373](#1373)
[`cadd192`](cadd192)
Thanks [@tkattkat](https://github.com/tkattkat)! - Update screenshot
collector in agent evals cli

- Updated dependencies
\[[`0f3991e`](0f3991e),
[`e0e22e0`](e0e22e0),
[`f261051`](f261051),
[`e021674`](e021674),
[`6a5496f`](6a5496f),
[`fea1700`](fea1700),
[`5b288d9`](5b288d9),
[`e822f5a`](e822f5a),
[`638efc7`](638efc7),
[`a890f16`](a890f16),
[`934f492`](934f492),
[`bd2db92`](bd2db92),
[`51e0170`](51e0170),
[`05f5580`](05f5580),
[`f56a9c2`](f56a9c2),
[`b40ae11`](b40ae11),
[`0d2b398`](0d2b398),
[`cd01f29`](cd01f29),
[`a734fca`](a734fca),
[`b342acf`](b342acf),
[`2987cd1`](2987cd1),
[`dfab1d5`](dfab1d5),
[`4d71162`](4d71162)]:
    -   @browserbasehq/[email protected]

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants