Skip to content
BryanFiFifePublic

About

Local delegated-consent enforcement for autonomous AI agents

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

Assentia

Your agent can act for you. It cannot consent for you.
An open-source project from Caledapt

License: MIT Python 3.11+ MCP No API keys Fail closed

Assentia

Assentia is a local delegated-consent enforcement layer for autonomous AI agents. It gives browser agents a policy decision point before they interact with cookie or tracking consent interfaces, preventing an agent from silently granting more consent than its user delegated.

The default path is fully local: no paid service, no API key, and no network call is required for classification. Assentia is released free and open source under the MIT License by Caledapt, a Scottish AI implementation and adoption business founded by Bryan Small.

Why this exists

Saito, Kataiwa, Takashima and Ohki describe Invisible Consent as consent generated by browsing agents on a user's behalf without a meaningful opportunity for the user to notice or intervene. Their CHI EA 2026 study reports that agents often favour the easiest path through consent UI and that cookie acceptance persisted in 14.4% of explicit consent interactions even under a deny-all instruction.

Assentia puts an explicit policy boundary between the agent and that decision.

Research: Invisible Consent: Browser Automation by LLM Agents is Not Privacy-aware · DOI 10.1145/3772363.3799048

Decision flow

Browser agent
    │
    │ visible banner text + domain
    ▼
Assentia classifier
    │
    │ banner state + detected controls
    ▼
Assentia policy engine
    │
    ├── reject_all
    ├── essential_only
    ├── accept_all
    └── blocked
    │
    ▼
Agent may perform only that action

The classifier never clicks, navigates, submits, or grants consent. Unknown or unsupported UI fails closed.

Policy modes

Mode Behaviour
essential_only Prefer reject_all; otherwise use a genuine essential/necessary-only control; otherwise block.
strict Use reject_all when present; otherwise block.
allow_all Permit accept_all only when an accept control is detected; unknown UI still blocks.

A global default can be overridden per domain. The most specific matching parent-domain override wins.

mode: essential_only
domains:
  example.com: strict
  trusted.example: allow_all

The default policy path is ~/.assentia/policy.yaml. Override it with ASSENTIA_POLICY_PATH.

MCP contract

Assentia exposes three FastMCP tools:

  • consent.choose(banner_state?, banner_text?, domain?)
  • consent.get_policy(domain?)
  • consent.set_policy(mode, domain?)

MCP permits dot-separated tool names, so the public names mirror the consent namespace directly.

A host agent should be instructed to call consent.choose before interacting with cookie or tracking consent UI and to perform only permitted_action. A blocked result means it must not grant consent. If the workflow cannot safely continue, it should ask the human.

Example decision:

{
  "permitted_action": "reject_all",
  "policy_mode": "essential_only",
  "banner_state": "essential_only_present",
  "domain": "https://example.com",
  "classification": {
    "state": "essential_only_present",
    "actions": {
      "reject_all": true,
      "essential_only": false,
      "accept_all": true,
      "settings": true
    },
    "classifier": "rules"
  }
}

Install from source

Requires Python 3.11+ and uv.

git clone https://github.com/BryanFiFife/Assentia
cd assentia
uv sync --extra dev
uv run playwright install chromium
uv run pytest

Run the MCP server over STDIO:

uv run assentia

FastMCP's mcp.run() uses STDIO by default, which makes the server suitable for local MCP clients.

MCP client configuration

From a local checkout, point the client at uv and run Assentia from the project directory. For example:

{
  "mcpServers": {
    "assentia": {
      "command": "uv",
      "args": ["--directory", "/absolute/path/to/assentia", "run", "assentia"]
    }
  }
}

Use the configuration shape required by your MCP client. The important contract is that the client launches uv run assentia with this repository as its working directory.

Classifiers

Rules, default

The built-in classifier is deterministic and side-effect free. It recognises common English controls such as Reject all, Necessary only, Accept all, and Manage preferences.

No API or model is needed:

