Implementation:Microsoft Playwright ActionRunner RunAction
| Knowledge Sources | |
|---|---|
| Domains | AI_Testing, Browser_Automation, Test_Execution |
| Last Updated | 2026-02-11 00:00 GMT |
Overview
Concrete internal mechanism for dispatching AI agent-generated browser actions to Playwright API calls and managing the agentic loop lifecycle, provided by the Playwright library.
Description
The runAction function is the core action dispatcher within Playwright's agent system. It receives a structured action object from the LLM's tool call and executes the corresponding Playwright API operation against the browser page. This function handles 14 distinct action types, covering navigation, interaction, form filling, and assertion operations.
The dispatcher operates in two modes:
- generate mode: The LLM generates actions in real-time, and each action is executed immediately.
- run mode: Actions are replayed from a cache, with no LLM involvement.
The broader agentic loop is managed by the Context class (context.ts:L35-168), which maintains page references, agent parameters, conversation history, and token budgets. The loop orchestration in pageAgent.ts (L90-162) coordinates the observe-decide-act cycle, invokes the LLM via the @lowire/loop library, and handles caching, retry logic, and result collection.
The --run-agents CLI flag controls execution modes at the test runner level: none (cache only, default), missing (LLM for uncached), all (always LLM).
Usage
This is an internal implementation detail, not a public API. Understanding it is useful when:
- Debugging agent test failures by examining which actions were dispatched
- Extending the agent with custom action types
- Understanding the performance characteristics of the agentic loop
- Analyzing agent-usage artifacts to optimize test efficiency
- Configuring the
--run-agentsCLI flag for different CI/CD pipeline stages
Code Reference
Source Location
- Repository: playwright
- File:
packages/playwright-core/src/server/agent/actionRunner.ts:L38-57(action dispatcher) - File:
packages/playwright-core/src/server/agent/pageAgent.ts:L90-162(agentic loop orchestration) - File:
packages/playwright-core/src/server/agent/context.ts:L35-168(Context class)
Signature
// Action dispatcher
async function runAction(
progress: Progress,
mode: 'generate' | 'run',
page: Page,
action: actions.Action,
secrets: NameValue[]
): Promise<void>
// Context class (manages agentic loop state)
class Context {
page: Page;
agentParams: AgentParams;
history: Message[];
tokenBudget: { used: number; limit: number };
constructor(page: Page, agentParams: AgentParams);
addToHistory(message: Message): void;
consumeTokens(input: number, output: number): void;
isBudgetExhausted(): boolean;
}
Import
// Internal module - not directly imported by test authors
// Used internally by PageAgentDispatcher
// The --run-agents CLI flag is the primary user interface:
// npx playwright test --run-agents=missing
// npx playwright test --run-agents=all
// npx playwright test --run-agents=none
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| progress | Progress |
Yes | Playwright progress tracking object for timeout and cancellation management |
| mode | 'run' | Yes | Whether actions are being generated live by the LLM or replayed from cache |
| page | Page |
Yes | The Playwright Page instance to execute actions against |
| action | actions.Action |
Yes | A structured action object specifying the type and parameters of the browser action |
| secrets | NameValue[] |
Yes | Array of name-value pairs for sensitive data (e.g., passwords) to be substituted into action parameters |
Outputs
| Name | Type | Description |
|---|---|---|
| (resolved) | Promise<void> |
Resolves when the action has been successfully executed against the page |
| (rejected) | Error |
Throws on action failure (element not found, timeout, navigation error, etc.) |
Supported Action Types
The runAction dispatcher handles 14 action types:
| Action Type | Playwright API | Description |
|---|---|---|
| navigate | page.goto(url) |
Navigate to a URL |
| click | locator.click() |
Click an element by reference |
| drag | locator.drag(target) |
Drag an element to a target position |
| hover | locator.hover() |
Hover over an element |
| fill | locator.fill(value) |
Fill a form field with text |
| select_option | locator.selectOption(value) |
Select a dropdown option |
| press_key | keyboard.press(key) |
Press a keyboard key or combination |
| type | keyboard.type(text) |
Type text character by character |
| set_checked | locator.setChecked(checked) |
Set checkbox/radio checked state |
| snapshot | accessibility tree capture | Capture page state as accessibility tree |
| expect_visible | assertion check | Assert element visibility |
| expect_visible_text | assertion check | Assert text visibility |
| expect_value | assertion check | Assert input field value |
| expect_url | assertion check | Assert current URL |
Usage Examples
Basic Example
// This is internal API - shown for understanding, not direct usage.
// Test authors interact through agent.perform(), agent.expect(), agent.extract()
import { test } from '@playwright/test';
// Standard usage via the agent fixture
test('example using the agent', async ({ agent }) => {
// Internally, perform() triggers the agentic loop which calls runAction
// for each LLM-generated action
await agent.perform('Fill in the contact form and submit it');
// Internally, expect() uses assertion action types via runAction
await agent.expect('A success message is displayed');
});
CLI Usage for Execution Modes
# Default: cache-only mode (no LLM calls, fastest, zero cost)
npx playwright test
# Equivalent to default
npx playwright test --run-agents=none
# Use LLM only for tasks not found in cache
npx playwright test --run-agents=missing
# Always use LLM, regenerate all caches
npx playwright test --run-agents=all
Understanding Agent Usage Artifacts
{
"testFile": "tests/checkout.spec.ts",
"testTitle": "user can complete checkout",
"agentUsage": {
"perform": [
{
"task": "Navigate to the store and add a laptop to the cart",
"turns": 5,
"inputTokens": 12340,
"outputTokens": 890,
"actions": ["navigate", "snapshot", "click", "snapshot", "click"]
},
{
"task": "Proceed to checkout and fill in payment details",
"turns": 8,
"inputTokens": 23450,
"outputTokens": 1560,
"actions": ["snapshot", "click", "fill", "fill", "fill", "snapshot", "click", "snapshot"]
}
],
"expect": [
{
"expectation": "The order confirmation page shows a success message",
"turns": 2,
"inputTokens": 5670,
"outputTokens": 230
}
],
"totalTokens": {
"input": 41460,
"output": 2680
}
}
}
Cache File Structure
{
"version": 1,
"entries": [
{
"key": "Navigate to the store and add a laptop to the cart",
"responses": [
{
"role": "assistant",
"content": null,
"tool_calls": [
{
"function": {
"name": "browser_navigate",
"arguments": "{\"url\": \"https://store.example.com\"}"
}
}
]
}
],
"metadata": {
"model": "gpt-4o",
"timestamp": 1739232000000
}
}
]
}