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.
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.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 See Runtime Resolution β Background cleanup thread.
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.What is still not safe on import
PR #5219 intentionally kept two behaviours. Be honest with your host application about them.Root logger is still reconfigured (basicConfig force=True)
Root logger is still reconfigured (basicConfig force=True)
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 is still monkeypatched
warnings.warn is still monkeypatched
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 noresolve_runtime call happens before the fork, no daemon thread is cloned into a child in an undefined state.
- gunicorn (pre-fork)
- multiprocessing.Process
- ProcessPoolExecutor
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
Import at the parent, resolve in the child
Import at the parent, resolve in the child
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.Configure host logging after importing PraisonAI
Configure host logging after importing PraisonAI
basicConfig(force=True) still runs at import. Import the SDK first, then attach your own handlers so they survive.Set env vars before launch to keep them
Set env vars before launch to keep them
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.Re-suppress asyncio yourself if you need it
Re-suppress asyncio yourself if you need it
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.Related
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

