Skip to main content
import praisonaiagents spawns no background thread, preserves host environment variables via setdefault, and leaves the host asyncio logger untouched β€” so it is safe to import at the parent of a pre-fork server before workers fork.
The user imports the SDK inside a gunicorn master or a multiprocessing parent; nothing starts a daemon thread or corrupts the environment before workers fork. Reference: PraisonAI PR #5219, fixes #5162. This is the Python companion to JS Import Safety & Runtimes.

What’s safe on import (after PR #5219)

Three import-time side effects that used to corrupt the host process are gone.
1

Host environment variables are preserved

praisonaiagents._logging._configure_environment() uses os.environ.setdefault(key, value). A value the host exported before launch (LITELLM_LOG, LITELLM_TELEMETRY, PYDANTIC_WARNINGS_ENABLED, and the rest) is kept β€” and no longer leaks a different value into subprocesses spawned afterwards.
See Logging Configuration β†’ Environment variables: setdefault, not overwrite for the full variable list.
2

The asyncio logger is left alone

"asyncio" was removed from the SDK’s noisy-logger list. Import no longer forces logging.getLogger("asyncio") to CRITICAL, so host asyncio errors (Task exception was never retrieved, scheduling failures) continue to surface.
3

No cleanup thread is spawned at import

The runtime/resolve.py cleanup daemon starts lazily on the first cache write β€” inside resolve_runtime under _runtime_cache_lock β€” not at module import. A bare import praisonaiagents or a touch of runtime.SessionContext spawns nothing, which is exactly the guarantee pre-fork server deployments need.
See Runtime Resolution β†’ Background cleanup thread.

What is still not safe on import

PR #5219 intentionally kept two behaviours. Be honest with your host application about them.
praisonaiagents still calls logging.basicConfig(force=True) at import. If your host configured logging before importing PraisonAI, its handler is closed and replaced.Workaround: import PraisonAI first, then configure your own logging β€” or accept the SDK’s default config.
warnings.warn and warnings.warn_explicit remain patched to suppress a hardcoded pattern list plus any UserWarning mentioning β€œpydantic”. Your own warnings matching those patterns will be swallowed.Workaround: save the originals yourself before importing, or reinstate them from the module (verify the attribute name in _warning_patch.py at head β€” the originals are stored as _original_warn / _original_warn_explicit).

Fork-safety guide

Import at the parent, then fork β€” as long as no resolve_runtime call happens before the fork, no daemon thread is cloned into a child in an undefined state.
Before PR #5219 the import-time cleanup thread was cloned into every child at fork() in an undefined state β€” a known cause of hangs and duplicate cache eviction under gunicorn pre-fork workers, multiprocessing.Process, and Celery prefork. After PR #5219, importing at the parent is safe as long as no resolve_runtime call happens before fork.

Best Practices

Under a pre-fork server, keep import praisonaiagents in the master and let the first agent.start() / resolve_runtime happen inside each worker. The lazy cleanup daemon then starts per-worker, never in the master.
basicConfig(force=True) still runs at import. Import the SDK first, then attach your own handlers so they survive.
Export LITELLM_LOG, LITELLM_TELEMETRY, and friends in your shell / systemd / Docker before the process starts. setdefault preserves them and never leaks a different value into subprocesses.
Import no longer silences the asyncio logger. If you want the old quiet behaviour, call logging.getLogger("asyncio").setLevel(logging.CRITICAL) in your own code.

Import Safety (JS)

JavaScript companion β€” no dotenv side effects on import

Logging Configuration

setdefault env vars and the untouched asyncio logger

Runtime Resolution

Lazy cleanup-thread start and fork safety

Thread Safety

Output-singleton locks and concurrent agent guarantees