Agent Governance Foundation

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")
Note: a DENY raises 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

Methodaction.typeresource
goto(url)navigatethe URL
click(selector)clickthe selector
fill(selector, value)fillthe selector (never the typed value)
set_input_files(selector, files)uploadthe selector

Everything else on Pagepasses through unguarded by design — a deliberately small, curated set rather than an attempt to cover Playwright's full API.

Related