Browser4 Plugin Development
Quick Start
mvn -pl browser4-pdk install # install the PDK parent POM once
mvn archetype:generate -DarchetypeGroupId=ai.platon.pulsar \
-DarchetypeArtifactId=browser4-plugin-archetype # scaffold the plugin project
mvn -f <artifactId>/pom.xml package # build the plugin JAR
Deploy the JAR to the server's plugins/ directory (or POST it to http://localhost:8182/api/plugins/install) and restart — the plugin is auto-discovered. Prerequisites: JDK 17+, Maven 3.9+, and access to the browser4-pdk parent POM.
For the full walkthrough — requirements clarification, mount-point implementation, services/config, manifest, tests, build & deploy — see Step-by-Step Workflow.
When to Use
Use this skill when the user wants to create, build, scaffold, or extend a Browser4 plugin — CAPTCHA solving, media processing, content conversion, page-category detection, custom RPA actions, or new LLM agent tools. It is the deep guide (mount points, services, tests, deployment); for plugin code scaffolding inside this repo use the browser4-coding skill.
Do NOT create a plugin for: simple data extraction from a known site (use the browser4-cli HTML snapshot / X-SQL instead), one-off browser automation (the CLI or a quick script is faster), or modifying core Browser4 behavior (that belongs in the main source tree, not a plugin).
How It Works
A plugin is a thin JAR built against the browser4-pdk parent POM: you scaffold the project from the archetype, implement the relevant PluginMount interfaces (Browse/Load/Crawl event mounts, ToolMount, PageSnifferMount), wire Spring auto-configuration, and build. The server auto-discovers the JAR from plugins/ on restart and logs the mounted beans.
Patterns
1. Event-handling plugin (BrowseEventMount)
Scaffold with mountPoints=["BrowseEventMount"], implement the browse handler, and register it via auto-configuration. The key hook is onDocumentSteady — see Step 4a for the full code.
2. Plugin with LLM agent tools (ToolMount)
Scaffold with mountPoints=["ToolMount"] and hasCustomTools=true, implement a ToolExecutor extending AbstractToolExecutor, and declare the tool in plugin.json — see Step 4d.
3. Full-featured plugin (all major patterns)
Model it on the first-party plugins — browser4-plugins/browser4-images/ implements BrowseEventMount + ToolMount + Browser4Plugin + Config + Service + BrowseEventHandler + ToolExecutor.
Flags
The archetype takes named parameters — there are no CLI flags:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
groupId |
String | Yes | — | Maven groupId for the new plugin project (e.g., com.example) |
artifactId |
String | Yes | — | Maven artifactId, conventionally browser4-<feature-name> |
version |
String | No | 1.0.0-SNAPSHOT |
Plugin version |
pluginName |
String | Yes | — | Human-readable plugin name (e.g., "My Feature Plugin") |
pluginDescription |
String | No | "A Browser4 plugin that provides custom functionality" |
One-line description |
mountPoints |
String[] | No | ["BrowseEventMount"] |
Which PluginMount interfaces to implement. Options: BrowseEventMount, LoadEventMount, CrawlEventMount, ToolMount, PageSnifferMount |
hasCustomTools |
Boolean | No | false |
Whether the plugin registers LLM agent tool executors |
hasLifecycle |
Boolean | No | false |
Whether the plugin implements the Browser4Plugin lifecycle interface |
features |
String[] | No | — | List of concrete capabilities to implement (e.g., "detect media on page", "download files", "expose LLM tool") |
When to Create a Plugin
Create a plugin when you need to:
- Hook into the browse lifecycle — execute custom logic on page-navigation events (before navigation, after DOM is steady, before tab close). Examples: CAPTCHA detection and solving, ad blocking, custom RPA workflows.
- Hook into the load lifecycle — intercept or transform page content during loading. Examples: URL normalization and stripping tracking parameters, content extraction, HTML post-processing.
- Hook into the crawl lifecycle — accept or reject URLs during crawling. Examples: domain allowlists, duplicate URL filtering, paywall detection and skip.
- Register custom tools for LLM agents — expose new capabilities as callable functions. Examples: image download, PPTX generation, database queries, API integrations.
- Add page category sniffers — teach Browser4 to recognize new page types so it can adapt its behavior. Examples: CAPTCHA pages, login pages, paywalls, shopping carts.
Errors & Recovery
| Symptom | Likely cause | Fix |
|---|---|---|
| Plugin not loaded at startup; no "registered plugin" log | browser4-plugin.json missing, malformed, or JAR not in the plugins directory |
Verify JAR is in the configured plugins directory; verify JSON is valid; verify autoConfigurationClasses FQN matches |
| Plugin skipped as "default-disabled (opt-in)" | Manifest has defaultEnabled: false and no explicit enable override |
Enable with browser4.plugins.enable=<name> or browser4.plugins.enable-all=true, or set defaultEnabled: true |
ClassNotFoundException for Browser4 API classes |
Dependency scope is compile instead of provided |
Change all browser4-* and Spring Boot deps to <scope>provided</scope> |
| Mount point handlers never fire | Auto-configuration class doesn't implement the correct PluginMount interface, or AutoConfiguration.imports file is missing/wrong |
Verify AutoConfiguration.imports contains the exact FQN; verify the auto-config class implements the mount interface |
BeanCreationException at startup |
A bean dependency is missing or circular | Check bean constructor args; ensure @Lazy on the auto-config class |
| Tool executor not available to agents | getToolExecutors() returns empty list, or executor not exposed as a Spring bean |
Verify the list contains beans from applicationContext; verify executor has @Bean in auto-config |
| Archetype generation fails | Maven can't resolve browser4-plugin-archetype |
Build the PDK locally first: mvn -pl browser4-pdk install |
onDocumentSteady handler throws silently |
Missing try-catch in handler body | Always wrap handler body in try-catch; log errors via a logger |
| Config properties have no effect | Config class not reading from Config or property prefix mismatch |
Verify fromConfig() method reads all keys with correct prefix; verify property names in application config |
NoSuchMethodError at runtime |
Plugin compiled against a different Browser4 version than the host | Rebuild with matching browser4-pdk version; or reinstall the matching Browser4 version |
| JAR contains embedded dependencies | Fat JAR instead of thin JAR — spring-boot-maven-plugin with repackage goal |
Remove or skip the repackage goal; ensure only maven-jar-plugin is active |
NoClassDefFoundError for third-party libraries |
Third-party dependency not bundled in the plugin JAR | Use compile scope for third-party deps (not provided) so they are included in the JAR |
Critical Warnings
Warning: All
browser4-*and Spring Boot dependencies must use<scope>provided</scope>. Usingcompilescope causesClassNotFoundExceptionat runtime because the host application provides these classes. The plugin JAR should only bundle your own code and true third-party libraries (usecompilescope for those).
Warning: Always annotate the auto-configuration class with
@Lazy. Plugin beans depend on services that may not be available until the application context is fully initialized. Without@Lazy, startup may fail withBeanCreationException.
Warning: The
browser4-plugin.jsonmanifest and theBrowser4Plugin.manifestproperty must stay in sync. The JSON file is always required for JAR discovery; theBrowser4Plugininterface is optional. If both are present, the JSON manifest is authoritative for the plugin registry.
Warning: Event handlers run on the browser event loop. Never perform blocking I/O (HTTP calls, file writes) directly in a handler — use coroutines. For
ToolMountexecutors, the framework handles coroutine dispatch automatically.
Warning: An uncaught exception in one event handler can break the entire handler chain. Always wrap handler bodies in try-catch and log failures.
Note: For lightweight plugin development without cloning the full Browser4 repo, the
browser4-pdkparent POM extendspulsar-parentfrom Maven Central. Third-party developers only need the archetype and a Maven installation.
Tip: Build and test incrementally. After scaffolding, immediately run
mvn packageto verify the build works before writing any custom code. Then implement one mount point at a time, rebuilding and testing after each.
Tip: Read the
browser4-pdk-test-pluginsource before writing complex handlers. It demonstrates every mount point and serves as the compatibility canary.
Tip: When using
@ConditionalOnProperty, prefermatchIfMissing = trueso the plugin is enabled by default unless explicitly disabled. This matches the convention used by all first-party plugins.
Tip: The
browser4-plugins/browser4-images/plugin is the best all-around reference — it implementsBrowseEventMount+ToolMount+Browser4Pluginwith a config data class, service layer, browse event handler, and tool executor.
Reference Map
| I want to... | Read |
|---|---|
| Walk through the full plugin lifecycle (requirements → scaffold → deploy) | Step-by-Step Workflow |
| Know which files a plugin project contains and what each is for | File Reference |
| Understand default vs opt-in loading and enable overrides | Plugin Loading |
Key source files to read for patterns and examples:
| Resource | Path | What it demonstrates |
|---|---|---|
| Canonical test plugin | browser4-pdk/browser4-pdk-test-plugin/ |
All three event-phase mount points (BrowseEventMount, LoadEventMount, CrawlEventMount) — the compatibility canary |
| Plugin archetype | browser4-pdk/browser4-plugin-archetype/src/main/resources/archetype-resources/ |
Scaffolded project structure, templates for all required files |
| PluginMount interfaces | browser4-core/browser4-skeleton/src/main/kotlin/ai/platon/pulsar/skeleton/plugin/MountPoints.kt |
PluginMount, BrowseEventMount, LoadEventMount, CrawlEventMount interface definitions |
| Event lifecycle | browser4-core/browser4-skeleton/src/main/kotlin/ai/platon/pulsar/skeleton/event/PageEvents.kt |
LoadEventHandlers, BrowseEventHandlers, CrawlEventHandlers — all 28 hooks |
| Event handler types | browser4-core/browser4-skeleton/src/main/kotlin/ai/platon/pulsar/skeleton/event/EventHandlers.kt |
Chainable handler function types (WebPageWebDriverEventHandler, etc.) |
| Plugin manifest | browser4-core/browser4-skeleton/src/main/kotlin/ai/platon/pulsar/skeleton/plugin/PluginManifest.kt |
PluginManifest data class schema |
| ToolMount + registry | browser4-agentic/src/main/kotlin/ai/platon/pulsar/agentic/tools/ToolMount.kt |
ToolMount interface + CustomToolRegistry singleton |
| ToolExecutor base | browser4-agentic/src/main/kotlin/ai/platon/pulsar/agentic/tools/builtin/AbstractToolExecutor.kt |
ToolExecutor interface and AbstractToolExecutor base class |
| PDK parent POM | browser4-pdk/pom.xml |
Parent POM for plugin projects (standalone — inherits from pulsar-parent on Maven Central) |
| Plugin dev docs | docs/plugin-development.md |
Full plugin development guide with API reference |
| Most complete reference plugin | browser4-plugins/browser4-images/ |
Implements BrowseEventMount + ToolMount + Browser4Plugin + Config + Service + BrowseEventHandler + ToolExecutor — all major patterns |
| CAPTCHA plugin | browser4-plugins/browser4-captcha/ |
Reference for PageSnifferMount + multi-tool executor |
| PDK test plugin source | browser4-pdk/browser4-pdk-test-plugin/src/main/kotlin/ai/platon/pulsar/pdk/testplugin/config/TestPluginAutoConfiguration.kt |
Minimal mount-point wiring for all three event phases |
See Also
- Plugin Development Guide — Official plugin development documentation
- AGENTS.md — Project architecture, build commands, code style, and testing conventions
- PDK Test Plugin — Minimal reference plugin implementing all mount points
- Built-in Plugins — Five first-party plugin implementations (captcha, images, media, pptx, markdown)