-
Notifications
You must be signed in to change notification settings - Fork 1.1k
azure/bedrock api integration #1048
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 13 commits
76cc39b
28f4b6e
1a415bb
04fb315
8eccd56
c6a752d
2931804
2f3b8b9
be8b7a4
27c722c
69c3d93
467dade
0735ca3
76b44ae
18937ee
0af4acf
c762944
4bd7412
ce07cfa
06ae0e6
9fe40fd
938b51c
607b4c3
adec13c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
import { Stagehand } from "@browserbasehq/stagehand"; | ||
import { z } from "zod/v3"; | ||
|
||
/** | ||
* AWS Bedrock Integration Example for Stagehand | ||
* | ||
* This example demonstrates how to use Stagehand with AWS Bedrock models. | ||
* Anthropic models work best for advanced features like structured extraction | ||
* and observation, while OpenAI models work well for navigation and basic operations. | ||
* | ||
* SETUP: | ||
* | ||
* 1. Enable model access in AWS Bedrock Console: | ||
* - Visit: https://console.aws.amazon.com/bedrock/ | ||
* - Go to "Model access" → "Enable model access" | ||
* - Enable desired models (e.g., Anthropic Claude, OpenAI models) | ||
* - Wait for approval | ||
* | ||
* 2. Authentication (choose one): | ||
* | ||
* Option A - Bearer Token: | ||
* ``` | ||
* AWS_BEARER_TOKEN_BEDROCK=bedrock-api-key-[your-base64-token] | ||
* ``` | ||
* | ||
* Option B - Standard AWS Credentials: | ||
* ``` | ||
* AWS_ACCESS_KEY_ID=your-access-key | ||
* AWS_SECRET_ACCESS_KEY=your-secret-key | ||
* ``` | ||
* | ||
* 3. Set region and model: | ||
* ``` | ||
* AWS_REGION=us-east-1 | ||
* ``` | ||
* | ||
* RECOMMENDED MODELS: | ||
* - anthropic.claude-3-5-sonnet-20240620-v1:0 (best for extraction/observation) | ||
* - anthropic.claude-3-haiku-20240307-v1:0 (faster, good for basic tasks) | ||
* - openai.gpt-oss-120b-1:0 (good for navigation and simple operations) | ||
*/ | ||
|
||
async function runBedrockExample() { | ||
// Initialize Stagehand with AWS Bedrock | ||
const stagehand = new Stagehand({ | ||
env: "BROWSERBASE", | ||
modelName: "bedrock/us.anthropic.claude-sonnet-4-20250514-v1:0", | ||
modelClientOptions: { | ||
region: "us-west-2", // Will use environment variables if not specified | ||
}, | ||
}); | ||
|
||
try { | ||
await stagehand.init(); | ||
const page = stagehand.page; | ||
|
||
console.log("🚀 Stagehand initialized with AWS Bedrock"); | ||
|
||
// Navigate to a website | ||
await page.goto("https://example.com"); | ||
console.log("📄 Navigated to example.com"); | ||
|
||
// Perform actions on the page | ||
await page.act("click the link"); | ||
console.log("🎯 Clicked the 'More information...' link"); | ||
|
||
// Extract structured data | ||
const pageInfo = await page.extract({ | ||
instruction: "Extract the page title and text", | ||
schema: z.object({ | ||
title: z.string(), | ||
text: z.string(), | ||
}), | ||
}); | ||
|
||
console.log("📊 Extracted data:", pageInfo); | ||
|
||
// Observe elements on the page | ||
const elements = await page.observe(); | ||
console.log(`👀 Found ${elements.length} interactive elements`); | ||
|
||
console.log("✅ AWS Bedrock example completed successfully!"); | ||
} catch (error) { | ||
console.error("❌ Error:", error); | ||
|
||
// Common troubleshooting hints | ||
if (error.message?.includes("access")) { | ||
console.error("💡 Check model access in AWS Bedrock Console"); | ||
} else if ( | ||
error.message?.includes("credentials") || | ||
error.message?.includes("authentication") | ||
) { | ||
console.error("💡 Verify your AWS credentials are set correctly"); | ||
} | ||
} finally { | ||
await stagehand.close(); | ||
} | ||
} | ||
|
||
// Run the example | ||
runBedrockExample(); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -747,6 +747,7 @@ ${scriptContent} \ | |
const result = await this.api.act({ | ||
...observeResult, | ||
frameId: this.rootFrameId, | ||
modelClientOptions: this.stagehand["modelClientOptions"], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is this required? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We will need this once we add self-healing |
||
}); | ||
this.stagehand.addToHistory("act", observeResult, result); | ||
return result; | ||
|
@@ -783,6 +784,7 @@ ${scriptContent} \ | |
frameId: this.rootFrameId, | ||
modelClientOptions: | ||
modelClientOptions || this.stagehand["modelClientOptions"], | ||
modelName: modelName || this.stagehand["modelName"], | ||
}; | ||
const result = await this.api.act(opts); | ||
this.stagehand.addToHistory("act", actionOrOptions, result); | ||
|
@@ -844,7 +846,10 @@ ${scriptContent} \ | |
if (!instructionOrOptions) { | ||
let result: ExtractResult<T>; | ||
if (this.api) { | ||
result = await this.api.extract<T>({ frameId: this.rootFrameId }); | ||
result = await this.api.extract<T>({ | ||
frameId: this.rootFrameId, | ||
modelClientOptions: this.stagehand["modelClientOptions"], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is this required? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes because otherwise it doesn't get sent to the API. We need this param on all api calls now |
||
}); | ||
} else { | ||
result = await this.extractHandler.extract(); | ||
} | ||
|
@@ -882,6 +887,7 @@ ${scriptContent} \ | |
frameId: this.rootFrameId, | ||
modelClientOptions: | ||
modelClientOptions || this.stagehand["modelClientOptions"], | ||
modelName: modelName || this.stagehand["modelName"], | ||
}; | ||
const result = await this.api.extract<T>(opts); | ||
this.stagehand.addToHistory("extract", instructionOrOptions, result); | ||
|
@@ -991,6 +997,7 @@ ${scriptContent} \ | |
frameId: this.rootFrameId, | ||
modelClientOptions: | ||
modelClientOptions || this.stagehand["modelClientOptions"], | ||
modelName: modelName || this.stagehand["modelName"], | ||
}; | ||
const result = await this.api.observe(opts); | ||
this.stagehand.addToHistory("observe", instructionOrOptions, result); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -48,7 +48,6 @@ export class StagehandAPI { | |
|
||
async init({ | ||
modelName, | ||
modelApiKey, | ||
domSettleTimeoutMs, | ||
verbose, | ||
debugDom, | ||
|
@@ -59,11 +58,6 @@ export class StagehandAPI { | |
browserbaseSessionCreateParams, | ||
browserbaseSessionID, | ||
}: StartSessionParams): Promise<StartSessionResult> { | ||
if (!modelApiKey) { | ||
throw new StagehandAPIError("modelApiKey is required"); | ||
} | ||
this.modelApiKey = modelApiKey; | ||
|
||
const region = browserbaseSessionCreateParams?.region; | ||
if (region && region !== "us-west-2") { | ||
return { sessionId: browserbaseSessionID ?? null, available: false }; | ||
|
@@ -191,6 +185,12 @@ export class StagehandAPI { | |
const queryString = urlParams.toString(); | ||
const url = `/sessions/${this.sessionId}/${method}${queryString ? `?${queryString}` : ""}`; | ||
|
||
this.logger({ | ||
category: "execute", | ||
message: `Executing ${method} with args: ${JSON.stringify(args)}`, | ||
level: 1, | ||
|
||
}); | ||
|
||
const response = await this.request(url, { | ||
method: "POST", | ||
body: JSON.stringify(args), | ||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -1,5 +1,6 @@ | ||||||
import OpenAI from "openai"; | ||||||
import { CreateChatCompletionResponseError } from "@/types/stagehandErrors"; | ||||||
import type { ClientOptions } from "openai"; | ||||||
|
import type { ClientOptions } from "openai"; | |
clientOptions?: ClientOptions; |
Uh oh!
There was an error while loading. Please reload this page.