Optional Dependencies Check

How praisonai doctor env –deep probes optional packages — available, missing, broken, or slow

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.

Diagram

praisonai doctor env –deep

8 daemon threads\none per optional package

per-package gate\nmax(1.0, min(3.0, timeout/4))

available

missing

broken

slow

How It Works

Diagram
OptionalDependenciesCheckAgentUserOptionalDependenciesCheckAgentUserRequestProcessResultResponse

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:

    python
    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?")
    bash
    # 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:

    bash
    praisonai doctor env --deep --json > deps.json

    The metadata object contains one list per bucket:

    json
    {
      "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

Diagram
Optional DependenciesAgentUserOptional DependenciesAgentUserRequestProcess requestResultResponse

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): {names}”
slowImport didn’t finish inside per-package timeoutPASSRetry with a higher --timeout; skip if it’s a known-slow package

Broken praisonaiagents Install Surfaces the Real Import Error

Accessing anything exported through praisonai (for example from praisonai import Agent) points straight at a broken dependency instead of hiding it.

When the praisonaiagents package is installed but fails to import — typically a transitive dependency version conflict — the error now reads:

AttributeError: module 'praisonai' has no attribute 'Agent': praisonaiagents is installed but failed to import (<real ImportError message>)

The underlying exception is chained via __cause__ and cached, so the failing import is not retried on every lookup. Previously the same situation surfaced as a plain AttributeError that hid the real root cause; now the message points straight at the broken dependency.

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.

Diagram

–timeout N

N / 4

min(3.0, …)

max(1.0, …)

per-package deadline

--timeoutPer-package deadlineAggregate cap
10 (default)2.5s8.0s
203.0s16.0s
41.0s3.2s

Why Daemon Threads


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:

bash
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:

bash
praisonai doctor env --deep --timeout 20

Run only the optional deps check:

bash
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.

jsonc
{
  "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:

bash
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 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

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

pip install --force-reinstall <package> clears a broken C-extension cache.


Related