praisonai doctor env --deep probes eight optional packages in parallel and reports each as available, missing, broken, or slow — no single hanging import can stall the check.
How It Works
Quick Start
Check before wiring up knowledge features
An agent that uses
chromadb for RAG will fail at runtime if the package is broken. Run the check first:How It Works
The Four Outcome Buckets
Each optional package lands in exactly one bucket per run:| Bucket | When | Status | Remediation |
|---|---|---|---|
available | Import succeeded | PASS | — |
missing | ImportError — package not installed | PASS | Install the package if you need that feature |
broken | Import raised a non-ImportError (broken C extension, missing shared object) | WARN | ”Reinstall the broken optional package(s): “ |
slow | Import didn’t finish inside per-package timeout | PASS | Retry with a higher --timeout; skip if it’s a known-slow package |
A
broken result is distinct from missing: the package is installed but its import fails with a non-ImportError (e.g. a corrupted C extension). The check surfaces this as WARN rather than masking it as “not installed” — which would misleadingly tell users to install a package that is already there.The Eight Optional Packages
| Package | Feature area |
|---|---|
chromadb | Knowledge/RAG features |
mem0ai | Memory features |
litellm | Multi-provider LLM support |
praisonaiui | aiui (Chat/Dashboard UI) |
gradio | Gradio UI |
crawl4ai | Web crawling |
tavily | Tavily search |
duckduckgo_search | DuckDuckGo search |
Per-Package Timeout
Each import runs on its own daemon thread with an individual deadline computed from the global--timeout:
--timeout 10, each package gets 2.5 seconds. The overall aggregate deadline is max(per_package_timeout, config.timeout * 0.8) — the check never exceeds 80% of the engine budget.
--timeout | Per-package deadline | Aggregate cap |
|---|---|---|
| 10 (default) | 2.5s | 8.0s |
| 20 | 3.0s | 16.0s |
| 4 | 1.0s | 3.2s |
Why Daemon Threads
Daemon threads (rather than a
ThreadPoolExecutor) are used deliberately: a pool’s worker threads are joined by its internal atexit handler at interpreter shutdown even after shutdown(wait=False), so a truly hanging import would still stall CLI exit. Daemon threads are abandoned on exit, so a hanging import can never block the process from terminating.Configuration Options
| Flag | Description |
|---|---|
--deep | Enable deeper probes, including the optional_deps parallel import check |
--timeout SEC | Global timeout in seconds (default: 10). Per-package deadline: max(1.0, min(3.0, timeout/4)) |
--json | Output in JSON format for CI gating |
--only optional_deps | Run only the optional deps check |
--skip optional_deps | Skip the optional deps check |
Common Patterns
Gate CI on broken packages only:CI/JSON Output
Gate CI onmetadata.broken being empty. A broken install is actionable; a missing install often is not.
broken list in a shell script:
Best Practices
Gate CI on broken, not missing
Gate CI on broken, not missing
Gate CI on
metadata.broken being empty — a broken install is actionable, a missing install often isn’t.Handle slow packages in short-timeout environments
Handle slow packages in short-timeout environments
If a package repeatedly lands in
slow, raise --timeout or skip the entire check with --skip optional_deps in short-timeout environments.Reinstall a broken package
Reinstall a broken package
pip install --force-reinstall <package> clears a broken C-extension cache.Related
Doctor CLI
Full reference for praisonai doctor health checks and subcommands
Doctor CLI Reference
CLI command reference for all doctor subcommands
Runtime Config Migration
Detect and migrate legacy cli_backend fields with praisonai doctor runtime
Vector Store
chromadb-backed vector storage for knowledge and RAG features