ASSENTIA_CLASSIFIER=rules uv run assentia

Ollama, optional

Assentia can classify with a local Ollama model without changing the enforcement contract:

ASSENTIA_CLASSIFIER=ollama \
ASSENTIA_OLLAMA_MODEL=gemma3:4b \
uv run assentia

Optional settings:

  • ASSENTIA_OLLAMA_URL, default http://127.0.0.1:11434/api/generate
  • ASSENTIA_OLLAMA_TIMEOUT, default 8 seconds

Ollama is not required for the default installation. Assentia uses Python's standard library HTTP client, so enabling the backend adds no Python dependency.

Custom classifier

Python integrations may inject a classifier with assentia.set_classifier(callable). It must return one of the four banner states and may include detected action capabilities. This is useful for local vision models, accessibility-tree classifiers, or a host-specific CMP detector.

Banner states

Assentia preserves a small, stable state contract:

  • essential_only_present
  • accept_all_present
  • no_reject_option
  • unknown

The classification also includes explicit action capabilities. This prevents the enforcement engine from confusing a visible Reject all control with a differently labelled essential-only control.

Playwright integration

examples/playwright_demo.py shows the intended hook:

  1. read visible page text;
  2. call Assentia;
  3. inspect permitted_action;
  4. click only a matching control for that action;
  5. perform no consent interaction when the decision is blocked or the permitted control cannot be located.

Run it against a site you are authorised to automate:

ASSENTIA_DEMO_URL='https://example.com' uv run python examples/playwright_demo.py

The example is deliberately conservative. It is an integration pattern, not a universal CMP clicker.

Tests

uv run pytest -q

The suite covers:

  • all four required classifier outcomes;
  • essential-only, strict, and allow-all policy modes;
  • fail-closed unknown states;
  • domain and subdomain overrides;
  • policy validation and persistence;
  • custom classifier injection;
  • MCP-facing tool functions;
  • a real Chromium process that proves an essential-only policy rejects a banner and never clicks Accept all.

GitHub Actions runs the suite on Python 3.11, 3.12, and 3.13 and installs Chromium for the browser regression test.

Security model and limitations

Assentia constrains a cooperating, correctly integrated agent. An MCP server alone cannot force a malicious or incorrectly wired agent to consult it. Stronger guarantees require enforcement below the agent, for example in the browser automation host, extension, proxy, or network layer.

Current limitations:

  • The rules classifier is intentionally English-first and text-first.
  • Preference centres that hide rejection behind multiple steps are not traversed automatically.
  • The example Playwright selectors do not attempt universal iframe or shadow-DOM CMP handling.
  • An Ollama classification failure is surfaced as an error rather than silently falling back to a more permissive result.
  • A supplied banner_state contains less information than raw banner text, so integrations should prefer banner_text where practical.

These are safety boundaries, not claims of universal coverage.

Project principles

  1. No silent consent. A browser agent does not acquire consent authority merely because it can click a button.
  2. Fail closed. Ambiguity must not become tracking permission.
  3. Local first. The default consent decision path should not leak browsing context to another service.
  4. Classify, then enforce. Detection and permission are separate responsibilities.
  5. Policy belongs to the user. Agents execute delegated choices; they do not invent them.

About Caledapt

Assentia is developed and released by Caledapt as free, open infrastructure for safer AI adoption. Caledapt assesses, designs, implements, trains and supports practical AI systems for organisations, with a focus on measurable deployment rather than AI theatre.

Founder: Bryan Small on LinkedIn
Website: caledapt.com

Assentia is intended to remain useful independently of Caledapt services. The MIT licence permits commercial and non-commercial use, modification and redistribution subject to its terms.

Contributing

See CONTRIBUTING.md. Security-relevant bypasses should follow SECURITY.md.

Release history

See CHANGELOG.md.

License

Assentia is free and open-source software released by Caledapt under the MIT License.

Copyright © 2026 Caledapt / Bryan Small.

About

Local delegated-consent enforcement for autonomous AI agents

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages