Skip to content

[Claimed #2026] fix: unwrap Anthropic $PARAMETER_NAME wrapper in tool responses (fixes #1986)#2030

Open
github-actions[bot] wants to merge 3 commits intomainfrom
external-contributor-pr-2026
Open

[Claimed #2026] fix: unwrap Anthropic $PARAMETER_NAME wrapper in tool responses (fixes #1986)#2030
github-actions[bot] wants to merge 3 commits intomainfrom
external-contributor-pr-2026

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

Mirrored from external contributor PR #2026 after approval by @pirate.

Original author: @kagura-agent
Original PR: #2026
Approved source head SHA: d09ebd59f40d6d0e48dc1b41810597b3c1c19efc

@kagura-agent, please continue any follow-up discussion on this mirrored PR. When the external PR gets new commits, this same internal PR will be marked stale until the latest external commit is approved and refreshed here.

Original description

Problem

When using Anthropic models (e.g., anthropic/claude-sonnet-4-5) with act() or extract(), Claude wraps tool_use output in a { $PARAMETER_NAME: { ... } } envelope. This causes Zod schema validation to fail with AI_NoObjectGeneratedError because all expected fields appear undefined at the top level.

Reported in #1986.

Fix

Add a small unwrapToolResponse() helper that detects single-key objects with a $-prefixed key and strips the wrapper:

  • AnthropicClient.ts — unwrap toolUse.input before returning to callers
  • aisdk.ts — catch NoObjectGeneratedError, attempt to JSON-parse err.text, unwrap and re-validate against the schema. If recovery succeeds, return normally; if not, throw the original error

The helper is defensive: it only unwraps when the object has exactly one $-prefixed key, so non-Anthropic responses pass through unchanged.

Changes

File Change
unwrapToolResponse.ts New utility — detect and strip $PARAMETER_NAME wrapper
AnthropicClient.ts Apply unwrapToolResponse() to toolUse.input
aisdk.ts Recovery path in NoObjectGeneratedError catch block
unwrapToolResponse.test.ts 8 unit tests covering unwrap, passthrough, edge cases

Testing

  • 8 unit tests for the helper (wrapped objects, non-wrapped, arrays, null, primitives, empty objects, multi-key objects)
  • No changes to existing tests required (additive fix)

Summary by cubic

Fixes schema validation failures for Anthropic tool responses by unwrapping the $PARAMETER_NAME envelope so act()/extract() return a flat object. Prevents errors with models like anthropic/claude-sonnet-4-5 (fixes #1986).

  • Bug Fixes
    • Added unwrapToolResponse() to strip single $-prefixed wrappers; no-op otherwise.
    • Unwrap applied in the Anthropic client before returning toolUse.input; added a recovery path in @aisdk to parse error text, unwrap, re-validate, and return on success.
    • Added unit tests for wrapped, passthrough, and edge cases.

Written for commit d09ebd5. Summary will update on new commits. Review in cubic

@github-actions github-actions Bot added external-contributor Tracks PRs mirrored from external contributor forks. external-contributor:mirrored An internal mirrored PR currently exists for this external contributor PR. labels Apr 23, 2026
@github-actions
Copy link
Copy Markdown
Contributor Author

github-actions Bot commented Apr 23, 2026

This mirrored PR could not be refreshed automatically after approval by @pirate.

Refresh reason: missing-previous-source
Resolve the branch manually, then keep using this same mirrored PR.

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Apr 23, 2026

🦋 Changeset detected

Latest commit: d09ebd5

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

This PR includes changesets to release 4 packages
Name Type
@browserbasehq/stagehand Patch
@browserbasehq/stagehand-evals Patch
@browserbasehq/stagehand-server-v3 Patch
@browserbasehq/stagehand-server-v4 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

@pirate pirate closed this Apr 23, 2026
@github-actions github-actions Bot added external-contributor:stale The mirrored PR is stale and waiting for a fresh approval to refresh. and removed external-contributor:mirrored An internal mirrored PR currently exists for this external contributor PR. labels Apr 23, 2026
@pirate pirate reopened this Apr 23, 2026
@github-actions github-actions Bot added external-contributor:mirrored An internal mirrored PR currently exists for this external contributor PR. and removed external-contributor:stale The mirrored PR is stale and waiting for a fresh approval to refresh. labels Apr 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

external-contributor:mirrored An internal mirrored PR currently exists for this external contributor PR. external-contributor Tracks PRs mirrored from external contributor forks.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

act() fails with Anthropic models: response wrapped in $PARAMETER_NAME key

2 participants