Modern web applications are becoming more complex, while development teams are expected to release changes faster. Traditional automated tests are good at validating known scenarios, but they usually follow a fixed sequence of actions. When an application changes, those tests may need manual updates.
Agentic QA introduces another approach. Instead of treating automation as a simple list of browser commands, an agent can use a goal, inspect the application, decide what to do next, execute browser actions, and evaluate the result.
For .NET teams, this approach can be built around browser automation frameworks such as Playwright for .NET, combined with an AI agent layer and the existing testing infrastructure.
This article explains how to design such a pipeline, where it makes sense, and what problems developers should consider before using it in production.
What Is Agentic QA?
Traditional test automation generally looks like this:
Test Case
|
v
Open Browser
|
v
Click Element
|
v
Enter Data
|
v
Submit
|
v
Assert Result
The sequence is predefined.
An agentic QA pipeline adds a decision-making layer:
QA Goal
|
v
AI Agent
|
+----> Inspect Application
|
+----> Select Action
|
+----> Browser Automation
|
+----> Observe Result
|
+----> Evaluate
|
+----> Next Action
|
v
Test Result
For example, instead of explicitly defining every interaction, a QA task could be described as:
Verify that a new user can register, log in,
update their profile, and successfully log out.
The agent can break this goal into smaller actions, interact with the browser, inspect the resulting page, and determine whether the expected outcome was reached.
This does not mean conventional tests should be replaced. Agentic automation works best as an additional layer for exploratory, adaptive, and scenario-driven testing.
Why Combine Browser Automation with .NET?
Many organizations already have their testing infrastructure around .NET. They may use C#, CI/CD pipelines, test frameworks, reporting systems, and existing automation libraries.
Using browser automation from C# allows teams to keep these pieces together.
A simplified architecture can look like this:
QA Scenario
|
v
Agent Orchestrator
|
+----------+----------+
| |
v v
Test Context Agent Memory
|
v
Browser Tool
|
v
Playwright for .NET
|
v
Web Application
|
v
Observations / Results
|
v
Evaluation
The important architectural decision is to keep browser access behind well-defined tools rather than allowing the agent to directly control every part of the test infrastructure.
Core Components of an Agentic QA Pipeline
1. Test Goal
The test begins with a clear objective.
For example:
Verify that a customer can add a product
to the cart and complete checkout.
The goal should be specific enough to evaluate, but not necessarily tied to every individual browser click.
2. Agent Orchestrator
The orchestrator manages the agent loop.
Its responsibilities can include:
Providing the test objective
Maintaining the current test state
Calling browser tools
Limiting the number of actions
Recording observations
Evaluating success or failure
Producing a test report
3. Browser Automation Layer
The browser layer performs deterministic operations such as:
Navigate
Click
Fill
Select
Read text
Capture screenshots
Wait for elements
Inspect page state
With Playwright for .NET, these operations can be exposed through C# methods.
A simple browser abstraction might look like this:
public interface IBrowserTool
{
Task NavigateAsync(string url);
Task ClickAsync(string selector);
Task FillAsync(string selector, string value);
Task<string> GetTextAsync(string selector);
Task<string> GetCurrentUrlAsync();
}
The agent does not need to know how the underlying browser connection works. It only needs access to these controlled capabilities.
Building a Basic Browser Tool in C#
A minimal Playwright-based implementation can look like this:
using Microsoft.Playwright;
public sealed class BrowserTool : IBrowserTool
{
private readonly IPage _page;
public BrowserTool(IPage page)
{
_page = page;
}
public async Task NavigateAsync(string url)
{
await _page.GotoAsync(url);
}
public async Task ClickAsync(string selector)
{
await _page.Locator(selector).ClickAsync();
}
public async Task FillAsync(string selector, string value)
{
await _page.Locator(selector).FillAsync(value);
}
public async Task<string> GetTextAsync(string selector)
{
return await _page.Locator(selector).InnerTextAsync();
}
public async Task<string> GetCurrentUrlAsync()
{
return _page.Url;
}
}
The value of this abstraction is not the browser code itself. The important part is that browser capabilities are exposed as controlled operations.
An agent can then reason about which operation to use without having direct access to the entire application runtime.
Designing the Agent Loop
A practical agentic QA loop should be bounded.
A simplified implementation could look like this:
public async Task<TestResult> RunAsync(
string objective,
IBrowserTool browser)
{
var state = new TestState(objective);
for (int step = 0; step < 20; step++)
{
var action = await _agent.DecideNextActionAsync(state);
if (action.Type == ActionType.Complete)
{
return state.IsSuccessful
? TestResult.Passed(state)
: TestResult.Failed(state);
}
await ExecuteActionAsync(action, browser);
var observation = await ObserveAsync(browser);
state.AddObservation(observation);
if (await _agent.ShouldStopAsync(state))
{
break;
}
}
return TestResult.Failed(
state,
"Agent reached the maximum number of steps.");
}
The maximum-step limit is important.
Without a boundary, an agent can repeatedly inspect a page, retry an operation, or make unnecessary decisions. A production pipeline should always have limits around execution time, action count, retries, and resource usage.
Making Browser Actions Agent-Friendly
A common mistake is giving an AI agent only low-level selectors.
For example:
Click "#btn123"
does not provide much semantic information.
A better tool can expose intent:
Click the "Continue to Checkout" button.
The browser implementation can still resolve that action to a locator.
This separation creates two layers:
| Layer | Responsibility |
|---|---|
| Agent | Decides what should happen |
| Tool | Determines how the action is executed |
| Browser | Performs the action |
| Application | Produces the result |
This makes the system easier to debug and maintain.
Handling Dynamic Web Applications
Modern applications frequently contain asynchronous operations, dynamic content, dialogs, and client-side rendering.
Tests should avoid unnecessary fixed delays.
Prefer condition-based synchronization:
await page
.GetByRole(AriaRole.Button, new() { Name = "Submit" })
.ClickAsync();
await page
.GetByText("Order created successfully")
.WaitForAsync();
The test is waiting for a meaningful application state instead of assuming that a specific number of milliseconds is sufficient.
This becomes even more important when an agent is involved because the agent's next decision depends on the accuracy of the observation.
Agent Memory and Test Context
An agent needs context about what has already happened.
A simple state object might contain:
public sealed class TestState
{
public string Objective { get; }
public List<string> Actions { get; } = [];
public List<string> Observations { get; } = [];
public bool IsSuccessful { get; set; }
public TestState(string objective)
{
Objective = objective;
}
public void AddObservation(string observation)
{
Observations.Add(observation);
}
}
For longer workflows, the state can also contain:
Current URL
Authenticated user
Completed steps
Expected outcome
Previous failures
Screenshots
Relevant application data
The key is to keep the context focused. Sending an entire application state to an agent on every step can increase processing cost and make decisions less predictable.
Agentic QA vs Traditional Test Automation
| Area | Traditional Automation | Agentic QA |
|---|---|---|
| Test flow | Predefined | Goal-driven |
| Browser actions | Explicit | Selected dynamically |
| Adaptability | Limited | Higher |
| Determinism | High | Lower |
| Debugging | Usually straightforward | More complex |
| Maintenance | Selector/test updates | Tool and goal maintenance |
| Best use | Regression testing | Exploratory and adaptive scenarios |
| Failure analysis | Assertion-based | Observation + reasoning |
Traditional automation remains extremely valuable for deterministic regression tests.
Agentic QA is more useful when the test requires exploration, interpretation, or adapting to changing application state.
Production Best Practices
Keep Deterministic Tests Deterministic
Do not introduce an agent simply because it is available.
A login regression test with a known sequence is usually better represented as a normal automated test.
Use agentic behavior where dynamic decision-making provides actual value.
Restrict Tool Permissions
The agent should only receive the browser operations it needs.
Avoid exposing:
Execute arbitrary shell commands
Modify production data
Access application secrets
Run unrestricted database queries
Instead, provide narrowly scoped tools.
Use Test Accounts
Agentic tests should operate against dedicated test environments and controlled accounts whenever possible.
This reduces the risk of unintended changes to real data.
Capture Evidence
When a test fails, collect enough information to understand why.
Useful artifacts include:
Screenshot
Current URL
Browser console output
Network errors where relevant
Agent actions
Agent observations
Final failure reason
For example:
await page.ScreenshotAsync(new()
{
Path = "artifacts/test-failure.png",
FullPage = true
});
Set Execution Limits
Always define boundaries such as:
Maximum actions: 20
Maximum retries: 2
Maximum execution time: 5 minutes
The exact values should be determined by the application's workflow and CI environment rather than treated as universal defaults.
Common Mistakes
Giving the Agent Too Much Freedom
An unrestricted agent is difficult to control and audit.
Use a defined tool set and explicit permissions.
Replacing All Existing Tests
Agentic QA should complement deterministic automation rather than automatically replace it.
Keep stable regression tests where they provide predictable coverage.
Using Poor Test Objectives
A vague instruction such as:
Test the application.
does not provide a useful success criterion.
A better objective is:
Verify that a registered customer can update
their shipping address and see the new address
during checkout.
Ignoring Observability
If the pipeline records only "test failed," troubleshooting becomes difficult.
Store the action sequence and relevant browser evidence.
Troubleshooting Agentic QA Pipelines
The Agent Repeats the Same Action
Check whether the observation after the action actually changes.
Add:
Step limits
Duplicate-action detection
Explicit failure states
Better page-state extraction
The Agent Selects the Wrong Element
Improve the browser tool's semantic information.
Prefer accessible roles, labels, and stable attributes over fragile generated CSS selectors.
Tests Are Flaky
Investigate synchronization first.
Avoid arbitrary delays and make the test wait for meaningful application states.
CI Tests Behave Differently
Compare the local and CI environments, including:
Browser version
Application build
Environment variables
Authentication setup
Network access
Test data
Agentic behavior can make environmental differences more visible, but it does not eliminate the underlying cause.
Advantages and Disadvantages
Advantages
Can handle more dynamic workflows
Supports exploratory testing scenarios
Can adapt to intermediate application states
Reduces the need to hard-code every decision
Can produce richer failure context
Disadvantages
Less deterministic than conventional tests
More difficult to debug
Requires careful tool and permission design
Agent execution can introduce additional processing cost
Poorly designed agents can produce inconsistent test behavior
A Practical Adoption Strategy
A gradual rollout is safer than replacing an existing QA framework.
Start with conventional browser automation.
Build a clean browser-tool abstraction.
Add structured application observations.
Introduce an agent for one exploratory workflow.
Add execution limits and audit logging.
Capture screenshots and failure evidence.
Run agentic tests separately from critical deterministic regression tests.
Measure whether the agent actually improves coverage or reduces maintenance effort.
Expand only where the results justify the additional complexity.
Conclusion
Agentic QA brings a different way of thinking about browser automation. Instead of defining every browser action in advance, developers can give an agent a test objective and provide controlled tools that allow it to inspect the application, take actions, and evaluate the result.
For .NET teams, the most practical architecture is not "AI replaces testing." It is a layered system where established C# test infrastructure and browser automation provide deterministic execution, while an agent adds decision-making for scenarios that benefit from adaptability.
The strongest implementations will combine both approaches: conventional automation for predictable regression coverage and agentic workflows for exploratory, dynamic, and harder-to-script QA scenarios. The key is to keep the agent bounded, observable, and connected only to the tools it genuinely needs.

Jasen FiciPosted Sep 1, 2026, 1:21 PM
We shared this in DotNetNews here: https://dotnetnews.co/archive/the-net-news-daily-issue-531/