Overview
The quality of your prompts directly impacts Stagehand’s reliability and performance. This guide covers proven patterns for writing effective instructions.General Principles
Be Specific and Clear
// ❌ Vague
await stagehand.act("do something");
// ✅ Specific
await stagehand.act("click the blue 'Add to Cart' button");
Use Imperative Language
// ❌ Passive/Unclear
await stagehand.act("the login button should be clicked");
// ✅ Direct command
await stagehand.act("click the login button");
Include Visual Descriptors
// ❌ Ambiguous
await stagehand.act("click the button");
// ✅ Descriptive
await stagehand.act("click the red 'Submit' button at the bottom of the form");
Act() Prompts
Clicking Elements
// Good examples
await stagehand.act("click the 'Sign In' button");
await stagehand.act("click the menu icon in the top right");
await stagehand.act("click the third product card");
await stagehand.act("click the checkbox next to 'I agree to terms'");
Filling Forms
// ❌ Missing context
await stagehand.act("type '[email protected]'");
// ✅ Specifies target
await stagehand.act("type '[email protected]' in the email field");
await stagehand.act("type 'password123' in the password input");
await stagehand.act("type 'John Doe' in the full name field");
Selecting from Dropdowns
await stagehand.act("select 'United States' from the country dropdown");
await stagehand.act("select 'Medium' from the size selector");
await stagehand.act("choose 'Blue' from the color options");
Navigation
await stagehand.act("scroll down to the footer");
await stagehand.act("scroll to the reviews section");
await stagehand.act("hover over the 'Products' menu item");
Extract() Prompts
Specify What to Extract
// ❌ Too broad
const result = await stagehand.extract("get data");
// ✅ Specific fields
const result = await stagehand.extract(
"get the product title, price, and availability status"
);
Use Structured Schemas
import { z } from "zod";
const productSchema = z.object({
title: z.string().describe("The product name"),
price: z.number().describe("Price in USD"),
inStock: z.boolean().describe("Whether the product is available"),
rating: z.number().optional().describe("Star rating out of 5"),
});
const result = await stagehand.extract(
"extract the product details",
{ schema: productSchema }
);
// result.extraction is fully typed
console.log(result.extraction.title);
console.log(result.extraction.price);
List Extractions
const searchResultsSchema = z.object({
results: z.array(z.object({
title: z.string(),
url: z.string(),
description: z.string(),
})),
});
const results = await stagehand.extract(
"extract all search results including title, URL, and description",
{ schema: searchResultsSchema }
);
Observe() Prompts
Observe returns a list of actions to perform:// Get multiple related actions
const actions = await stagehand.observe(
"return actions to fill the login form with username '[email protected]' and password 'test123'"
);
for (const action of actions) {
await stagehand.act(action);
}
Good Observe Patterns
// Form filling
const formActions = await stagehand.observe(
"return actions to complete the signup form with name 'John', email '[email protected]', and phone '555-1234'"
);
// Multi-step workflows
const checkoutActions = await stagehand.observe(
"return actions to proceed through checkout: select shipping, enter payment details, and confirm order"
);
Agent Instructions
Clear Goals
const agent = stagehand.agent();
// ❌ Too vague
await agent.execute({
instruction: "do some stuff on Amazon",
maxSteps: 10,
});
// ✅ Clear objective
await agent.execute({
instruction: "search for 'wireless mouse' on Amazon and add the first result to cart",
maxSteps: 10,
});
Break Down Complex Tasks
// ❌ Too complex for one agent call
await agent.execute({
instruction: "research competitors, analyze pricing, create spreadsheet, and send email",
maxSteps: 50,
});
// ✅ Break into smaller tasks
await agent.execute({
instruction: "navigate to competitor website and extract product prices",
maxSteps: 15,
});
// Then handle analysis and email separately
Include Stop Conditions
await agent.execute({
instruction: "search for 'laptop' and add first result to cart, then stop",
maxSteps: 10,
});
await agent.execute({
instruction: "scroll through products until you find one under $50, then click it",
maxSteps: 20,
});
Using System Prompts
Stagehand-Level System Prompts
const stagehand = new Stagehand({
env: "LOCAL",
systemPrompt: `You are automating an e-commerce website.
- Always verify prices before adding to cart
- If an item is out of stock, skip it
- Prefer items with 4+ star ratings`,
});
Agent-Level System Prompts
const agent = stagehand.agent({
systemPrompt: `You are a research assistant.
- Extract data accurately
- When information is missing, note it as 'N/A'
- Today's date is ${new Date().toLocaleDateString()}`,
});
await agent.execute({
instruction: "gather company information from the about page",
maxSteps: 5,
});
Common Mistakes to Avoid
Overly Complex Instructions
// ❌ Too many steps in one instruction
await stagehand.act(
"click the menu, then click products, then select laptops category, then filter by price under $1000, then sort by rating"
);
// ✅ Break into individual actions
await stagehand.act("click the menu button");
await stagehand.act("click the 'Products' link");
await stagehand.act("select 'Laptops' from the category filter");
await stagehand.act("select 'Under $1000' from the price filter");
await stagehand.act("sort by rating");
Ambiguous References
// ❌ Which button?
await stagehand.act("click the button");
// ✅ Specific reference
await stagehand.act("click the 'Add to Cart' button");
Missing Context
// ❌ What form?
await stagehand.act("submit the form");
// ✅ Identifies the form
await stagehand.act("submit the login form");
await stagehand.act("click the submit button in the contact form");
Using Variables
Dynamically insert values into prompts:const userEmail = "[email protected]";
const password = "secure123";
await stagehand.act(
"type '{{email}}' in the email field",
{ variables: { email: userEmail } }
);
await stagehand.act(
"type '{{password}}' in the password field",
{ variables: { password } }
);
Variables with Agent
const searchTerm = "wireless keyboard";
const maxPrice = 50;
const agent = stagehand.agent();
await agent.execute({
instruction: "search for '{{product}}' and find options under ${{price}}",
maxSteps: 15,
variables: {
product: searchTerm,
price: maxPrice.toString(),
},
});
Testing Your Prompts
Iterate and Refine
// Start simple
await stagehand.act("click login");
// If it fails, add more detail
await stagehand.act("click the login button");
// If still failing, be very specific
await stagehand.act("click the blue 'Log In' button in the top right corner");
Use Verbose Mode During Development
const stagehand = new Stagehand({
env: "LOCAL",
verbose: 2, // See detailed logs
});
await stagehand.act("click submit");
// Logs will show what Stagehand "sees" and how it interprets your instruction
Prompt Engineering for Reliability
Handle Dynamic Content
// ❌ Brittle: relies on exact text
await stagehand.act("click the button that says 'Add to Cart'");
// ✅ Flexible: works with variations
await stagehand.act("click the button to add the item to the cart");
Account for Loading States
// Wait for content before acting
const page = stagehand.context.pages()[0];
await page.waitForLoadState("domcontentloaded");
await stagehand.act("click the first product");
Use Conditional Logic
try {
await stagehand.act("click the cookie consent banner's accept button", {
timeout: 5000,
});
} catch (error) {
// No banner appeared, continue
}
await stagehand.act("search for products");
Example: Complete Workflow
import { Stagehand } from "@browserbasehq/stagehand";
import { z } from "zod";
const stagehand = new Stagehand({
env: "LOCAL",
cacheDir: "./cache",
});
await stagehand.init();
const page = stagehand.context.pages()[0];
await page.goto("https://example-store.com");
// Clear, specific instructions
await stagehand.act("type 'laptop' in the search bar");
await stagehand.act("click the search button");
// Structured extraction
const productSchema = z.object({
products: z.array(z.object({
name: z.string(),
price: z.number(),
rating: z.number(),
})),
});
const results = await stagehand.extract(
"extract the name, price, and rating for all products shown",
{ schema: productSchema }
);
// Act on extracted data
if (results.extraction.products.length > 0) {
await stagehand.act("click the first product in the search results");
}
await stagehand.close();