Sr. Content Developer at Microsoft, working remotely in PA, TechBash conference organizer, former Microsoft MVP, Husband, Dad and Geek.
159789 stories
·
33 followers

Browser automation with Pydantic-AI + Playwright

1 Share

When we build agents, we often want to give them the ability to browse the web: open webpages, navigate from one page to the other, and read the content of a webpage. By combining Pydantic AI with the Playwright capability from Pydantic AI Harness, we can build agents that browse the web safely and programmatically.

Using Pydantic AI with Microsoft Foundry models

Pydantic AI is an open-source model-agnostic framework from Pydantic for building LLM-based applications and agents. It's type-safe and supports OpenTelemetry, making it a great choice for robust production applications.

We can use Pydantic-AI with Microsoft Foundry models using either API keys or Entra token-based authentication. When possible, we always recommend the keyless route, so that's what we'll demonstrate here.

We use the azure-identity package to authenticate with Entra, using either local or managed identity, and get back a token provider callback function for that credential:

from azure.identity.aio import AzureDeveloperCliCredential, get_bearer_token_provider # Replace with ManagedIdentityCredential when running in production on Azure credential = AzureDeveloperCliCredential(tenant_id=os.environ["AZURE_TENANT_ID"]) token_provider = get_bearer_token_provider(credential, "https://cognitiveservices.azure.com/.default")


Then we use the OpenAI package to configure the model connection:

