Statelock: Deterministic guardrails for browser agents, enforced at CDP Statelock, an open-source project from Inferlink, released a Chrome DevTools Protocol (CDP) proxy that enforces deterministic policy checks on AI browser agents before each click, keystroke, upload or download and records evidence for every decision. The tool installs as the PyPI package `statelock-ai` (importing as `statelock`; the PyPI package named `statelock` is an unrelated project) and works with Playwright, browser-use, Stagehand, LangChain or any CDP client against headless Chromium. In its built-in finance demo, a policy comparing `bank_deposit_amount` with `erp_invoice_amount` blocked a "Mark as Paid" click because the deposit was $4,900.00 against a $5,000.00 invoice, with the page, checked values, verdict and a screenshot stored under `artifacts/sessions//`. Statelock adds policy checks and evidence to AI browser automations. It is a Chrome DevTools Protocol CDP proxy between your agent Playwright, browser-use, Stagehand, LangChain or any CDP client and a headless Chromium. Before each click, keystroke, upload or download, Statelock captures the page and checks your policy, then releases or blocks the action. After a commit action it checks post-conditions. It records evidence for every decision. An agent can then work in a real web portal inside clear limits: it may decline a manuscript but not send it to review, or mark an invoice as paid only when the bank deposit matches. Install it the package is statelock-ai and imports as statelock ; the PyPI package named statelock is an unrelated project : pip install statelock-ai python -m playwright install chromium Write a policy and a key for your agent. This policy blocks "Mark as Paid" on the built-in finance demo when the bank deposit and the invoice differ: cat policy.yaml <<'EOF' policies: - agent id: finance agent target url contains: /demo/finance pre conditions: - assert field equal: {left: bank deposit amount, right: erp invoice amount} EOF statelock keygen --agent-id finance agent --append keys.yaml prints the agent's key; keys.yaml holds only its hash Start Statelock with the demo pages on: STATELOCK POLICY FILE=policy.yaml STATELOCK AUTH KEYS FILE=keys.yaml STATELOCK ARTIFACT DIR=artifacts \ STATELOCK DEMO=1 statelock --port 8010 In another shell, run an agent that tries to mark a mismatched invoice as paid: export STATELOCK URL=http://localhost:8010 STATELOCK API KEY=slk ... the key keygen printed cat agent.py <<'EOF' import asyncio from playwright.async api import async playwright import statelock.client async def main - None: async with async playwright as p: async with await statelock.client.connect playwright p as governed, governed.guard : await governed.page.goto "http://localhost:8010/demo/finance?scenario=mismatch" await governed.page.click "text=Mark as Paid" asyncio.run main EOF python agent.py StatelockPolicyViolationError: pre condition/assert field equal Blocked action because bank deposit amount $4,900.00 did not equal erp invoice amount $5,000.00 ... The click never reached the page. artifacts/sessions/