Integration Registry
Add custom CLI / managed-agent / hosted-agent integrations via Python entry points
from praisonai.integrations import ClaudeCodeIntegration
integration = ClaudeCodeIntegration(workspace="/path/to/project")
result = await integration.execute("Refactor this module")Import any built-in or plugin-registered integration straight from praisonai.integrations — a static export map serves built-ins, and the praisonai.integrations entry-point group adds third-party names.
Integration Registry lets third-party developers add custom CLI tools, managed agents, and agent backends to PraisonAI, importable from a single module.
Choose Your Registration Path
Pick a path based on how the integration ships.
Quick Start
- Use a built-in integration
python from praisonai.integrations import ClaudeCodeIntegration integration = ClaudeCodeIntegration(workspace="/path/to/project") - Distribute as a pip plugin
toml # your-plugin/pyproject.toml [project.entry-points."praisonai.integrations"] acme = "acme_praison:AcmeIntegration"python # after `pip install your-plugin` — no praisonai code changes needed from praisonai.integrations import acme integration = acme(workspace="/path/to/project")The left-hand side (
acme) is the name users import; the right-hand side is the dotted path to the class. Names that collide with a built-in are ignored — built-ins always win.
How It Works
__getattr__onpraisonai.integrationsfirst checks the static_STATIC_EXPORTSmap (name -> "module:attr"), lazily importing the owning module on first access.- If the name isn’t a built-in, it’s looked up in the
praisonai.integrationsentry-point group andep.load()-ed. - Unknown names raise
AttributeError(native Python behaviour). - Dunder / underscore-prefixed submodule names (e.g.
from praisonai.integrations import base) fall through to normal import machinery.
Precedence
Built-ins always win because they are served by _STATIC_EXPORTS before the entry-point lookup runs. A plugin may only add names, never replace a shipped one.
| Source | When resolved | On name collision |
|---|---|---|
Built-in (_STATIC_EXPORTS) | Checked first in __getattr__ | Wins — plugin never consulted |
| Third-party entry-point plugin | Only if no static-map hit | Cannot shadow a built-in |
Available built-in names
Every key below imports directly: from praisonai.integrations import <name>.
CLI Tools
BaseCLIIntegration— base class for CLI toolsCLIExecutionError— CLI execution error classget_available_integrations— list available integrationsClaudeCodeIntegration— Claude Code CLIGeminiCLIIntegration— Gemini CLICodexCLIIntegration— Codex CLICursorCLIIntegration— Cursor CLI
Managed Agents
ManagedAgent(aliasManagedAgentIntegration) — managed agent interfaceAnthropicManagedAgent— Anthropic managed agentManagedConfig(aliasManagedBackendConfig) — managed agent configuration
Local & Sandboxed Agents
LocalManagedAgent— local managed agentLocalManagedConfig— local agent configurationSandboxedAgent— sandboxed agent executionSandboxedAgentConfig— sandboxed agent configuration
Agent Backends
HostedAgent— hosted agent backendHostedAgentConfig— hosted agent configurationLocalAgent— local agent backendLocalAgentConfig— local agent configuration
Registry Functions
ExternalAgentRegistry— external agent registry (typed source of truth for--external-agent)get_registry— get the external-agent registryregister_integration— register a new integrationcreate_integration— create an integration instance
Typed backend registries
The two typed registries are unchanged by #4651 and remain the sources of truth for their surfaces:
| Registry | Surface it drives |
|---|---|
ExternalAgentRegistry | the --external-agent CLI short names |
ManagedBackendRegistry | the run_on= kwarg |
Use these when you need typed enumeration of backends rather than plain module importability.
Migration from the old registry
The internal registry surfaces removed in PR #4651 no longer exist. Update any code that touched them:
| Removed | Replacement |
|---|---|
from praisonai.integrations._unified_registry import get_integrations_registry | from praisonai.integrations import <name> (still works for every built-in and plugin) |
INTEGRATIONS_REGISTRY module attribute | none — import the name you need directly |
IntegrationRegistry class | none — built-ins served by _STATIC_EXPORTS, plugins via the entry-point group |
registry.get_by_attr(module, attr) | getattr(praisonai.integrations, attr) / a normal import |
| Typed backend enumeration | ExternalAgentRegistry / ManagedBackendRegistry |
# ❌ Before (removed)
from praisonai.integrations._unified_registry import get_integrations_registry
cls = get_integrations_registry().get_by_attr(__name__, "ClaudeCodeIntegration")
# ✅ After
from praisonai.integrations import ClaudeCodeIntegrationAdvanced Usage
Adding a new built-in backend
Built-in CLI backends (Claude Code, Gemini, Codex, Cursor) are registered from a single canonical module: praisonai/integrations/_cli_loaders.py. It exports BUILTIN_INTEGRATIONS (short-alias → loader) used by ExternalAgentRegistry. Register a new built-in there and add the class to _STATIC_EXPORTS in praisonai/integrations/__init__.py to make it importable.
Build your own namespace
Use create_lazy_getattr(registry) from praisonai._registry to give your own package the same lazy-loading + entry-point dispatch behaviour:
# my_pkg/__init__.py
from praisonai._registry import PluginRegistry, create_lazy_getattr
_REG = PluginRegistry(entry_point_group="my_pkg.plugins")
__getattr__ = create_lazy_getattr(_REG)PluginRegistry.has(name) -> bool (added in #4651) is a cheap, load-free membership check you can use before triggering a lazy import.
Best Practices
Import from the package root, not submodules
Use the public surface so you get built-in-vs-plugin resolution:
# ✅ Good
from praisonai.integrations import ClaudeCodeIntegration
# ❌ Bad — internal module path, not the public API
from praisonai.integrations.claude_code import ClaudeCodeIntegrationNever reuse a built-in name
Built-ins are served by _STATIC_EXPORTS before the entry-point lookup runs, so a plugin sharing a built-in name is never reached. Pick a name unique to your package.
Prefer typed registries for enumeration
When you need to list backends (not just import one), use ExternalAgentRegistry / ManagedBackendRegistry — they own the --external-agent and run_on= surfaces.
Upgrade for entry-point discovery
Plugin discovery needs PR #4154 or later. On older releases, only built-ins resolve.