mcpField
S
stagehand-automation

stagehand-automation

github.com/adaptationio开发76 次安装
代码仓库

关于 stagehand-automation

基于 Stagehand v3 的浏览器自动化技能,面向测试和网页任务开发者,支持用自然语言执行操作、提取结构化数据并观察页面状态;DOM 变化时可调整元素定位。

主要功能

  1. 01自然语言驱动浏览器操作
  2. 02提取带架构验证的数据
  3. 03观察页面元素与状态
  4. 04DOM 变化时自适应定位
  5. 05结合 Playwright 执行混合自动化

适用场景

  1. 01构建可适应界面改版的端到端测试
  2. 02从网站提取结构化信息
  3. 03自动填写复杂表单
  4. 04执行跨站点工作流

MCP 相关

Stagehand 可作为 MCP 服务启动,让 Claude Desktop 或其他兼容 MCP 的客户端控制浏览器。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/adaptationio/skrillz --skill stagehand-automation

安装后在 Claude Code 中输入/stagehand-automation确认已加载。

附带文件references/api-reference.mdreferences/troubleshooting.md

详细介绍

Stagehand 自动化

概述

Stagehand v3 是最先进的 AI 浏览器自动化框架,将脆弱的传统自动化与智能自修复能力相结合。它基于 Chrome DevTools Protocol(CDP)构建,速度比 v2 快 44%,并可与 Claude 无缝集成。

核心创新:DOM 发生变化时,AI 会自适应,而不是让测试失败。

核心 API:

  • act() - 使用自然语言执行操作
  • extract() - 从页面提取结构化数据
  • observe() - 识别元素和页面状态

快速入门(10 分钟)

1. 安装 Stagehand
npm install @browserbase/stagehand zod
2. 配置 Claude API
# Add to .env
ANTHROPIC_API_KEY=your_api_key_here
3. 编写第一个自动化脚本
import { Stagehand } from "@browserbase/stagehand";
import { z } from "zod";

async function main() {
  const stagehand = new Stagehand({
    env: "LOCAL",
    modelName: "claude-sonnet-4-20250514",
    modelClientOptions: {
      apiKey: process.env.ANTHROPIC_API_KEY,
    },
  });

  await stagehand.init();
  await stagehand.page.goto("https://news.ycombinator.com");

  // AI-powered action - survives UI changes!
  await stagehand.act({ action: "click on the first story link" });

  // Extract structured data
  const data = await stagehand.extract({
    instruction: "extract the story title and author",
    schema: z.object({
      title: z.string(),
      author: z.string(),
    }),
  });

  console.log(data);
  await stagehand.close();
}

main();
4. 运行
npx ts-node your-script.ts

核心 API

act() - 执行操作

使用自然语言执行操作:

// Click elements
await stagehand.act({ action: "click the login button" });

// Fill forms
await stagehand.act({ action: "fill in the email field with '[email protected]'" });
await stagehand.act({ action: "enter password 'securepass123'" });

// Navigate
await stagehand.act({ action: "scroll down to the pricing section" });
await stagehand.act({ action: "click the 'Sign Up' button in the header" });

// Complex actions
await stagehand.act({
  action: "select 'Premium' from the plan dropdown and click Continue"
});

自修复:如果按钮 ID 从 #login-btn 变为 #auth-signin,Stagehand 会自动适应。

extract() - 获取结构化数据

使用架构验证提取数据:

import { z } from "zod";

// Simple extraction
const title = await stagehand.extract({
  instruction: "get the main page title",
  schema: z.object({
    title: z.string(),
  }),
});

// Complex extraction
const products = await stagehand.extract({
  instruction: "extract all products with name, price, and availability",
  schema: z.object({
    products: z.array(z.object({
      name: z.string(),
      price: z.number(),
      inStock: z.boolean(),
    })),
  }),
});

// Extract from specific area
const cartItems = await stagehand.extract({
  instruction: "get items in the shopping cart",
  schema: z.object({
    items: z.array(z.object({
      name: z.string(),
      quantity: z.number(),
      price: z.number(),
    })),
    total: z.number(),
  }),
});
observe() - 分析页面状态

了解页面元素和状态:

// Find elements
const elements = await stagehand.observe({
  instruction: "find all clickable buttons on this page"
});

// Check state
const loginState = await stagehand.observe({
  instruction: "is the user logged in? Look for profile icons or logout buttons"
});

// Identify form fields
const formFields = await stagehand.observe({
  instruction: "identify all form input fields and their labels"
});

自修复模式

传统方式与 Stagehand 的对比
// TRADITIONAL (Playwright) - Breaks when DOM changes
await page.click('#submit-btn-v2');  // Fails if ID changes
await page.click('.btn-primary:nth-child(2)');  // Fails if order changes

// STAGEHAND - Self-healing
await stagehand.act({ action: "click the submit button" });  // Always works
await stagehand.act({ action: "click the primary action button" });  // Adapts
自修复的触发时机
  1. ID/类名变化:按钮 ID 从 #old-id 变为 #new-id
  2. 结构变化:元素在 DOM 树中的位置发生变化
  3. 文本变化:按钮文本从「Submit」变为「Send」
  4. 样式变化:CSS 类名经过重新整理
缓存(性能优化)

Stagehand v3 会缓存已发现的元素:

// First call: AI analyzes page, finds element (slow)
await stagehand.act({ action: "click login" });

// Second call: Uses cached selector (fast)
await stagehand.act({ action: "click login" });

// Cache invalidated when page changes significantly

混合方案:Playwright + Stagehand

将传统自动化的速度与 AI 的弹性相结合:

import { Stagehand } from "@browserbase/stagehand";
import { test, expect } from "@playwright/test";

test('hybrid test', async () => {
  const stagehand = new Stagehand({ env: "LOCAL" });
  await stagehand.init();

  // Use Playwright for stable, fast operations
  await stagehand.page.goto('https://app.example.com');
  await stagehand.page.fill('[data-testid="email"]', '[email protected]');

  // Use Stagehand for dynamic/fragile elements
  await stagehand.act({ action: "click the login button" });

  // Use Playwright for assertions
  await expect(stagehand.page).toHaveURL(/dashboard/);

  // Use Stagehand for complex extraction
  const dashboardData = await stagehand.extract({
    instruction: "get user stats from dashboard",
    schema: z.object({
      totalOrders: z.number(),
      accountBalance: z.number(),
    }),
  });

  expect(dashboardData.totalOrders).toBeGreaterThan(0);
});

Claude 集成

模型选择
// Claude Sonnet 4 (recommended - balance of speed/quality)
const stagehand = new Stagehand({
  modelName: "claude-sonnet-4-20250514",
  modelClientOptions: {
    apiKey: process.env.ANTHROPIC_API_KEY,
  },
});

// Claude Opus (highest quality, slower)
const stagehand = new Stagehand({
  modelName: "claude-opus-4-20250514",
});

// Claude Haiku (fastest, simpler tasks)
const stagehand = new Stagehand({
  modelName: "claude-3-5-haiku-20241022",
});
成本优化
// Use Haiku for simple actions (cheaper)
const simpleStagehand = new Stagehand({
  modelName: "claude-3-5-haiku-20241022",
});
await simpleStagehand.act({ action: "click login" });

// Use Sonnet for complex extraction
const complexStagehand = new Stagehand({
  modelName: "claude-sonnet-4-20250514",
});
const data = await complexStagehand.extract({
  instruction: "extract all product details with nested specifications",
  schema: complexSchema,
});
预估成本
操作模型预估成本
简单的 act()Haiku~$0.001
复杂的 act()Sonnet~$0.005
简单的 extract()Haiku~$0.002
复杂的 extract()Sonnet~$0.01

MCP 集成

通过 Model Context Protocol 在 Claude Desktop 中使用 Stagehand:

// Stagehand MCP server enables Claude to control browsers
// from Claude Desktop or any MCP-compatible client

import { StagehandMCPServer } from "@browserbase/stagehand/mcp";

const server = new StagehandMCPServer();
server.start();

// Now Claude can call:
// - stagehand.act({ action: "..." })
// - stagehand.extract({ instruction: "..." })
// - stagehand.observe({ instruction: "..." })

错误处理

try {
  await stagehand.act({
    action: "click the non-existent button",
    timeout: 10000,  // 10 second timeout
  });
} catch (error) {
  if (error.message.includes('timeout')) {
    console.log('Element not found within timeout');
  } else if (error.message.includes('multiple')) {
    console.log('Multiple matching elements found - be more specific');
  } else {
    throw error;
  }
}

// Retry pattern
async function actWithRetry(stagehand, action, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await stagehand.act({ action });
    } catch (error) {
      if (i === maxRetries - 1) throw error;
      await new Promise(r => setTimeout(r, 1000));
    }
  }
}

最佳实践

1. 明确具体地编写指令
// BAD - ambiguous
await stagehand.act({ action: "click button" });

// GOOD - specific
await stagehand.act({ action: "click the blue 'Add to Cart' button below the product image" });
2. 使用上下文
// Provide context for better accuracy
await stagehand.act({
  action: "in the navigation menu, click on 'Settings'"
});

await stagehand.act({
  action: "in the user dropdown in the top right, click 'Logout'"
});
3. 与 Playwright 结合以提高速度
// Fast: Use Playwright for data-testid elements
await stagehand.page.click('[data-testid="submit"]');

// Resilient: Use Stagehand for dynamic elements
await stagehand.act({ action: "dismiss the cookie banner" });
4. 架构验证
// Always use Zod schemas for type safety
const schema = z.object({
  title: z.string().min(1),
  price: z.number().positive(),
  inStock: z.boolean(),
});

const data = await stagehand.extract({
  instruction: "get product details",
  schema,
});
// data is fully typed!

使用场景

  1. 自修复 E2E 测试:在 UI 重新设计后仍能通过的测试
  2. 网页抓取:从任何网站提取数据
  3. 表单自动化:自动填写复杂表单
  4. 测试 AI 聊天机器人:与对话式 UI 交互
  5. 跨站点工作流:自动化多站点流程

参考资料

  • references/stagehand-v3-guide.md - 完整的 API 参考
  • references/claude-integration.md - API 设置和模型选择
  • references/self-healing-patterns.md - 高级模式

Stagehand v3 将 AI 驱动的自修复能力引入浏览器自动化——让测试能够自适应,而不是失败。

评论

支持 Markdown