from openai import AsyncOpenAI client = AsyncOpenAI( base_url=os.environ["AZURE_OPENAI_ENDPOINT"] + "/openai/v1", api_key=token_provider, ) model = OpenAIChatModel( model_name=os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"], provider=OpenAIProvider(openai_client=client), )


Let's break down the options used above:

  • base_url: We point this at the OpenAI-compatible endpoint for our Foundry model. This endpoint works for Azure OpenAI models (like gpt-5.4, which this project deploys), and for cross-provider Foundry models that support the OpenAI v1 API, like Kimi-K2.7-Code. The base URL looks like "https://AZURE_OPENAI_SERVICE_NAME.openai.azure.com/openai/v1".
  • api_key: We pass in the token provider callback function that generates OAuth2 tokens using our Entra credential. If we were using API keys, we'd simply pass in the key string here instead.
  • model_name: We provide the name of the deployment, not the name of the model. Oftentimes, the deployment name is the same as the model, but not always - it depends on how you set it up in the Portal or infrastructure-as-code files. Notably, when using models on Foundry, you must always make an explicit deployment for the desired model, before you can use it.

Integrating Playwright capability

Playwright is a browser automation library. It was originally built for writing E2E tests to verify website correctness, and is still the best option for E2E tests today. Its browser automation capabilities also make it a powerful way to give an agent access to websites. When you yourself are developing a website, it's a great way to give the agent access to browse the website, do manual QA, and iterate on design improvements. We can also use Playwright to access other websites, as long as the website's terms permit programmatic access.

To integrate Pydantic AI with Playwright, we bring in the PlaywrightBrowser capability from pydantic-ai-harness, a library of additional capabilities for Pydantic AI agents.

from pydantic_ai_harness.playwright import PlaywrightBrowser browser = PlaywrightBrowser( allowed_domains=[website_hostname], block_private_addresses=True, headless=False, max_content_tokens=30000, action_timeout_ms=5_000, navigation_timeout_ms=30_000, screenshot_on_navigate=False, auto_install_chromium=False, )

Let's review those parameters:

  • allowed_domains: Restricts top-level navigation and data-moving requests (like fetch and XHR) to the specified hostnames. This prevents unexpected navigation and data transfer, keeping the agent’s scenario targeted.
  • block_private_addresses: By default, this option is set to True to prevent navigation to localhost and private or reserved IP addresses, even when that address appears in allowed_domains. Set it to False only when the agent needs explicit access to a trusted locally deployed application.
  • headless: By default, Playwright will run in headless mode, which means that the browser window is not visible. When developing, I often set this to False, since it can be helpful to actually watch Playwright control the browser.
  • max_content_tokens: This option limits the amount of webpage text returned to the agent. This defaults to 4000 tokens, so I increased it to 30,000 tokens to allow for longer webpages. Keep in mind that the amount of content returned will increase the usage of the context window, affecting both performance and latency of subsequent LLM calls.
  • action_timeout_ms and navigation_timeout_ms: Actions like clicking or typing and page navigations get separate deadlines, since they fail for different reasons. A click on a selector that does not exist should fail fast, so the action deadline defaults to 5 seconds, while a page load deserves more room; here I allow 30 seconds for navigation. A tool call can also pass its own timeout_ms when the agent knows a step is slow.
  • screenshot_on_navigate: Controls whether Playwright takes a screenshot after every navigation and attaches to the agent session. This defaults to False, since screenshots can bloat the context window, but you may want to enable it for more design-heavy workflows or for human auditing purposes.
  • auto_install_chromium: When set to True, the library itself will download the binary for the Chromium browser. This is off by default, so you must explicitly install chromium before running. Typically you would install chromium in your environments manually so that you can properly cache it across runs, like in CI/CD.

Creating the Pydantic AI agent

Now that we have the Foundry model connection and Playwright browser configured, we can construct a Pydantic AI agent that combines the model and capabilities together. We also include the FileSystem capability, restricted to an outputs folder, so that the agent can easily write out its Markdown reports.

agent = Agent( model=model, capabilities=[browser, FileSystem(root_dir=OUTPUT_ROOT)], system_prompt="You are a careful manual QA agent testing a website that the user owns...", )

 

Then we run the agent, asking it to do a manual QA pass on the specified website:

result = await agent.run( f"Perform a manual QA pass on {url}. Load this URL first, make a testing plan, and investigate " "the highest-value usability risks and functional bugs you can safely reproduce. " "Write the required report to outputs/qa-report.md.", )

 

The Pydantic AI agent sends the query to the Foundry model, along with the Playwright tool definitions, and the model decides which Playwright tool to call, looping until it's completed the task:

 

Instrumenting OpenTelemetry for inspecting the browsing activity

We can inspect the generated report to see that the agent successfully completed the task, but we usually want to dig deeper: What pages did it browse? What commands did it run on those pages? How many tokens were used during the process?

Fortunately, we can instrument any Pydantic AI agent with OpenTelemetry, exporting the traces to any OpenTelemetry-compliant provider, like Pydantic Logfire or Azure App Insights.

Let's step through the code to send traces to Logfire:

trace_file = (OUTPUT_ROOT / "traces.jsonl").open("a", encoding="utf-8") configured_logfire = logfire.configure( send_to_logfire="if-token-present", token=os.getenv("LOGFIRE_TOKEN"), service_name="pydanticai-playwright-qa", console=logfire.ConsoleOptions(), additional_span_processors=[SimpleSpanProcessor(ConsoleSpanExporter(out=trace_file))], )

That constructor sends the traces to Logfire based on the token saved in the environment. It includes logging of the traces to the console, plus an additional exporter to a local file. The console traces are helpful for us to watch while we are developing the agent, and the local traces file can be useful input for coding agents debugging an agent. By pointing an agent at the traces file, it can audit the Playwright browser calls and recommend improvements to the prompt and parameters.

Next, we set up instrumentation specific to the packages we're using:

configured_logfire.instrument_openai(client) configured_logfire.instrument_pydantic_ai(agent, include_content=True)

That code calls instrument_openai for our calls through the openai package, and instrument_pydantic_ai for our calls through pydantic-ai package. Both of those packages export traces using the Generative AI semantic conventions, which exists to ensure that calls to LLMs, tools, and agents, are traced in a consistent way across observability platforms and agent frameworks.

After running the agent, we can browse through the traces. Here's what a single run looks like:

 

To also export traces to Azure Application Insights, we can add an additional span processor from the azure-monitor-opentelemetry-exporter package, pointing at our App Insights instance:

connection_string = os.environ["APPLICATIONINSIGHTS_CONNECTION_STRING"] logfire.configure( # other arguments additional_span_processors=[ SimpleSpanProcessor(ConsoleSpanExporter(out=trace_file)), SimpleSpanProcessor( AzureMonitorTraceExporter.from_connection_string(connection_string) ), ], )

Since both platforms support OpenTelemetry, the traces are the same across both.

Accessing authenticated websites

But wait, what if the target website requires user login? When Playwright starts a browser instance, it's completely isolated from your day-to-day browser instance, so it has no access to cookies. Typically, that is a very good thing, since we don't want agents to have arbitrary access to our logged in accounts. However, you may be building an agent that is dependent on access to a logged in website.

In that case, we can explicitly pass a session state to the PlaywrightBrowser instance, and it will use the cookies and local storage from that state:

browser = PlaywrightBrowser( storage_state=json.loads(Path("playwright/.auth/site.json").read_text()) )

To generate that state JSON file, we can run the Playwright codegen command to pop up the website. Once we login and close the browser, the browser state is saved to the target location. It's important to keep that storage file safe and secure - don't check into version control!

uv run playwright codegen https://your-owned-site.example/ --save-storage=playwright/.auth/site.json

Then pass the saved state to the agent through the command-line option:

uv run python pydanticai_playwright.py https://your-owned-site.example/ \ --session-state playwright/.auth/site.json

Next steps

Download the full code for the Pydantic AI agent from this project:

github.com/pamelafox/pydanticai-playwright-agent

That repository also includes infrastructure-as-code (Bicep) for provisioning an Azure OpenAI model and configuring the full environment for you.

Fork the code, customize it, and make your own browser-using agent!

Read the whole story
alvinashcraft
32 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

Integrating French IGN Maps into the Blazorise Map Component

1 Share
Learn how to display IGN raster maps and thematic layers in Blazorise Maps, and center a map by geocoding a French address.
Read the whole story
alvinashcraft
33 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

Introducing the New TX Text Control Technical Demos

1 Share
We are happy to announce the release of our new TX Text Control technical demos, which provide a comprehensive showcase of our powerful text processing capabilities. Explore a variety of live demos demonstrating the versatility and functionality of TX Text Control in real-world applications.

Read the whole story
alvinashcraft
33 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

How to trust your AI-assisted data analysis

1 Share

AI tools can easily produce data analysis that looks authoritative without being verifiable. For anyone using AI to analyse data, whether you are the person doing the work or the person relying on the output, this post highlights what you should be thinking about.

Do those numbers look right?

Imagine an analysis lands on your desk. It has specific numbers, a clear narrative, a well-formatted report and a chart that makes the answer feel obvious. The person who produced it used AI to do most of the heavy lifting, and they are pleased with the result, so is everyone else who reads it. Then someone asks the natural follow-up question - how did we arrive at this number? And they're met with silence - not because the analysis is wrong, but because there is no way to tell whether it is right.

This is a pattern we are seeing more often as AI tools become part of everyday work for people without technical backgrounds. The output looks polished, but the process behind it does not exist in any form that can be inspected. The gap between those two things is where trust quietly breaks down. And as I've argued numerous times before: data insights are useless, even dangerous, if they can't be trusted.

Why the output looks right even when it isn't

Modern AI tools are very good at producing plausible, well-presented output. That is true whether the underlying logic is sound or not. A poorly reasoned analysis and a carefully reasoned one can look almost identical on the page. The chart will be just as impressive, the commentary will be just as confident, the numbers will be just as specific.

If supporting documentation has been written, it's probably not as helpful as you would assume as it will typically describe what the analysis was intended to do. It rarely describes what it actually does, because the person writing the documentation often cannot tell the difference. The intent is in their head, but the implementation is in the AI's output - and the two are assumed to match.

A good way to think about this is remembering the "human in the loop" concept that has become central to the rise of AI - keeping a real person involved in the AI workflow to ensure accuracy, safety, accountability or ethical decision-making. But, this only works if the human can meaningfully evaluate what the AI did.

In a recent piece of work we reviewed, a domain expert had used AI to produce statistical analysis of a fairly sensitive dataset. The code looked plausible, and the code comments were thorough. But buried inside were arbitrary decisions about how the statistical analysis would work - values that the AI had chosen with no rationale attached - and the person who had commissioned the work had no way of knowing they were there, or even that they should be looking for them.

A pattern that causes this: isolated sessions, incremental patches

The root cause is usually structural rather than careless. It comes from how AI chat tools are typically used - one session at a time, each conversation picking up the last one's output and nudging it forward.

The analysis gets built across many isolated AI sessions in an incremental, exploratory way. It works, in the sense that something usable comes out the other end. But it has been patched together across many sessions without keeping a full contextual history, and without ever being focused on creating a working, end-to-end, repeatable process.

That is what causes the whole process to fail. You end up with something that produces an answer but cannot be explained. There is no single artefact you can hand to someone else and say "this is how we got here." Each change lives inside a different chat transcript, each assumption is set in a session that has long since scrolled out of context. Nobody, including the person who built it, can reconstruct the whole thing.

The most important shift: from answers to working out

The single most useful change is in a mindset shift about what you're asking the AI to do. Instead of asking AI for a conclusion, ask it to write the code that produces the conclusion.

This represents a step-change from how most non-technical users approach AI tools. Asking AI for an answer gives you something you cannot verify. Asking AI to write code that calculates the answer gives you something repeatable, inspectable, and shareable. The reasoning moves from inside the AI's head to a file you can open. You can run it again next week with new data, you can add checks and balances, and someone else can independently review it.

The point worth emphasising is that this works even if you cannot read code yourself. If the analysis exists as code, you have the option of asking someone who can. Or, if all else fails, you could use a different AI (model) to act as an independent reviewer, or explain what the code is doing. If all you have is a chat transcript and a final figure, that option does not exist.

Most of us will have encountered this principle long before we heard of AI. In any school level maths exam, arriving at the right answer was not enough on its own. Your teacher wanted to see your working out - not because they doubted you could produce a number, but because the working out was the only way to know whether you understood the method, whether you could apply it again, and whether the answer was the result of genuine reasoning rather than a lucky guess. Marks were awarded for the process, not just the conclusion. The same logic applies here.

A framework for trustworthy AI-assisted analysis

Here are five practical principles, none of which require a technical background to apply.

1. Work toward a process, not a pile of outputs. Every session should be building something durable, not generating a temporary result. The goal is an end-to-end process, set of steps, or pipeline you can run again, not a folder of one-off answers that happen to agree with each other. This might mean instructing the AI to write a plan first, which it can refer back to and update as things progress, or being clear about your expectations on what type of outputs you need.

2. Ask for code, not conclusions. Put the logic somewhere visible and re-runnable. If the AI writes code, the reasoning is inspectable, even if you need help to inspect it. If the AI just tells you the answer, it isn't. Most major AI tools have the ability to write and even execute code, even if you can't.

3. Break it into steps you can check. Ask the AI to show intermediate outputs at each stage - row counts, averages, ranges, the shape of the data after each transformation. And generate these intermediary outputs in formats that you can verify - e.g. .csv files that you can open in Excel. Numbers you can sense-check are far more trustworthy than a single final number presented as the result.

4. Use persistent projects, not isolated sessions. Most AI tools now offer projects or persistent contexts/memory. They keep the AI's understanding of your analysis consistent across sessions and avoid the patched-and-incremental failure mode where every conversation starts from scratch. Add this to an overarching plan, and you've got a workflow that can pick back up where you left off and regain and apply any necessary context.

5. Track what changes. Even basic file versioning helps, like version history in a synced OneDrive folder (but Git is much better). The goal is being able to answer "what changed between this run/feature and the last?" If you cannot answer that question, you cannot explain a change in your results, and you cannot defend the analysis to anyone who asks about it.

What to ask if you're the decision-maker, not the analyst

You do not need to understand the code to ask the right questions. Three questions will quickly expose whether an AI-assisted analysis is verifiable or not:

  • Can this be run again with new data and produce the same result?
  • Can you walk me through the intermediate steps?
  • What changed between this version and the previous one?

If nobody on the team can answer those questions clearly, the analysis isn't ready to rely on. That is true regardless of how good the chart looks or how confident the summary sounds. The biggest hurdle is likely to be the discomfort of asking - it can feel like you are challenging the analyst's competence. But, you are checking that the work is in a state where it can be trusted, which is a different thing entirely.

Summary

So yes, the technology is genuinely capable - AI tools can produce analysis in a fraction of the time that a skilled team can. But capability without traceability is a specific risk. To put it another way, as I said at SQL Bits 2024 in my talk about testing data solutions: If it matters if it's wrong, then you need to be able to prove that it's right.

The risk is biggest for people who do not have a technical background but, importantly, following the advice in this post does not require you to become a software developer. It does require treating AI as a collaborator inside a structured process, rather than a magic oracle you ask once and then publish. And yes, this approach will take slightly more discipline up front, but it will give you something you can actually defend when the questions start.



Read the whole story
alvinashcraft
33 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

Preview v0.101.2323.0

1 Share

PowerToys v0.101.2323.0 Preview

This preview release prevents update checks from resetting enabled modules, restores Shortcut Guide exclusions, and improves issue-triage accuracy.

Installer Hashes

Description Filename sha256 hash
Per user - x64 PowerToysUserSetup-0.101.2323.0-x64.exe BBC4B04CB626CAADF99C87610425F23EF3F45CCE3A81B34BFC695A2B7293FEE8
Per user - ARM64 PowerToysUserSetup-0.101.2323.0-arm64.exe 5284241DAE076E26C0F551C50BA11610D4182681F05E41368C8A540076FC9281
Machine wide - x64 PowerToysSetup-0.101.2323.0-x64.exe 1C31ACFEA3003543E390E6FE4414CB5F71CB56AF8D9210DB522433EE381F43C1
Machine wide - ARM64 PowerToysSetup-0.101.2323.0-arm64.exe 5A44BFC48381BEB8E03A12B7C7AC7BD60F1632F9C51A008D2D1E4AAC36C4922A

Highlights

  • Settings: Prevented manual update checks from overwriting enabled module states when Settings held stale or default values.
  • Shortcut Guide: Restored excluded-app filtering for regular-hotkey and Windows-key-hold activations, including newly saved exclusions.
  • Issue triage: Preserved reported version labels and recognized more natural-language reproduction steps.

General

  • Added attribution for Wzhudev's AltBackTick work to the Window Hopper settings page in #49962.
  • Corrected automated issue triage so it no longer manages version labels and better recognizes concise reproduction steps in #49999.
  • Prevented update checks from sending or applying stale general settings that could reset enabled modules in #50018.
  • Restored Shortcut Guide excluded-app filtering on every hidden-overlay activation while preserving visible-overlay close and promotion behavior in #50046 by @LegendaryBlair.
Read the whole story
alvinashcraft
34 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

Microsoft quietly hides the new OneDrive app it force-installed on Windows 11, but it’s still on your PC

1 Share

You’ll no longer find “OneDrive Photos” in the Start menu apps list or in Windows Search results, as Microsoft appears to be quietly hiding the app while it figures out a way to make the experience less intrusive.

OneDrive Photos is the same app that was force-installed on PCs running Windows 11 and 10, including enterprise devices where it doesn’t even launch.

After the rollout, Microsoft called it an accident and noted that it did not intend to release the app so broadly.

“We are incubating a new photos experience in OneDrive that went more broadly than it should have in Windows,” Microsoft’s Jeff Teper wrote in a post on X. “We’re fixing that. Windows Photos will always give you the option of local and cloud photos and the choice to use OneDrive or not.”

Microsoft also argued that it’s listening to feedback and will improve how OneDrive displays photos across desktop, web, and mobile.

In other words, Microsoft has no plans to give up on this new client, even though it overlaps with the existing OneDrive and Photos integrations on Windows 11. Instead, the company now appears to be hiding the standalone app from Start and Search while it works on making the experience less intrusive, including adding a way to remove it separately.

What is this new OneDrive app?

OneDrive Photos for Windows 11

For those who were never offered the OneDrive Photos app during the accidental rollout, it’s a new web-based (WebView2) client that allows you to browse local photos and those stored in the cloud.

OneDrive Photos app RAM usage

This means the app essentially loads OneDrive.com’s Gallery with access to your local storage. In our tests, we found OneDrive Photos to be more than decent, as its RAM usage typically stays below 1GB, which is still better than Microsoft’s usual standards, considering we have apps like Weather consistently using more than a gigabyte of memory.

OneDrive Photos Search page OneDrive Photos for Windows 11 OneDrive Photos image editor This PC section in OneDrive Gallery app OneDrive Photos app Gallery section OneDrive Photos app People section

OneDrive Photos also does a pretty good job of being a gallery app. It automatically finds photos stored across your PC’s folders, and you have the option to manually exclude or include locations. At the same time, you can easily use it to access photos in the cloud and move or copy files back and forth.

However, OneDrive Photos still feels unnecessary because you can already access everything in OneDrive directly in File Explorer, or you can simply use the Microsoft Photos app.

When OneDrive Photos was added to PCs, we noticed it wasn’t easy to remove because it was tied to the main OneDrive sync client, which is pre-installed on Windows PCs.

Windows 11 OneDrive Photos
OneDrive Photos app in the Search results before today’s update

If you clicked the Uninstall button in the search results for “OneDrive Photos,” you’d be redirected to the Windows Settings app, where you’d see the OneDrive sync client listed, not the Photos experience you actually wanted to remove:

OneDrive app uninstall button

The problem is that if you uninstall the OneDrive sync client just because you don’t want the new Photos app, you risk breaking OneDrive shortcuts in File Explorer and other places, as well as interrupting cloud sync.

For example, if a file is synced to the cloud and isn’t present locally, but you think it is, removing the sync client could leave you without the local access you expected.

OneDrive in Windows 11

Microsoft later admitted that it should have provided an option to remove OneDrive Photos without affecting the OneDrive sync client and said it’ll be rolled out later this year. But that didn’t calm the backlash, and Microsoft is now hiding the app while it works on giving users greater control over it.

OneDrive Photos is now hidden from Windows Search and Start

In our tests, OneDrive Photos no longer appears in the Start menu’s apps list, and searching for “OneDrive Photos” in Windows Search doesn’t bring it up either.

For example, the app showed up alongside the OneDrive sync client when you searched for Photos before today’s update. Now, if you search for it, you’ll only see the sync client, which was already pre-installed on Windows PCs unless you removed it after setting up Windows.

OneDrive Photos app disappeared
OneDrive Photos app disappeared after today’s update

But the OneDrive Photos app is still quietly sitting inside your PC.

Our tests confirm that the app itself remains installed and can still be launched through other entry points, such as by opening the OneDrive installation folder and double-clicking OneDrive.App.exe:

OneDrive Photos app hidden

That means Microsoft hasn’t actually removed it. It has simply stopped presenting OneDrive Photos as another standalone app on your PC.

That’s probably a better approach than putting yet another Photos app in the Start menu, especially when Windows already ships with Microsoft Photos and OneDrive is deeply integrated into File Explorer. But it also makes the whole rollout even stranger.

OneDrive Photos now quietly lives on your PC and can read your local photos, but it won’t show up in Search or the Start menu. I assume this is part of Microsoft’s effort to limit the backlash while it works on adding a dedicated uninstall option.

“We’re adding controls to remove the OneDrive Photos experience separately from the OneDrive app,” Microsoft previously noted in an update to its admin portal.

“OneDrive is giving people more control over their Windows experience by allowing them to uninstall the OneDrive Photos experience independently. Removing the Photos experience does not uninstall the OneDrive app, interrupt file sync, or delete photos and files. This provides a clear removal option for people who prefer to manage their photos with another app,” the company explained.

It’s only a matter of time before OneDrive Photos returns more visibly, but when it does, you’ll at least have the option to remove it easily.

The post Microsoft quietly hides the new OneDrive app it force-installed on Windows 11, but it’s still on your PC appeared first on Windows Latest

Read the whole story
alvinashcraft
2 hours ago
reply
Pennsylvania, USA
Share this story
Delete
Next Page of Stories