Browser agent integration
A browser-automation agent has no downstream server for AGF to front — the browser is local. GuardedPage wraps a Playwright page directly instead, gating the four actions with the most governance relevance.
Install
pip install agf-sdk[browser]
Requires Python ≥ 3.10 and playwright ≥ 1.40. No separate gateway or runtime component — this is pure SDK.
Set your API key
export AGF_API_KEY=agfk_your_key_here
Generate a key from Settings → API Keys.
Wrap a page
GuardedPage wraps a real Playwright Page — every other method (title(), screenshot(), the rest of Playwright's API, including with page:) passes straight through untouched.
import os
from playwright.sync_api import sync_playwright
from agf import AGFClient
from agf.browser import GuardedPage
client = AGFClient(api_key=os.environ["AGF_API_KEY"])
with sync_playwright() as p:
browser = p.chromium.launch()
page = GuardedPage(
browser.new_page(),
client,
agent_id="did:agf:agt_01abc",
)
page.goto("https://vendor-portal.acme.com/invoices") # checked: navigate
page.click("#approve-payment") # checked: click
page.fill("#amount", "4200.00") # checked: fill
page.set_input_files("#receipt", "receipt.pdf") # checked: upload
# Everything else passes through untouched
page.title()
page.screenshot(path="confirmation.png")AGFDeniedError before the underlying Playwright call runs — the click, fill, or navigation genuinely never happens.Async pages
GuardedPage works identically with playwright.async_api — detected automatically, no separate class:
import asyncio
from playwright.async_api import async_playwright
from agf import AGFClient
from agf.browser import GuardedPage
async def main():
client = AGFClient(api_key="ak_live_...")
async with async_playwright() as p:
browser = await p.chromium.launch()
page = GuardedPage(await browser.new_page(), client, agent_id="did:agf:agt_01abc")
await page.goto("https://vendor-portal.acme.com/invoices")
await page.click("#approve-payment")
asyncio.run(main())Delegated authority
# Pass a delegation chain explicitly if this agent's authority derives
# from an upstream one, same as any other AGF integration
page = GuardedPage(
browser.new_page(),
client,
agent_id="did:agf:agt_01abc",
chain=[orchestrator_jwt, agent_jwt],
)What's guarded
| Method | action.type | resource |
|---|---|---|
| goto(url) | navigate | the URL |
| click(selector) | click | the selector |
| fill(selector, value) | fill | the selector (never the typed value) |
| set_input_files(selector, files) | upload | the selector |
Everything else on Pagepasses through unguarded by design — a deliberately small, curated set rather than an attempt to cover Playwright's full API.

