Skip to main content
The user runs generation with a custom adapter registry so tenants or tests stay isolated. Inject a custom adapter registry when you need tenant isolation, parallel test safety, or per-run plugin overrides.

Quick Start

1

Simple Usage

Use the process-default registry for normal applications:
2

With Configuration

Inject a custom registry for tenant isolation or testing:

How It Works

All plugin registries expose Registry.default() or get_default_registry() unless noted. When a SandboxConfig’s sandbox_type is unknown to the built-in list, SandboxManager now resolves it through praisonai.sandbox._registry automatically — no manual registry.resolve() call is needed for typical use.

Common Patterns

Multi-tenant isolation

Test isolation

Family-alias adapters now honour your registry. The AutoGen family router (framework: autogen) resolves variants through the owning registry — the one that constructed it — so a tenant-scoped FrameworkAdapterRegistry sees your autogen_v2 / autogen_v4 / ag2 registrations even when callers use the family alias. Before this fix, only direct aliases (autogen_v2 etc.) honoured the injected registry; the family alias silently reached into the process-default registry. See AutoGen with PraisonAI.
The resolve_or_default() policy now covers every wrapper entry point. In addition to AgentsGenerator, the following surfaces used to fall back to a hardcoded "praisonai" and now consult the registry:
  • Jobs API — POST /api/v1/runs (praisonai.jobs.router) and job execution (praisonai.jobs.executor)
  • Scheduler — praisonai.scheduler.yaml_loader (framework recorded in scheduler-YAML)
  • Workflow YAMLs — the observability session tag and the cli_backend compatibility check in AgentsGenerator’s workflow paths
  • Workflow helper — framework_adapters.workflow_framework.framework_from_config() (now accepts an optional registry= kwarg)
These entry points use the process-default registry by default (get_default_registry()). To make them respect a tenant/test registry in code you control, either swap the process default before the entry point is exercised, or pass a custom registry to the class that owns the entry point (e.g. AgentsGenerator(adapter_registry=...), framework_from_config(cfg, registry=...)). See PraisonAI PR #5039 for the full migration.If your tenant registry only registers crewai, AgentsGenerator(framework=None, adapter_registry=tenant_registry) now picks crewai (previously it errored, because "praisonai" was not registered). See Default Framework Selection.

Custom default via the injected registry

Omit framework= and the resolved backend comes from your registry’s pick_default():

AutoGenerator with custom registry

After construction, AutoGenerator retains the resolved adapter as self._adapter (mirroring AgentsGenerator.framework_adapter), and self.framework is derived from adapter.name — the authoritative name, not the raw constructor argument. This is a stable observable side effect; the underscore prefix marks it private-by-convention, so treat the attribute name itself as an implementation detail.

Injecting a tool-timeout executor

Like adapter_registry=, the tool_timeout_executor= constructor parameter lets you supply a shared thread-pool instead of letting each AgentsGenerator lazily create its own.
The injected executor is treated as borrowed — gen.close() and exiting the with block will not shut it down. You stay responsible for shared_pool.shutdown().

Best Practices

Accept registries as parameters rather than calling defaults inside helpers:
Registry operations are thread-safe, but adapter instances may not be. Prefer one registry per worker or test case.
Custom registries add complexity. Reach for DI only when you need tenant overrides, test isolation, or sandboxed experimental adapters.

Framework Adapter Plugins

Extend PraisonAI with custom execution frameworks

Bot Platform Plugins

Add custom messaging platforms via entry points