Skip to content

Restore Action inputs to act - #2427

Open
monadoid wants to merge 3 commits into
v4-spikefrom
restore-act-action
Open

Restore Action inputs to act#2427
monadoid wants to merge 3 commits into
v4-spikefrom
restore-act-action

Conversation

@monadoid

@monadoid monadoid commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

There were duplicate act schemas so we were missing the ability to pass in action inputs to act().
In Shriya’s v4 eval PR, 27 out of 359 Act eval rows were failing for exactly this missing functionality:

throw new Error(
  "V4 GAP: v4 has no act(observeResult) self-healing replay...

Before this fix, Stagehand v3 scored 93.89% on Act (338/360), while v4 scored 78.83% (283/359). Naively assuming all 27 affected rows pass once the fix is merged and the evals are re-enabled, v4 would reach 86.35% (310/359)—an improvement of 7.52 percentage points.

This restores string | Action directly on the canonical StagehandActParamsSchema across the protocol, TypeScript SDK, Python SDK, and server.

The unused legacy ActRequestSchema and its paired response/types are removed, leaving one live Act request contract and one reusable ActionSchema.


Summary by cubic

Restores passing an Action from observe to act in v4 for deterministic replay and self-healing. Unifies Act input on StagehandActParamsSchema and makes protocol result schemas strict.

  • New Features

    • StagehandActParamsSchema.input now accepts string | Action across the protocol (stagehand.v4.json), server, sdk-ts, and sdk-python.
    • Server: passing an Action skips the first LLM call and runs the deterministic executor with variable substitution and self-healing.
    • Docs: packages/docs/v4/reference/stagehand.mdx documents Action fields for TS and Python; sdk-ts exports Action and ActResultData.
  • Refactors

    • Removed legacy ActRequestSchema/ActResponseSchema; one Act request contract plus a reusable ActionSchema.
    • Protocol result schemas now use strict objects (no extra fields).

Written for commit 53cbf8f. Summary will update on new commits.

Review in cubic

@changeset-bot

changeset-bot Bot commented Jul 25, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 53cbf8f

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

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

@monadoid
monadoid marked this pull request as ready for review July 25, 2026 13:58

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

No issues found across 12 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.
Architecture diagram
sequenceDiagram
    participant SDK as SDK (TS/Python)
    participant Client as StagehandClient
    participant Server as Act Service
    participant LLM as LLM Provider
    participant Browser as Browser Page

    Note over SDK,Browser: Act Call Flow - Action Input Path (NEW)

    SDK->>Client: act(action: Action)
    Note over SDK,Client: Input is Action object (not string)
    Client->>Server: stagehand.act({ input: Action, pageId, options })

    Server->>Server: Detect typeof input !== "string"
    
    alt Deterministic replay succeeds
        Server->>Server: takeDeterministicAction(action)
        Server->>Browser: performAction(method, selector, args)
        Browser-->>Server: Action executed
        Server-->>Client: { success: true, actions: [...] }
        Client-->>SDK: ActResult
    else Deterministic replay fails
        Server->>Server: takeDeterministicAction(action) fails
        Note over Server: Element detached / stale
        Server->>Server: Fall back to LLM self-healing path
        Server->>Browser: captureSnapshot()
        Browser-->>Server: DOM snapshot
        Server->>LLM: getActionFromLLM(instruction, dom)
        LLM-->>Server: New action with fresh selector
        Server->>Browser: performAction(new method, new selector)
        Browser-->>Server: Action executed
        Server-->>Client: { success: true, actions: [...] }
        Client-->>SDK: ActResult
    end

    Note over SDK,Browser: Act Call Flow - String Input Path (unchanged)

    SDK->>Client: act(instruction: string)
    Client->>Server: stagehand.act({ input: string, pageId, options })
    Server->>Browser: waitForDomNetworkQuiet()
    Server->>Browser: captureSnapshot()
    Browser-->>Server: DOM snapshot
    Server->>LLM: getActionFromLLM(buildActPrompt(instruction))
    LLM-->>Server: Inferred action
    Server->>Browser: performAction(method, selector, args)
    Browser-->>Server: Action executed
    Server-->>Client: ActResult
    Client-->>SDK: ActResult
Loading

Re-trigger cubic

@monadoid
monadoid force-pushed the restore-act-action branch from 8233173 to 44766ae Compare July 28, 2026 11:40
@monadoid
monadoid requested a review from a team as a code owner July 28, 2026 11:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant