> ## Documentation Index
> Fetch the complete documentation index at: https://praison.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Framework Availability Detection

> Thread-safe, cached framework availability checking for PraisonAI adapters

Check whether optional frameworks and dependencies are installed before you run agents or YAML workflows.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent

agent = Agent(name="assistant", instructions="You are a helpful assistant.")
agent.start("Run my task once a framework is available.")
```

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonai import PraisonAI

# PraisonAI picks the first available framework automatically
praison = PraisonAI(agent_file="agents.yaml")
praison.run()
```

The user runs YAML without naming a framework; PraisonAI probes installed adapters and picks the first available.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    subgraph "Framework Availability Detection"
        Check[🔍 Check Request] --> Cache{💾 Cached?}
        Cache -->|Hit| Result[✅ Return Result]
        Cache -->|Miss| Probe[🔬 Probe Import]
        Probe --> Store[💾 Store Result]
        Store --> Result
    end

    classDef input fill:#6366F1,stroke:#7C90A0,color:#fff
    classDef process fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef output fill:#10B981,stroke:#7C90A0,color:#fff

    class Check input
    class Cache,Probe,Store process
    class Result output

```

## How It Works

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
sequenceDiagram
    participant User
    participant Agent
    participant Feature as Framework Availability Detection

    User->>Agent: Request
    Agent->>Feature: Process request
    Feature-->>Agent: Result    Agent-->>User: Response
```

## Quick Start

<Steps>
  <Step title="Run YAML — framework auto-detected">
    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    from praisonai import PraisonAI

    praison = PraisonAI(agent_file="agents.yaml")
    praison.run()  # uses first available framework (crewai → praisonai → autogen)
    ```

    <Note>
      `ag2` is registered and can be requested explicitly via `--framework ag2` or `framework: ag2` in YAML, but it is not part of the auto-detect chain because its adapter is an unimplemented stub. Selecting it explicitly will raise `NotImplementedError` at run time until a full implementation lands.
    </Note>
  </Step>

  <Step title="Probe before selecting a framework">
    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    from praisonai._framework_availability import is_available

    if is_available("crewai"):
        print("CrewAI is installed")

    frameworks = ["autogen", "autogen_v4", "crewai", "ag2", "langgraph", "openai_agents", "google_adk"]
    available = [fw for fw in frameworks if is_available(fw)]
    print(f"Available: {available}")
    ```
  </Step>
</Steps>

***

## API Reference

| Function                                       | Signature                            | Behaviour                                                            |
| ---------------------------------------------- | ------------------------------------ | -------------------------------------------------------------------- |
| `is_available(name: str) -> bool`              | Raises `ValueError` on unknown name  | Cached on first call (double-checked locking under `threading.Lock`) |
| `invalidate(name: str \| None = None) -> None` | Pass `None` to clear the whole cache | Useful in tests that monkey-patch `importlib`                        |

***

## Known Probe Names

The following framework names are supported:

| Name              | Detection Method                                                                    | Notes                                                       |
| ----------------- | ----------------------------------------------------------------------------------- | ----------------------------------------------------------- |
| `crewai`          | `importlib.util.find_spec("crewai")`                                                | Standard probe                                              |
| `autogen`         | `importlib.util.find_spec("autogen")`                                               | AutoGen v0.2 package                                        |
| `autogen_v4`      | `find_spec("autogen_agentchat")` + `find_spec("autogen_ext")`                       | AutoGen v0.4 packages                                       |
| `ag2`             | Distribution + namespace check                                                      | See AG2 Detection below                                     |
| `praisonaiagents` | `import praisonaiagents`                                                            | PraisonAI agents framework                                  |
| `praisonai_tools` | `import praisonai_tools`                                                            | PraisonAI tools package                                     |
| `agentops`        | `import agentops`                                                                   | AgentOps observability                                      |
| `litellm`         | `import litellm`                                                                    | LiteLLM package                                             |
| `openai`          | `import openai`                                                                     | OpenAI Python client                                        |
| `chromadb`        | `importlib.util.find_spec("chromadb")`                                              | Vector store backend; used by `ChromaVectorStore`           |
| `pinecone`        | `importlib.util.find_spec("pinecone")`                                              | Vector store backend; used by `PineconeVectorStore`         |
| `qdrant_client`   | `importlib.util.find_spec("qdrant_client")`                                         | Vector store backend                                        |
| `weaviate`        | `importlib.util.find_spec("weaviate")`                                              | Vector store backend                                        |
| `langgraph`       | `find_spec("langgraph")` + `find_spec("langgraph.prebuilt")`                        | LangGraph framework                                         |
| `openai_agents`   | Distribution check + `from agents import Runner`                                    | OpenAI Agents SDK                                           |
| `google_adk`      | `_google_adk_probe()` — three-step: dist check → `google.adk` spec → `Agent` import | Google ADK framework; `True` only when all three steps pass |

<Note>
  `google_adk` detection uses a three-step probe in `_google_adk_probe()`: (1) `importlib.metadata.distribution("google-adk")` — the PyPI dist must be installed; (2) `importlib.util.find_spec("google.adk")` — the namespace must be discoverable; (3) `from google.adk.agents import Agent` with fallback to `from google.adk import Agent`. All three must succeed for `is_available("google_adk")` to return `True`. Install with `pip install 'praisonai-frameworks[google-adk]'` or `pip install 'praisonai[google-adk]'`.
</Note>

Vector store backends use the same centralized probe registry — `praisonai.adapters.vector_stores` calls `is_available("chromadb")` / `is_available("pinecone")` rather than maintaining its own `_check_*` helpers.

<Note>
  `autogen_v2` is an **adapter name** registered in `FrameworkAdapterRegistry`, not a probe name in `_framework_availability`. The probe name remains `autogen` (it imports the `autogen` v0.2 package). Use the adapter's `.is_available()` method to test whether a specific adapter will dispatch successfully — it folds in the `implemented` marker.
</Note>

***

## Adapter Availability vs Framework Availability

Two distinct concepts affect whether an AutoGen-family adapter will actually work:

| Question                                         | API                                                            |
| ------------------------------------------------ | -------------------------------------------------------------- |
| "Is the underlying package importable?"          | `is_available("autogen")` from `_framework_availability`       |
| "Will calling `adapter.run(...)` actually work?" | `AutoGenV4Adapter().is_available()` (folds `implemented` flag) |

For AutoGen v0.4 and AG2 today: the package may import successfully, but the adapter still reports `False` because `implemented = False`. This is the safety-by-default behaviour added in PR #2086.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonai._framework_availability import is_available

# Package-level check: is the v0.4 package installed?
pkg_available = is_available("autogen_v4")  # True if autogen-agentchat is installed

# Adapter-level check: will dispatch actually work?
from praisonai.framework_adapters.autogen_adapter import AutoGenV4Adapter
adapter_available = AutoGenV4Adapter().is_available()  # False — implemented = False

# pkg_available may be True while adapter_available is False
# Always use adapter.is_available() to test dispatch-readiness
```

***

## AG2 Detection Quirk

AG2 ships under the `autogen` namespace, so `is_available("ag2")` checks **both**:

1. `importlib.metadata.distribution('ag2')` - Ensures AG2 distribution is installed
2. `importlib.util.find_spec("autogen")` - Ensures `autogen` namespace is importable

This prevents false positives when only the legacy AutoGen package is installed.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonai._framework_availability import is_available

# This checks both AG2 distribution AND autogen namespace
if is_available("ag2"):
    print("AG2 is properly installed and autogen namespace is available")
```

***

## Cache Management

Results are cached indefinitely until explicitly invalidated:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonai._framework_availability import is_available, invalidate

# First call - performs actual import check
result1 = is_available("crewai")  # Slow: actual import

# Subsequent calls - returns cached result
result2 = is_available("crewai")  # Fast: cached

# Invalidate specific framework
invalidate("crewai")
result3 = is_available("crewai")  # Slow: re-checks import

# Invalidate entire cache
invalidate()  # Clear all cached results
```

***

## Thread Safety

The availability checker uses double-checked locking under `threading.Lock` for thread-safe caching:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
import threading
from praisonai._framework_availability import is_available

def worker():
    # Safe to call from multiple threads
    return is_available("crewai")

threads = [threading.Thread(target=worker) for _ in range(10)]
for t in threads:
    t.start()
for t in threads:
    t.join()
```

***

## Custom Adapter Usage

Plugin authors can use `_framework_availability` for their `is_available()` implementations:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonai._framework_availability import is_available
from praisonai.framework_adapters.base import BaseFrameworkAdapter

class MyAdapter(BaseFrameworkAdapter):
    name = "myframework"
    
    def is_available(self) -> bool:
        return is_available("myframework")  # Uses centralized detection
```

<Warning>
  Third-party adapters cannot extend the known probe names at runtime. The `_PROBES` dict is module-level and not extensible via public API.
</Warning>

***

## Testing Support

Use `invalidate()` in tests that mock `importlib`:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
import unittest.mock
from praisonai._framework_availability import is_available, invalidate

def test_framework_detection():
    # Clear any cached results
    invalidate()
    
    with unittest.mock.patch('importlib.util.find_spec', return_value=None):
        assert not is_available("crewai")
    
    # Clear cache again for clean test state
    invalidate()
```

***

## Backward-compat constants on `praisonai.agents_generator`

Six module-level constants are available for backward compatibility and can be imported directly from `praisonai.agents_generator`.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonai.agents_generator import CREWAI_AVAILABLE, AUTOGEN_AVAILABLE
```

| Constant                    | Equivalent to                     |
| --------------------------- | --------------------------------- |
| `PRAISONAI_TOOLS_AVAILABLE` | `is_available("praisonai_tools")` |
| `CREWAI_AVAILABLE`          | `is_available("crewai")`          |
| `AUTOGEN_AVAILABLE`         | `is_available("autogen")`         |
| `AG2_AVAILABLE`             | `is_available("ag2")`             |
| `PRAISONAI_AVAILABLE`       | `is_available("praisonaiagents")` |
| `AGENTOPS_AVAILABLE`        | `is_available("agentops")`        |

For new code, use `is_available("crewai")` directly rather than importing these constants.

***

## Best Practices

<AccordionGroup>
  <Accordion title="Prefer adapter.is_available() for dispatch decisions">
    Package probes (`is_available("autogen_v4")`) only confirm importability. Use `AutoGenV4Adapter().is_available()` when you need to know whether execution will actually succeed.
  </Accordion>

  <Accordion title="Use invalidate() in tests that mock importlib">
    Cached results persist for the process lifetime. Call `invalidate()` before and after monkey-patching `importlib` so probes re-run cleanly.
  </Accordion>

  <Accordion title="Avoid heavy imports inside is_available()">
    Custom adapters should delegate to `is_available()` rather than importing large packages on every CLI startup probe.
  </Accordion>

  <Accordion title="Use pick_default() instead of manual priority lists">
    For default framework selection, call `FrameworkAdapterRegistry.pick_default()` rather than hard-coding probe tuples.
  </Accordion>
</AccordionGroup>

***

## Related

<CardGroup cols={2}>
  <Card title="Framework Adapter Plugins" icon="plug" href="/docs/features/framework-adapter-plugins">
    Creating custom framework adapters
  </Card>

  <Card title="AutoGen Framework" icon="robot" href="/docs/framework/autogen">
    AutoGen framework integration
  </Card>

  <Card title="Google ADK Framework" icon="robot" href="/docs/framework/google-adk">
    Google ADK framework integration
  </Card>
</CardGroup>
