Logging Configuration
Control PraisonAI log output from the CLI or your own scripts
from praisonaiagents import Agent
agent = Agent(
name="logged-agent",
instructions="Process tasks with full logging enabled.",
output="verbose",
)
agent.start("Run this task with detailed logging.")Control how PraisonAI logs run-time information from the CLI or your own Python scripts.
The user runs an agent with verbose logging; PraisonAI emits structured lines to stderr for debugging.
Quick Start
- CLI Users
Set
LOGLEVEL=INFO(orDEBUG) before running PraisonAI commands to see more output.bash export LOGLEVEL=INFO praisonai agents.yaml - Script Users
Call
configure_cli_logging("INFO")once at app start, or wire your ownlogging.basicConfig().python from praisonai import PraisonAI from praisonai._logging import configure_cli_logging configure_cli_logging("INFO") # opt in to root-logger setup PraisonAI(agent_file="agents.yaml").run()
How It Works
| Import Type | Root Logger Configuration | Default Level |
|---|---|---|
CLI (praisonai command) | ✅ Automatic via configure_cli_logging() | WARNING |
Library (from praisonai import) | ❌ No automatic configuration | N/A |
Configuration Options
| Option | Type | Default | Description | ||
|---|---|---|---|---|---|
LOGLEVEL env var | str | WARNING | Read by configure_cli_logging(). Accepts standard Python levels. | ||
configure_cli_logging(level) | `str \ | int \ | None` | None (uses LOGLEVEL or WARNING) | Idempotent; only the first call configures the root logger. |
get_logger(name) | `str \ | None` | None (returns praisonai) | Returns a namespaced praisonai.<name> logger; never mutates root. |
Common Patterns
Quieting PraisonAI in a Larger App
import logging
from praisonai import PraisonAI
# Set only the praisonai logger to WARNING
logging.getLogger("praisonai").setLevel(logging.WARNING)
# Your app's logging remains untouched
praisonai = PraisonAI(agent_file="agents.yaml")
praisonai.run()Routing PraisonAI Logs to a File
import logging
from praisonai import PraisonAI
# Create file handler for praisonai logs only
handler = logging.FileHandler("praisonai.log")
handler.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(message)s"))
# Attach to praisonai logger tree
praisonai_logger = logging.getLogger("praisonai")
praisonai_logger.addHandler(handler)
praisonai_logger.setLevel(logging.INFO)
praisonai = PraisonAI(agent_file="agents.yaml")
praisonai.run()One-off CLI Debugging
# Debug a specific run
LOGLEVEL=DEBUG praisonai agents.yaml
# Back to quiet mode
praisonai agents.yamlImport-time behaviour (PR #5219)
import praisonaiagents no longer overwrites host environment variables or silences the host’s asyncio logger.
Reference: PraisonAI PR #5219, fixes #5162. For the full fork-safety story, see Python Import Safety & Fork Behaviour.
Environment variables: setdefault, not overwrite
praisonaiagents._logging._configure_environment() now uses os.environ.setdefault(key, value) instead of an unconditional assignment. A value the host exported before launch is preserved and no longer leaks a different value into any subprocess spawned afterwards.
# The host sets LITELLM_LOG before launching your script.
export LITELLM_LOG=DEBUG
python my_script.py # imports praisonaiagentsimport os
from praisonaiagents import Agent # env defaults applied when the LLM layer loads
# The host's DEBUG value is kept — setdefault does not overwrite it.
assert os.environ["LITELLM_LOG"] == "DEBUG"When the host has not set a value, the SDK still fills these in once praisonaiagents.llm is imported (since PR #6135, not on bare import praisonaiagents):
| Variable | Default set when unset |
|---|---|
LITELLM_TELEMETRY | False |
LITELLM_DROP_PARAMS | True |
LITELLM_LOG | ERROR |
LITELLM_DEBUG | False |
LITELLM_SUPPRESS_DEBUG_INFO | True |
LITELLM_VERBOSE | False |
LITELLM_SET_VERBOSE | False |
HTTPX_DISABLE_WARNINGS | True |
HTTPX_LOG_LEVEL | ERROR |
PYDANTIC_WARNINGS_ENABLED | False |
asyncio logger is no longer suppressed
"asyncio" has been removed from the SDK’s noisy-logger list, so import praisonaiagents no longer forces logging.getLogger("asyncio") to CRITICAL or clears its handlers. Host application asyncio errors — Task exception was never retrieved, coroutine-scheduling failures, and similar — surface again as your own logging config intends.
If you relied on the old import-time behaviour to hide those messages, set the level yourself in your own code:
import logging
import praisonaiagents # no longer touches the asyncio logger
# Opt back into suppression explicitly if you want it.
logging.getLogger("asyncio").setLevel(logging.CRITICAL)When the host has already configured logging
The SDK detects host-installed root handlers and leaves logging alone — your Django/FastAPI/gunicorn setup is preserved as-is.
import logging
logging.basicConfig(level=logging.INFO, format="%(levelname)s %(name)s %(message)s")
from praisonaiagents import Agent # root handlers, level, and httpx/openai loggers untouched
agent = Agent(instructions="You are a helpful assistant")
agent.start("Hello")Since PR #6135, the SDK’s logger setup checks logging.getLogger().handlers first and returns early if any handler exists. force=True was removed, so basicConfig no longer replaces host handlers. LOGLEVEL and noisy-logger silencing only apply when the host has not configured logging.
See Python Import Safety → Host logging, warnings, and env on import for the related warnings.warn and env guarantees.
Best Practices
Use namespaced loggers in library code
Always use get_logger("module") instead of the root logger when writing library code.
from praisonai._logging import get_logger
logger = get_logger("mymodule") # Creates praisonai.mymodule logger
logger.info("This won't interfere with the user's logging")Do not call basicConfig from libraries
Libraries should never call logging.basicConfig() as it mutates global state. Let applications control their logging setup.
# ❌ Bad - mutates global logger
import logging
logging.basicConfig(level=logging.INFO)
# ✅ Good - use namespaced logger
from praisonai._logging import get_logger
logger = get_logger("mylibrary")Prefer LOGLEVEL for one-shot debugging
Use the environment variable for temporary debugging instead of changing code.
# Quick debug session
LOGLEVEL=DEBUG praisonai agents.yaml
# Production run
praisonai agents.yamlAttach handlers to praisonai not root
When customizing PraisonAI logging, attach handlers to the praisonai logger tree rather than the root logger.
import logging
# ✅ Good - only affects praisonai
praisonai_logger = logging.getLogger("praisonai")
praisonai_logger.addHandler(my_handler)
# ❌ Bad - affects all logging
root_logger = logging.getLogger()
root_logger.addHandler(my_handler)