Upcoming Feature: AI Agent Execute is currently in development and will be available in an upcoming release. This documentation reflects the planned API and capabilities.
AI Agent Execute enables autonomous browser automation within your Playwright tests. Unlike atomic actions (click
, fill
, select
), context.agent()
handles complex, multi-step workflows across pages—allowing you to describe a high-level task and let the agent execute it end-to-end.
Why use agents? Agents excel at workflows where the exact path varies: searching, filtering, multi-page forms, checkout flows, and application processes. They complement Playwright’s deterministic approach by providing flexibility when UI paths diverge or evolve.
Installation
The agent API will be available through the Stably Playwright test integration:
import { test, expect } from '@stablyai/playwright-test';
Basic Usage
Create an agent from your test context and execute high-level instructions:
import { test, expect } from '@stablyai/playwright-test';
test('apply for a remote position', async ({ context, page }) => {
// Navigate to the starting page
await page.goto('https://company.com/careers');
// Execute a multi-step task that might span multiple tabs
await context.agent(
'Find remote senior software engineer roles, filter by full-time, and submit an application',
{ page, maxCycles: 25 }
);
console.log('Application submitted successfully');
});
How It Works
context.agent()
invokes an autonomous agent that:
- Observes the current page state using visual context
- Plans the next action based on your instruction and page content
- Executes browser actions (click, type, navigate, etc.)
- Repeats until the task completes or reaches the
maxCycles
limit
- Works across pages: The agent can navigate between different pages and domains to complete the task
The agent uses computer-use-capable models to understand web interfaces visually and semantically, similar to how humans browse.
Method Signature
await context.agent(
prompt: string,
options: {
page: Page;
maxCycles?: number;
}
): Promise<void>
Parameters
prompt
(string, required) - The high-level task to accomplish
options
(object, required) - Agent configuration
Options:
page
(Page, required) - The starting page for the agent. The agent may create additional pages as needed
maxCycles
(number, optional) - Maximum number of actions the agent can take. Default: 20
Common Use Cases
Agents handle complex, multi-page forms without explicit step-by-step instructions:
await context.agent(
'Complete the onboarding form: name is "Alex Chen", company is "Acme Corp", team size 50-100',
{ page, maxCycles: 15 }
);
Search and Filter Workflows
Let the agent navigate dynamic search results and apply filters:
await context.agent(
'Find studio headphones under $500, sort by highest rating, and add the top result to cart',
{ page, maxCycles: 20 }
);
Cross-Page Navigation
Agents can traverse multiple pages to complete tasks:
await page.goto('https://docs.example.com');
await context.agent(
'Navigate to the API reference section and find the authentication endpoint documentation',
{ page, maxCycles: 10 }
);
Conditional Workflows
Handle branching paths without explicit conditionals:
await context.agent(
'Subscribe to the newsletter if there is a popup, otherwise proceed to checkout',
{ page, maxCycles: 12 }
);
Set Up / Tear Down
Use agents to automate test setup and cleanup workflows:
import { test, expect } from '@stablyai/playwright-test';
test.describe('E-commerce checkout flow', () => {
test.beforeEach(async ({ context, page }) => {
// Navigate to the starting page
await page.goto('https://shop.example.com');
// Set up test data: add products to cart
await context.agent(
'Search for "wireless mouse", add the first result to cart, then search for "USB cable" and add it to cart',
{ page, maxCycles: 20 }
);
});
test.afterEach(async ({ context, page }) => {
// Clean up: clear cart and sign out
await context.agent(
'Navigate to cart, remove all items, then sign out',
{ page, maxCycles: 15 }
);
});
test('apply discount code', async ({ context, page }) => {
// Test assumes cart is already populated from beforeEach
await context.agent(
'Go to checkout, enter discount code "SAVE20", and verify discount is applied',
{ page, maxCycles: 10 }
);
await expect(page.locator('.discount-applied')).toBeVisible();
});
test('update shipping address', async ({ context, page }) => {
await context.agent(
'Go to checkout, change shipping address to 123 Main St, New York, NY 10001',
{ page, maxCycles: 15 }
);
await expect(page.locator('.shipping-address')).toContainText('123 Main St');
});
});
This approach is especially useful when:
- Manual setup involves multiple steps across different pages
- Setup data varies between test runs (dynamic content, user accounts)
- You want to reduce test code duplication
Configuration
Control agent behavior using maxCycles
:
// Set maxCycles to prevent runaway execution
await context.agent(
'Search for JavaScript frameworks and bookmark the top 3',
{ page, maxCycles: 15 } // Agent stops after 15 actions if task isn't complete
);
For complex tasks requiring many steps, increase maxCycles
:
await context.agent(
'Find and compare pricing plans across 3 SaaS products, then fill out a trial signup for the cheapest',
{ page, maxCycles: 40 } // Higher limit for complex workflows
);
Provide detailed instructions in the prompt itself:
await context.agent(
`Complete the medical insurance form with provided information.
Use conservative estimates when exact values are unavailable.
Skip optional fields unless explicitly mentioned.`,
{ page }
);
Multi-Page Capabilities
Unlike single-page actions, agents can navigate across pages and domains to complete tasks:
test('research and compare products across vendors', async ({ context, page }) => {
await page.goto('https://search.example.com');
await context.agent(
`Search for "wireless keyboards",
visit the product pages of the top 3 results,
and note the prices and ratings for each`,
{ page, maxCycles: 30 }
);
});
The agent tracks context across page navigations and maintains task progress throughout the journey.
Best Practices
Start on the Right Page
Navigate to a relevant starting point before executing tasks:
// ✅ Good: Start on the relevant page
await page.goto('https://github.com/browserbase/stagehand');
await context.agent(
'Get the latest merged PR on this repo',
{ page, maxCycles: 10 }
);
// ❌ Avoid: Starting from an unrelated page
await page.goto('https://github.com');
await context.agent(
'Get the latest PR on browserbase/stagehand',
{ page, maxCycles: 10 }
); // Agent wastes steps navigating
Be Specific with Instructions
Provide detailed, unambiguous instructions for better results:
// ✅ Specific instruction
await context.agent(
'Find Italian restaurants in Brooklyn open after 10pm with outdoor seating, sorted by rating',
{ page, maxCycles: 20 }
);
// ❌ Vague instruction
await context.agent(
'Find restaurants',
{ page, maxCycles: 20 }
); // Too ambiguous
Break Down Very Complex Tasks
For extremely complex workflows, break into sequential agent executions:
// First task: search and filter
await context.agent(
'Search for MacBook Pro and filter by 16-inch models under $2500',
{ page, maxCycles: 15 }
);
// Second task: checkout
await context.agent(
'Add the top result to cart and proceed to checkout',
{ page, maxCycles: 15 }
);
Combine with Assertions
Use Playwright assertions to verify agent outcomes:
await context.agent(
'Subscribe to the Pro plan',
{ page, maxCycles: 20 }
);
// Verify the outcome
await expect(page.locator('.success-message')).toBeVisible();
await expect(page).toHaveURL(/checkout\/success/);
Troubleshooting
Agent Stops Before Completing Task
Problem: Agent stops before finishing the requested task
Solutions:
- Increase
maxCycles
for complex workflows (default is 20)
- Break very complex tasks into smaller sequential executions
- Ensure the starting page is relevant to reduce wasted navigation steps
// Increase maxCycles for complex tasks
await context.agent(
'Complete the 5-page registration form with all required fields',
{ page, maxCycles: 40 } // Increased limit
);
// Or break into smaller tasks
await context.agent(
'Complete pages 1-2 of the registration form',
{ page, maxCycles: 15 }
);
await context.agent(
'Complete pages 3-5 of the registration form',
{ page, maxCycles: 20 }
);
Problem: Agent clicks wrong elements or takes unintended paths
Solutions:
- Make instructions more specific about what to click or avoid
- Provide domain-specific context in the agent’s
instructions
option
- Start from a more focused page to reduce ambiguity
// Provide clearer context in the prompt
await context.agent(
`Apply to the first full-time senior software engineer role listed.
You are searching for professional software engineering jobs.
Ignore internships, contract roles, and non-engineering positions.`,
{ page, maxCycles: 20 }
);
Task Times Out or Takes Too Long
Problem: Agent execution is slower than expected
Solutions:
- Ensure the starting page is close to the target workflow
- Reduce the scope of the task or break it into smaller pieces
- Check network conditions—slow page loads affect agent performance
Task Execution Issues
Problem: Task fails or doesn’t complete as expected
Solutions:
- Check if the UI changed mid-execution (dynamic content, popups)
- Increase
maxCycles
if the agent ran out of actions
- Review the error message for specific failure points
try {
await context.agent(
'Complete checkout',
{ page, maxCycles: 15 }
);
} catch (error) {
console.error('Agent execution failed:', error.message);
// Example: "Could not find payment method selector after 12 cycles"
}
Model Support
Stably’s agent execution uses computer-use-capable vision models optimized for browser automation. Model selection and configuration will be available through stably.config.ts
:
import { defineStablyConfig } from '@stablyai/playwright-test';
// stably.config.ts (upcoming)
export default defineStablyConfig({
use: {
agent: {
model: 'claude-sonnet-4-5', // Model with computer-use capabilities
maxCycles: 20, // Default cycle limit
},
},
});
Model-specific behavior and performance characteristics will be documented upon release.
When to Use Agents
-
Use
context.agent()
when:
- The workflow spans multiple pages or domains
- The exact path varies based on dynamic content
- You want to describe intent rather than prescribe steps
- The UI is exploratory (search, browse, filter, compare)
-
Use standard Playwright actions when:
- The flow is deterministic and well-defined
- Performance is critical (agents are slower than direct actions)
- You need precise control over each step
- The page structure is stable and predictable
Agents complement Playwright’s deterministic approach—use them where flexibility and autonomy provide value.
References