Skip to main content
import praisonaiagents spawns no background thread, leaves host environment variables alone, preserves host logging handlers, and never replaces warnings.warn — so it is safe to import inside an existing app or 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) and PR #6135 (fixes #6134). 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.

Host logging, warnings, and env on import (PR #6135)

PR #6135 removed the last import-time changes to host process state.
1

Root logger is left alone if the host configured it

logging.basicConfig(..., force=True) is gone. If the root logger already has a handler, import leaves the root handler list and level unchanged. See Logging Configuration → When the host has already configured logging.
2

Host httpx / openai / pydantic loggers are kept

When the host has configured logging, import no longer clears handlers or propagate on httpx, httpcore, openai.*, pydantic, or markdown_it loggers.
3

warnings.warn is never replaced

warnings.warn and warnings.warn_explicit are no longer monkey-patched. Noisy third-party warnings are silenced with scoped warnings.filterwarnings(...) entries only, so warnings.warn is the same object before and after import.
4

Env defaults wait for the LLM layer

LITELLM_*, HTTPX_*, and PYDANTIC_* defaults are applied when praisonaiagents.llm is imported — not on import praisonaiagents. Subprocesses the host spawns before using the LLM path inherit an unchanged environment. Values are still applied with setdefault.
Verify the invariant yourself:
The full assertion set lives in tests/unit/test_import_side_effects.py.

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.
If your app installs root handlers before importing PraisonAI, the SDK leaves them alone. If it imports PraisonAI first, attach your handlers afterwards as usual.
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

Host-configured logging is preserved on import

Runtime Resolution

Lazy cleanup-thread start and fork safety

Thread Safety

Output-singleton locks and concurrent agent guarantees