ToolSourceRegistry lets a Python package expose new tool-resolution sources through the praisonai.tool_sources entry-point group — no subclassing, no monkey-patching.
Quick Start
How It Works
Resolution walks the built-in chain first (localtools.py, wrapper registry, praisonaiagents.tools, praisonai-tools, core SDK registry), then each ToolSource from ToolSourceRegistry. Entry-point sources are appended to the built-in chain — they extend rather than replace it. When you pass sources= explicitly, entry-point sources are not appended; you fully own the chain.
Building a Tool Source Plugin
Implement the ToolSource protocol
Register the entry point in pyproject.toml
- a
ToolSourceclass (instantiated once —CorpToolsSource), - a factory function returning a
ToolSourceinstance, or - an already-constructed
ToolSourceinstance.
Ship it
Afterpip install, the source is live in every ToolResolver that uses the process-default registry (or any resolver you construct with a registry that discovers entry points).
Configuration Options
| Option | Where | Type | Default | Description |
|---|---|---|---|---|
source_registry | ToolResolver(...) constructor | Optional[ToolSourceRegistry] | Process-default registry (lazy) | Registry supplying third-party entry-point tool sources. Pass an empty registry to opt out. |
discover_entry_points | ToolSourceRegistry(...) constructor | bool | True | When False, the registry does not scan the praisonai.tool_sources entry-point group on construction. Use for tests or a hard opt-out. |
Common Patterns
- Opt out of third-party sources
- Isolate a plugin for a specific tenant
- Deterministic tests
Safety
- A plugin that raises during loading is logged and skipped — resolution never breaks for other callers.
- A plugin that resolves to an object not matching the
ToolSourceprotocol (missingname: stror callablelookup) is rejected with aTypeErrorinside_coerce_sourceand skipped — it never gets appended to the chain. - Behaviour is covered by
test_misbehaving_plugin_is_skippedandtest_invalid_shape_plugin_is_skippedin the SDK test suite.
Best Practices
Namespace your tool names
Namespace your tool names
Use a prefix like
corp. so plugin tools do not collide with built-in names.Return None fast for names you do not own
Return None fast for names you do not own
lookup() runs in chain order; bail out quickly when a name is not yours.Never raise from lookup() for expected misses
Never raise from lookup() for expected misses
Raise only for genuine errors — the registry logs and skips your source on failure, so a raise looks like a broken plugin.
Register a class, not an instance, when the source is cheap to build
Register a class, not an instance, when the source is cheap to build
Avoids stale process-wide state in long-running services.
Related
Tool Resolver
Single source of truth for loading tools
Persistence Backend Plugins
Same PluginRegistry pattern for stores
Framework Adapter Plugins
Entry-point plugins for execution frameworks
Registry Dependency Injection
Registry DI pattern across the wrapper

