Skip to main content
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

1

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:
from praisonaiagents import Agent

agent = Agent(
    name="Knowledge Assistant",
    instructions="Answer using indexed documents.",
    knowledge=["docs/manual.pdf"],   # requires chromadb
)
agent.start("How do I configure auth?")
# Confirm chromadb is present before wiring up knowledge features
praisonai doctor env --deep
2

CI/CD — capture the JSON report

Export the structured result so CI can gate on specific buckets:
praisonai doctor env --deep --json > deps.json
The metadata object contains one list per bucket:
{
  "id": "optional_deps",
  "status": "WARN",
  "message": "5 optional packages available, 2 not installed, 1 broken",
  "details": "Missing: gradio (Gradio UI), tavily (Tavily search); Broken install: chromadb (Knowledge/RAG features)",
  "remediation": "Reinstall the broken optional package(s): chromadb (Knowledge/RAG features)",
  "metadata": {
    "available": ["mem0ai", "litellm", "praisonaiui", "crawl4ai", "duckduckgo_search"],
    "missing":   ["gradio (Gradio UI)", "tavily (Tavily search)"],
    "broken":    ["chromadb (Knowledge/RAG features)"],
    "slow":      []
  }
}

How It Works

The Four Outcome Buckets

Each optional package lands in exactly one bucket per run:
BucketWhenStatusRemediation
availableImport succeededPASS
missingImportError — package not installedPASSInstall the package if you need that feature
brokenImport raised a non-ImportError (broken C extension, missing shared object)WARN”Reinstall the broken optional package(s):
slowImport didn’t finish inside per-package timeoutPASSRetry 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

PackageFeature area
chromadbKnowledge/RAG features
mem0aiMemory features
litellmMulti-provider LLM support
praisonaiuiaiui (Chat/Dashboard UI)
gradioGradio UI
crawl4aiWeb crawling
tavilyTavily search
duckduckgo_searchDuckDuckGo search

Per-Package Timeout

Each import runs on its own daemon thread with an individual deadline computed from the global --timeout:
per_package_timeout = max(1.0, min(3.0, config.timeout / 4))
With the default --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.
--timeoutPer-package deadlineAggregate cap
10 (default)2.5s8.0s
203.0s16.0s
41.0s3.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

FlagDescription
--deepEnable deeper probes, including the optional_deps parallel import check
--timeout SECGlobal timeout in seconds (default: 10). Per-package deadline: max(1.0, min(3.0, timeout/4))
--jsonOutput in JSON format for CI gating
--only optional_depsRun only the optional deps check
--skip optional_depsSkip the optional deps check

Common Patterns

Gate CI on broken packages only:
praisonai doctor env --deep --json > deps.json
broken=$(python3 -c "import json; d=json.load(open('deps.json')); print(len(d.get('results',[{}])[0].get('metadata',{}).get('broken',[])))" 2>/dev/null || echo "0")
[ "$broken" -gt "0" ] && { echo "Broken optional packages — see deps.json"; exit 1; }
Raise per-package timeout for slow environments:
praisonai doctor env --deep --timeout 20
Run only the optional deps check:
praisonai doctor env --deep --only optional_deps

CI/JSON Output

Gate CI on metadata.broken being empty. A broken install is actionable; a missing install often is not.
{
  "id": "optional_deps",
  "status": "WARN",
  "message": "5 optional packages available, 2 not installed, 1 broken",
  "details": "Missing: gradio (Gradio UI), tavily (Tavily search); Broken install: chromadb (Knowledge/RAG features)",
  "remediation": "Reinstall the broken optional package(s): chromadb (Knowledge/RAG features)",
  "metadata": {
    "available": ["mem0ai", "litellm", "praisonaiui", "crawl4ai", "duckduckgo_search"],
    "missing":   ["gradio (Gradio UI)", "tavily (Tavily search)"],
    "broken":    ["chromadb (Knowledge/RAG features)"],
    "slow":      []
  }
}
Check the broken list in a shell script:
praisonai doctor env --deep --json > deps.json
broken=$(python3 -c "import json,sys; d=json.load(open('deps.json')); print(len(d.get('results',[{}])[0].get('metadata',{}).get('broken',[])))" 2>/dev/null || echo "0")
if [ "$broken" -gt "0" ]; then
  echo "Broken optional packages detected — check deps.json for remediation"
  exit 1
fi

Best Practices

Gate CI on metadata.broken being empty — a broken install is actionable, a missing install often isn’t.
If a package repeatedly lands in slow, raise --timeout or skip the entire check with --skip optional_deps in short-timeout environments.
pip install --force-reinstall <package> clears a broken C-extension cache.

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