news 2026/9/12 6:52:53

Stagehand x CrewAI 集成实战:基于 MCP/stdio 的 Facade 桥接方案

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Stagehand x CrewAI 集成实战:基于 MCP/stdio 的 Facade 桥接方案

Stagehand x CrewAI 集成实战:基于 MCP/stdio 的 Facade 桥接方案

【免费下载链接】stagehandThe SDK For Browser Agents项目地址: https://gitcode.com/GitHub_Trending/stag/stagehand

导读

本文讲解如何在 Python CrewAI 框架中接入 Stagehand 浏览器 Agent 能力:通过一个保留截图信息的crewai-toolsMCP 适配器子类,将 Stagehand Facade MCP 服务器(基于 stdio 协议)暴露的runsnapshotscreenshot三个工具挂载给 CrewAI Agent。读完本文,你将掌握该集成的完整环境搭建、环境变量配置、运行方式、截图保留机制,以及其背后的安全模型与源码级实现原理。

该集成位于仓库的 packages/integrations/crewai 目录,是 Stagehand 多框架集成矩阵(Claude Code、Codex、Eve、Mastra、Vercel AI SDK 等)中的 Python 一员,详见 packages/integrations/README.md。

一、整体架构:CrewAI 如何驱动 Stagehand Facade

CrewAI 本身是纯文本的工具调用循环,不具备直接操作浏览器的能力。本示例的桥接思路是:

  • Facade MCP 服务器:由@browserbasehq/stagehand-integrations包的stagehand-facadestdio 服务器扮演(入口为 stdio-server.ts),它维护一个持久化浏览器,对外只暴露三个工具:runsnapshotscreenshot
  • CrewAI 侧agent.py通过mcpadaptMCPAdapt以 stdio 方式拉起 Node 子进程,再把 MCP 工具转换为 CrewAI 的BaseTool
  • 关键适配点crewai-toolsCrewAIToolAdapter在转换时会丢弃 MCP 的ImageContent块(文本化转换),因此示例实现了一个ImageSavingToolAdapter子类,在转换前把截图写入临时文件并用文本块替换,从而保住截图能力。

从源码结构看,这套“三个工具 + 一个持久化浏览器”的契约被定义在 core/src/facade/contract.ts 中一次,供所有宿主框架复用,不在各示例中重复维护。

二、环境准备与依赖安装

2.1 前置要求

  • Node.js 24+(facade 服务器是 Node 子进程;core 的 package.json 声明node >=22.18.0,但本示例明确要求 24+);
  • uv:Python 依赖管理工具,项目通过uv sync安装;
  • Python>=3.11,<3.14(见 pyproject.toml)。

2.2 安装步骤

先在仓库根目录安装依赖并构建 integrations 包,使 facade 服务器入口文件(dist/facade/stdio-server.mjs)存在:

pnpm install pnpm exec turbo run build --filter @browserbasehq/stagehand-integrations

然后安装 Python 依赖:

cd packages/integrations/crewai uv sync

依赖声明于 pyproject.toml:

  • crewai>=1.15,<2
  • crewai-tools[mcp]>=1.15,<2
  • dev 组:pytest>=9,<10ruff>=0.15,<1

注意:resolve_server_path()(见 agent.py)硬编码查找core/dist/facade/stdio-server.mjs,若找不到会抛出明确报错并提示先执行上面的 turbo build 命令,因此构建顺序不可省略。

三、环境变量配置:一张表看懂全部变量

变量用途
STAGEHAND_BROWSER浏览器后端。设置了BROWSERBASE_API_KEY时默认为browserbase,否则为local
BROWSERBASE_API_KEYBrowserbase API Key,云端浏览器隔离边界的关键凭据。
STAGEHAND_MODEL_NAME/STAGEHAND_MODEL_API_KEYFacade 服务器使用的模型及其 API Key。
CREWAI_MODELCrewAI Agent 模型,默认为openai/gpt-5.6-luna
OPENAI_API_KEY供宿主进程中 CrewAI Agent 模型使用;不会被转发给 facade 子进程(子进程环境变量是显式的STAGEHAND_*/BROWSERBASE_*白名单)。

关于最后一行,源码中的实现非常清晰:facade_env()只透传以STAGEHAND_BROWSERBASE_开头的环境变量(见 agent.py),并将注释明确说明“模型提供方凭据(例如OPENAI_API_KEY)被刻意不转发”。

3.1 底层配置解析逻辑

Facade 服务器侧的环境变量解析位于 core/src/facade/config.ts,值得展开:

  • STAGEHAND_BROWSER只接受localbrowserbase两个值,其它值直接抛StagehandFacadeConfigError
  • 未显式设置时,存在BROWSERBASE_API_KEY就选browserbase,否则选localrequestedBrowser ?? (browserbaseApiKey ? "browserbase" : "local"));
  • browserbase却缺 Key 会报错;STAGEHAND_MODEL_API_KEY设置了但没给STAGEHAND_MODEL_NAME也会报错;
  • 未显式指定模型时,若检测到 Google 系 Key(GOOGLE_GENERATIVE_AI_API_KEY/GEMINI_API_KEY/GOOGLE_API_KEY),默认模型为google/gemini-3.6-flash
  • 模型名采用provider/name格式,自动从环境推断对应 provider 的 Key(openai / anthropic / groq / cerebras 等);
  • local模式默认headless: false(有头浏览器),browserbase模式透传projectId

四、运行方式

packages/integrations/crewai/目录执行:

uv run pytest uv run python agent.py "your instruction"
  • uv run pytest:运行 test_contract.py 中的契约测试;
  • uv run python agent.py "your instruction":把命令行参数拼接为任务描述交给 CrewAI。不给指令时,脚本会打印用法并退出(退出码 2),见 agent.py。

运行后 Crew 会执行kickoff(),Agent 通过三个工具完成浏览器任务,最终输出一份“任务完成情况及结果”的简要报告(expected_output定义见 agent.py)。

4.1 契约测试:三个工具名与提示词被钉死

test_contract.py的三个测试分别验证:

  1. test_facade_tool_contract:会话暴露的工具名排序后必须恰好为["run", "screenshot", "snapshot"],且run工具描述中必须出现never "kind"
  2. test_image_saving_tool_adapter_preserves_screenshot:构造一个含TextContent+ImageContent的假CallToolResult,验证适配器把 PNG 字节写入stagehand-screenshot-*.png临时文件、返回文本路径、且原始 base64 不再出现在结果中;
  3. test_instructions_match_canonical_constant:当仓库内存在core/src/facade/contract.ts时,校验agent.py中手抄的FACADE_AGENT_INSTRUCTIONS与 TypeScript 端规范常量逐字一致(归一化空行后比较),防止两侧提示词漂移。

也就是说,Agent 的系统提示词并非每个示例各写一份,而是以 contract.ts 中的FACADE_AGENT_INSTRUCTIONS为唯一真源。

五、三个 Facade 工具:契约与用法

5.1 工具清单(来自 contract.ts 的FACADE_TOOLS

工具输入 Schema 要点说明
runcode(字符串)或actions(数组),二者恰好提供一个导航 + 自动化都在这里:传 JavaScript 走code,传快照动作批量走actions。动作必须用"op"(绝不用"kind")和"id"(绝不用"ref"),ID 需从最新快照复制为字符串。
snapshotincludeIframes(布尔,默认true抓取活动页面的可访问性树并注入带括号的元素 ID;每次调用都会替换活动页面的 ID 映射。
screenshotfullPage(布尔)、typepng/jpeg)、quality(0–100)截取活动页面。对尺寸受限的 MCP 客户端,推荐{"type":"jpeg","quality":40,"fullPage":false}

run支持的快照动作类型(由RefActionSchema定义,见 contract.ts):

  • clickhover:只需op+id
  • fill:额外value(字符串);
  • type:额外text,可选delay(非负数字);
  • press:额外key(字符串);
  • select:额外values(字符串或字符串数组,至少一项)。

运行时,CodeModeRunInputSchema通过.refine强制codeactions二选一(见 contract.ts)。值得一提的实现细节:线缆层刻意不设顶层oneOf互斥,因为基于 AI SDK 的 MCP 客户端(如 Eve、Vercel AI SDK)会拒绝带顶层oneOf的输入 Schema,导致run在客户端就被拒绝——互斥改为描述文本声明 + 运行时校验(该偏差在 contract.ts 的注释中有明确记录)。

5.2 提示词:Agent 被明确要求“只用一个持久化浏览器”

FACADE_AGENT_INSTRUCTIONS原文(contract.ts)规定:

  • 恰好三个工具:snapshot检查页面并注入元素 ID、run执行快照动作或 Playwright 风格pageAPI 的 JavaScript、screenshot视觉检查;
  • 简单交互用 snapshot 动作,多步工作流用run code
  • 每个动作只用"op""id",ID 仅对活动页面最新一次快照有效,导航或 ID 过期后必须重新 snapshot;
  • 不要启动另一个浏览器

5.3 服务端执行链路(tools.ts)

core/src/facade/tools.ts 中的StagehandFacadeTools是三个工具的服务端实现,几个关键点:

  • 快照水合snapshot()保存pageId → { url, xpathById }映射;runActions()执行前校验:未先快照则报NO_HYDRATED_SNAPSHOT_ERROR,页面 URL 与快照时不一致则报NAVIGATED_SNAPSHOT_ERROR并删除缓存,ID 查不到对应 XPath 则报staleSnapshotIdError(id)——这些错误常量同样定义在 contract.ts;
  • 动作执行:通过experimentalBatch在浏览器上下文内运行一段预置的ACTION_RUNNER_SOURCE,用locator依次执行 click/hover/fill/type/press/select,返回{ completed }
  • 代码执行run(code)把用户代码包进FACADE_PRELUDE/FACADE_EPILOGUE后注入浏览器上下文,提供pagecontextbrowser等 Playwright 兼容运行时(createPlaywrightCompatRuntime,见 runtime.ts),用户代码抛错会以 envelope 形式回传并重新抛出;
  • 串行队列:所有操作经enqueue排队,避免并发操作同一个浏览器;截图支持 JPEG quality 取整以及“Base64 预算内压缩”(screenshot-transport.ts)。

六、截图保留机制:为什么需要 ImageSavingToolAdapter

当前版本的 CrewAI 工具循环是纯文本的,且crewai-tools的 MCP 适配器会丢弃 MCP 图片块。为让 Agent 仍能“看到”页面,ImageSavingToolAdapter(agent.py)的做法是:

  1. 包裹原工具 callable;
  2. 遍历CallToolResult.content:非图片块原样保留;ImageContent块则按 MIME 类型(image/jpeg.jpegimage/png.png)解码写入tempfile.mkstemp生成的临时文件(前缀stagehand-screenshot-);
  3. 用一条文本块Screenshot saved to <path>.替换图片块,再交给父类做文本化转换。

因此每次截图后,Agent 拿到的是一个本地文件路径,打开该文件即可查看截图。

七、安全模型:模型代码跑在哪里

run(code)执行的是模型撰写的 JavaScript,其运行位置是本示例最需要理解的安全边界:

  • 代码通过experimentalBatch扩展的 service worker 中浏览器侧执行绝不在宿主进程中运行
  • Python 宿主进程只负责拉起 facade 服务器(Node 子进程)并持有 MCP 连接,模型撰写的 JavaScript 不会进入宿主进程;
  • Browserbase 是推荐的隔离边界:把浏览器放到 Browserbase 云端(配置BROWSERBASE_API_KEY),模型代码即使有越界行为也被限制在浏览器沙箱与云端会话内;
  • 子进程环境变量白名单(STAGEHAND_*/BROWSERBASE_*)进一步确保宿主侧的模型凭据(如OPENAI_API_KEY)不会被模型代码读到。

服务器侧还有一层防护:sanitizeErrorMessage(stdio-server.ts)在错误回传时对 API Key、Bearer Token、bb_前缀 Browserbase Key、Google AIza Key 等做脱敏,避免凭据泄露到 Agent 上下文。

八、常见排查方向

  • 报错“Stagehand facade server not found”:说明core/dist/facade/stdio-server.mjs尚未构建,回到仓库根目录执行pnpm exec turbo run build --filter @browserbasehq/stagehand-integrations
  • 报错“node was not found”:宿主进程通过shutil.which("node")定位 Node(agent.py),需确保 Node 24+ 在PATH中;
  • STAGEHAND_BROWSER 取值错误 / browserbase 缺 Key:查看stagehandFacadeConfigFromEnv的校验分支(config.ts),按 3.1 节约束配置;
  • Agent 抱怨 ID 失效:快照 ID 只对活动页面的最新快照有效,导航后必须先重新snapshot

结语

本示例的价值在于把“浏览器自动化”能力以最小的契约面(三个工具、一个持久化浏览器、纯文本 MCP 传输)接入 CrewAI,同时通过截图适配器弥补crewai-tools的文本化限制。理解其契约定义(contract.ts)、配置解析(config.ts)、服务端工具实现(tools.ts)与安全边界(service worker + 环境白名单)后,你既可以直接照搬运行,也可以把同样的模式迁移到其它 MCP 客户端框架中。

【免费下载链接】stagehandThe SDK For Browser Agents项目地址: https://gitcode.com/GitHub_Trending/stag/stagehand

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/12 6:52:36

2026年WordPress多语言插件选型与优化指南

1. 为什么WordPress多语言插件如此重要&#xff1f;在2026年的今天&#xff0c;网站多语言支持已不再是锦上添花的功能&#xff0c;而是全球化数字营销的基本配置。根据最新的网站分析数据&#xff0c;提供母语访问体验的网站转化率平均提升47%&#xff0c;跳出率降低32%。对于…

作者头像 李华
网站建设 2026/9/12 6:47:45

Android安全加固工具dpt-shell核心技术解析与应用实践

1. Android安全加固工具dpt-shell深度解析 在移动应用安全领域&#xff0c;Android平台因其开放性面临着严峻的安全挑战。dpt-shell作为一款专业级安全加固工具&#xff0c;通过独特的动态防护技术为APK文件提供运行时保护。不同于传统的静态加固方案&#xff0c;它采用动态代码…

作者头像 李华
网站建设 2026/9/12 6:46:34

从awesome-gpt-image-2资源清单到落地工作流:图像生成实战

01 从"awesome"仓库聊起&#xff1a;我为什么盯上了gpt-image-2这个热词如果你常逛GitHub&#xff0c;看到"awesome-"开头的仓库应该不陌生——这类项目的定位就是"把某个方向最好的东西全部整理到一张清单里"。而"awesome-gpt-image-2&quo…

作者头像 李华
网站建设 2026/9/12 6:46:29

Karpathy力推的Skills是什么?从原理到实战打造可复用Agent技能包

这段时间 AI 圈最热闹的一个词&#xff0c;除了 agent&#xff0c;就是skills。我关注这个方向&#xff0c;很大程度上是因为 Andrej Karpathy 在多个场合反复提过一个观点&#xff1a;未来大模型的使用方式&#xff0c;不会停留在"你问我答"&#xff0c;而是会演化成…

作者头像 李华