Pydantic AI

Build provider-agnostic, typed Python browser agents with dependency injection.

Pydantic AI is the Pydantic team's agent framework. It's provider-agnostic and reuses the Pydantic models you'd already validate API I/O with for tool arguments and final outputs, so adding an agent to a typed Python codebase doesn't introduce a parallel schema layer. The Steel integration passes a Playwright Page through RunContext.deps, so every tool in an agent run sees the same cloud browser without module globals.

Requirements

  • Steel API Key: Active Steel subscription
  • Model provider key: OpenAI, Anthropic, Google, or any other Pydantic AI-supported provider
  • Python: 3.10+

Connect Steel to Pydantic AI

Define a BrowserDeps dataclass holding the Steel-backed Playwright Page, register tools that read ctx.deps.page, and pass deps= to agent.run:

Python
from dataclasses import dataclass
from playwright.async_api import Page, async_playwright
from pydantic_ai import Agent, RunContext
from steel import Steel
@dataclass
class BrowserDeps:
page: Page
async def navigate(ctx: RunContext[BrowserDeps], url: str) -> dict:
"""Navigate to a URL and wait for the page to load."""
await ctx.deps.page.goto(url, wait_until="domcontentloaded")
return {"url": ctx.deps.page.url, "title": await ctx.deps.page.title()}
agent = Agent(
"openai:gpt-5-mini",
deps_type=BrowserDeps,
tools=[navigate],
)
steel = Steel(steel_api_key=STEEL_API_KEY)
session = steel.sessions.create()
playwright = await async_playwright().start()
browser = await playwright.chromium.connect_over_cdp(
f"{session.websocket_url}&apiKey={STEEL_API_KEY}"
)
page = browser.contexts[0].pages[0]
result = await agent.run("Open example.com and report the title.", deps=BrowserDeps(page=page))

Full runnable starter: Steel + Pydantic AI recipe →

Resources