Academy → Developer GuideOfficial documentation · Arabic guidance

Browser Provider Plugins

إضافات مزوّد المتصفح

Advanced4 min readLesson 252 questions✓ 2026-08-18
Before you read

What this page is, and what it holds.

This page covers Browser Provider Plugins. You will use hermes tools here; about 4 minutes to read. Start on public pages with no sign-in. A browser wired to your accounts acts as you.

7sections
6code examples
0tables
1commands
724source words
The official one-line description

How to build a cloud browser backend plugin for Hermes Agent

What you will be able to do

Outcomes taken from this page, not a template.

  • Understand what التحكم في المتصفح is and when you need it.
  • Run hermes tools and understand what happens next.
  • Know the common mistake before you hit it.
Identifiers you will meet

Exactly as they appear in Hermes.

Commands
  • hermes tools
Page map

Jump to the part you need.

  1. 01How it fits together
  2. 02Discovery
  3. 03Directory structure
  4. 04The BrowserProvider ABC
  5. 05Users configure it
  6. 06Reference implementations
  7. 07Checklist
The full official page

Nothing summarised away.

The documentation body below is reproduced from the official source so commands and identifiers stay exact. Each section carries a short note describing what it contains.

Browser provider plugins register a cloud browser backend that services cloud-mode browser_* tool calls (navigate, click, screenshot, …). Built-in providers — Browserbase, Browser Use, and Firecrawl — all ship as plugins under plugins/browser/<name>/. You can add a new one, or override a bundled one, by dropping a directory next to them.

How it fits together

Explains the idea itself. Read it slowly; the later sections build on it.

A browser provider does not implement browsing. It implements session lifecycle: create a remote browser session, hand back a CDP websocket URL, and tear the session down. Hermes' own browser stack (agent-browser + tools/browser_tool.py) connects to whatever CDP URL you return and drives the page from there — every provider gets the full browser_* toolset for free.

The active provider is selected by browser.cloud_provider in config.yaml; the dispatcher in tools/browser_tool.py is a pure registry lookup with no per-provider conditionals.

Discovery

Explains the idea itself. Read it slowly; the later sections build on it.

Hermes scans for browser backends in three places:

  1. Bundled — <repo>/plugins/browser/<name>/ (auto-loaded with kind: backend)
  2. User — ~/.hermes/plugins/browser/<name>/ (opt-in via plugins.enabled or hermes plugins enable <name>)
  3. Pip — packages declaring a hermes_agent.plugins entry point

Each plugin's register(ctx) calls ctx.register_browser_provider(...), which puts the instance into the registry in agent/browser_registry.py.

Directory structure

Settings you configure once. Change one at a time so you can see what each does.

Text4 lines
plugins/browser/my-backend/
├── __init__.py     # register() entry point
├── provider.py     # BrowserProvider subclass
└── plugin.yaml     # Manifest with kind: backend and provides_browser_providers

plugin.yaml:

YAML7 lines
name: browser-my-backend
version: 1.0.0
description: "My cloud browser backend. Requires MY_BACKEND_API_KEY."
author: you
kind: backend
provides_browser_providers:
  - my-backend

__init__.py:

Python5 lines
from plugins.browser.my_backend.provider import MyBackendProvider


def register(ctx) -> None:
    ctx.register_browser_provider(MyBackendProvider())

The BrowserProvider ABC

Commands you type in a terminal. Understand what one does before copying it. Commands here: hermes tools.

Implement agent.browser_provider.BrowserProvider. Three lifecycle methods plus identity:

Python36 lines
from agent.browser_provider import BrowserProvider


class MyBackendProvider(BrowserProvider):
    @property
    def name(self) -> str:
        return "my-backend"          # the browser.cloud_provider config value

    @property
    def display_name(self) -> str:
        return "My Backend"          # shown in `hermes tools`

    def is_available(self) -> bool:
        """Cheap check only — env var present, dep importable.
        NO network calls: runs at tool-registration time and on every
        `hermes tools` paint."""
        return bool(os.environ.get("MY_BACKEND_API_KEY"))

    def create_session(self, task_id: str) -> dict:
        """Create a remote browser session; return the session-metadata contract."""
        session = my_api.create_browser(...)
        return {
            "session_name": f"my-backend-{task_id}",  # unique agent-browser session name
            "bb_session_id": session.id,              # provider session ID (for cleanup)
            "cdp_url": session.cdp_ws_url,            # CDP websocket URL
            "features": {"stealth": True},            # feature flags you enabled
        }

    def close_session(self, session_id: str) -> bool:
        """Terminate by provider session ID. Log-and-return-False on error —
        never raise, so the dispatcher's cleanup loop keeps moving."""
        ...

    def emergency_cleanup(self, session_id: str) -> None:
        """Best-effort teardown from atexit/signal handlers. Must not raise."""
        ...

The session-metadata contract

create_session() must return at least session_name, bb_session_id, cdp_url, and features. Two quirks worth knowing:

  • bb_session_id is a legacy key name kept verbatim for backward compatibility with tools/browser_tool.py — it holds your provider's session ID regardless of vendor. Don't rename it.
  • create_session() may raise — ValueError for missing credentials, RuntimeError for network/API failures. The dispatcher surfaces these to the user. This differs from close_session/emergency_cleanup, which must never raise.

An optional external_call_id key supports managed-gateway billing.

getsetupschema() — the hermes tools picker row

Override this to appear as a first-class option in the Browser Automation picker with API-key prompts and an install hook:

Python12 lines
def get_setup_schema(self) -> dict:
    return {
        "name": "My Backend",
        "badge": "paid",
        "tag": "Cloud browser with stealth and proxies",
        "env_vars": [
            {"key": "MY_BACKEND_API_KEY",
             "prompt": "My Backend API key",
             "url": "https://mybackend.example"},
        ],
        "post_setup": "agent_browser",   # ensures local Chromium is installed (agent-browser itself resolves via npx)
    }

Per the project standard for tool backends: if a backend can't be selected and configured through hermes tools, it isn't done — "set this env var manually" is not an integration.

Users configure it

Settings you configure once. Change one at a time so you can see what each does.

YAML2 lines
browser:
  cloud_provider: my-backend

Reference implementations

Explains the idea itself. Read it slowly; the later sections build on it.

The three bundled providers under plugins/browser/ are the canonical examples, in ascending complexity: firecrawl (simplest), browser_use, and browserbase (stealth/proxy/keep-alive feature flags with graceful fallback when paid features are unavailable). Copy the closest one.

Checklist

Commands you type in a terminal. Understand what one does before copying it. Commands here: hermes tools.

  • [ ] name is lowercase and stable (it's a config value users write)
  • [ ] is_available() makes zero network calls
  • [ ] create_session() returns the full metadata contract (bb_session_id key name intact)
  • [ ] close_session() / emergency_cleanup() never raise
  • [ ] get_setup_schema() exposes your env vars so hermes tools can configure the backend
  • [ ] plugin.yaml declares kind: backend + provides_browser_providers
Knowledge check

2 questions answered by this page alone.

Every option is a real identifier from the Hermes documentation. The wrong ones are real too, just from other pages.

1. Which of these headings does not appear in this lesson?
2. Which configuration key appears in this lesson's examples?