External Provider Packages¶
External adapter packages can register WorldForge providers without modifying the WorldForge
repository. WorldForge discovers them at construction time through the
worldforge.providers Python entry-point group.
Entry-point declaration¶
Add an entry to your package's pyproject.toml:
The entry-point name (my-policy) is the provider name WorldForge will surface in
providers(), doctor(), and benchmark/evaluation reports. The value
(my_pkg.adapters:make_my_policy_provider) is a fully qualified callable that returns a
:class:~worldforge.providers.base.BaseProvider.
Factory contract¶
The referenced callable takes one optional keyword argument and returns a BaseProvider:
from worldforge.providers import BaseProvider, ProviderProfileSpec
from worldforge import ProviderCapabilities
def make_my_policy_provider(*, event_handler=None) -> BaseProvider:
return MyPolicyProvider(event_handler=event_handler)
Three rules:
- The provider's
nameattribute must equal the entry-point name. WorldForge raisesWorldForgeErrorfromProviderCatalogEntry.create()when they disagree, which prevents accidental name collisions in user-facing output. - The factory must return a
BaseProvidersubclass. Returning anything else is rejected with a typed error when the entry is invoked. - The provider follows the same env-gated auto-registration rules as in-repo providers:
configured()must returnTruefor the provider to be auto-registered. Hosts can still register an unconfigured provider explicitly viaforge.register_provider(...).
Contract CLI¶
Run the provider contract CLI before opening an issue or PR for an external adapter:
uv run worldforge provider contract my-policy --format json
uv run worldforge provider contract --factory my_pkg.adapters:make_my_policy_provider --format markdown
The command accepts either a registered provider name or a direct module:factory path. It emits
safe-to-attach JSON or Markdown evidence with provider metadata, passed checks, skipped host-owned
checks, failures, next steps, and validation commands.
WorldForge does not call non-local provider capabilities by default. A configured remote, robotics,
or optional-runtime provider records those capability checks as skipped until the host reruns with
--live on a prepared machine. Use --score-info, --score-candidates, and
--policy-info when a score or policy adapter needs provider-native fixture payloads.
Failure behaviour¶
Discovery never crashes the host. Each entry-point that cannot be wrapped is recorded with a typed reason:
| Cause | Example reason |
|---|---|
| Module import fails (missing optional dependency) | missing dependency: No module named 'torch' |
| Loaded value is not callable | entry point did not resolve to a callable |
| Name collides with an in-repo provider | duplicate name (in-repo provider already registered) |
| Two entry points share a name | duplicate name (already discovered earlier in this group) |
| Loader raises any other exception | load failed: <message> |
| Factory raises at construction time | factory raised: <message> |
The full report lives on WorldForge.entry_point_discovery():
from worldforge import WorldForge
forge = WorldForge()
report = forge.entry_point_discovery()
print(report.discovered_count, "external providers discovered")
for skip in report.skipped:
print(f"skipped {skip.name}: {skip.reason}")
Checkout-safe package demo¶
Run the demo workflow when you want a complete package-shape example without publishing or installing anything globally:
uv run python scripts/demo_showcases.py run external-provider-package --workspace-dir .worldforge/demo-showcases --overwrite
It writes a temp package under the demo workspace with a pyproject.toml, provider factory, and
package-local test. The preserved external-provider-discovery.json shows successful discovery,
explicit disabled-discovery behavior, duplicate in-repo provider-name handling, and a missing
optional dependency skip reason. The output is safe to attach, but it is package-shape evidence
only; it is not PyPI publishing, a live provider call, or promotion evidence.
Disabling discovery¶
Two switches turn discovery off:
- Constructor flag:
WorldForge(discover_entry_points=False)skips discovery entirely. - Environment variable: setting
WORLDFORGE_DISABLE_ENTRY_POINTSto a non-empty value has the same effect for all forges in the process. Hosted environments use this to keep CI runs deterministic when third-party packages are installed for unrelated reasons.
When discovery is disabled, forge.entry_point_discovery().enabled is False and no
external providers are registered.
Stability¶
This surface is provisional. The entry-point group name and discovery report shape are
stable for the current release, but EntryPointSkip.reason strings are human-readable
diagnostics rather than a machine-parseable contract. Treat them like log messages.
Related public API¶
| Symbol | Purpose |
|---|---|
worldforge.ENTRY_POINT_GROUP |
The entry-point group name (worldforge.providers). |
worldforge.ENTRY_POINT_DISABLE_ENV_VAR |
Name of the disable env var. |
worldforge.discover_entry_point_providers |
Run discovery without instantiating a forge. |
worldforge.EntryPointDiscoveryReport |
Frozen dataclass with the run summary. |
worldforge.EntryPointSkip |
One skip record (name, value, reason). |
WorldForge.entry_point_discovery() |
The report captured at construction time. |