Skip to main content
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:
  1. Observes the current page state using visual context
  2. Plans the next action based on your instruction and page content
  3. Executes browser actions (click, type, navigate, etc.)
  4. Repeats until the task completes or reaches the maxCycles limit
  5. 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

Multi-Step Forms

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 }
);

Agent Performs Unexpected Actions

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

I