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

# Strict Tools Mode

> Fail-fast dependency checking for templates

Strict tools mode provides fail-fast dependency checking before running templates. When enabled, the template will not execute if any required tool, package, or environment variable is missing.

## Python API

### DependencyChecker

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonai.templates import DependencyChecker, StrictModeError
from praisonai.templates import TemplateLoader

# Load a template
loader = TemplateLoader()
template = loader.load("my-template")

# Create dependency checker
checker = DependencyChecker()

# Check all dependencies (non-strict - returns status)
result = checker.check_template_dependencies(template)
print(f"All satisfied: {result['all_satisfied']}")

# Enforce strict mode (raises exception if missing)
try:
    checker.enforce_strict_mode(template)
    print("✓ All dependencies satisfied")
except StrictModeError as e:
    print(f"Missing dependencies:\n{e}")
    print(f"Missing items: {e.missing_items}")
```

### Checking Individual Dependencies

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

checker = DependencyChecker()

# Check tool availability
tool_status = checker.check_tool("internet_search")
print(f"Available: {tool_status['available']}")
print(f"Source: {tool_status['source']}")  # local, builtin, external, registered, resolver, custom

# Check package availability
pkg_status = checker.check_package("pandas")
print(f"Available: {pkg_status['available']}")
print(f"Install hint: {pkg_status['install_hint']}")

# Check environment variable
env_status = checker.check_env_var("OPENAI_API_KEY")
print(f"Available: {env_status['available']}")
print(f"Masked value: {env_status['masked_value']}")  # sk-****1234
```

### Tool Source Values

`check_tool()` delegates to `ToolResolver.list_available_sources()` — the same resolution chain used at agent run time. The `source` field reflects where the tool actually comes from:

| Source                                   | Where it comes from                                                        | Notes                                               |
| ---------------------------------------- | -------------------------------------------------------------------------- | --------------------------------------------------- |
| `local`                                  | Your local `tools.py` (via `ToolResolver`)                                 | Requires `PRAISONAI_ALLOW_LOCAL_TOOLS=true`         |
| `builtin`                                | `praisonaiagents.tools` (via `ToolResolver`)                               | No extra install needed                             |
| `external`                               | `praisonai-tools` package (via `ToolResolver`)                             | Requires `pip install praisonai-tools`              |
| `registered`                             | Wrapper `ToolRegistry` or core SDK entry-point plugin (via `ToolResolver`) | Tools registered via `register_function()`          |
| `resolver`                               | Resolvable but not attributed to a bucket (rare)                           | Conservative fallback                               |
| `custom`                                 | Custom tool directories (`custom_tool_dirs=[...]`)                         | Always honored unconditionally                      |
| `builtin` / `praisonai-tools` / `custom` | Legacy fallback path                                                       | Only appears when `ToolResolver` cannot be imported |

<Note>
  **Tools registered via `ToolRegistry.register_function()` and core SDK entry-point plugins are now correctly reported as `available`.** Before [PR #2642](https://github.com/MervinPraison/PraisonAI/pull/2642), these tools resolved correctly at agent run time but were reported as "not installed" by the dependency checker. The checker now delegates to `ToolResolver` — the same source of truth used by `resolve()` — so diagnostic output matches runtime behaviour.

  If you are migrating from an earlier version and previously saw tools reported as missing in strict mode, verify those tools are registered via `ToolRegistry` or a `praisonai.tool_sources` entry-point plugin — they will now appear as `available` with `source: "registered"`.
</Note>

### Getting Install Hints

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonai.templates import DependencyChecker, TemplateLoader

loader = TemplateLoader()
template = loader.load("video-analyzer")

checker = DependencyChecker()
hints = checker.get_install_hints(template)

for hint in hints:
    print(f"• {hint}")
# Output:
# • Tool 'youtube_tool': pip install praisonai-tools[video]
# • Package 'opencv-python': pip install opencv-python
# • Environment variable 'YOUTUBE_API_KEY': export YOUTUBE_API_KEY=<value>
```

Install hints are only generated for tools that are genuinely missing from all sources. Tools that resolve via `ToolRegistry` or entry-point plugins will not trigger install hints.

## StrictModeError

When strict mode fails, `StrictModeError` is raised with:

| Attribute       | Type | Description                                |
| --------------- | ---- | ------------------------------------------ |
| `message`       | str  | Human-readable error message               |
| `missing_items` | dict | Dict with 'tools', 'packages', 'env' lists |

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
try:
    checker.enforce_strict_mode(template)
except StrictModeError as e:
    if e.missing_items["tools"]:
        print(f"Missing tools: {e.missing_items['tools']}")
    if e.missing_items["packages"]:
        print(f"Missing packages: {e.missing_items['packages']}")
    if e.missing_items["env"]:
        print(f"Missing env vars: {e.missing_items['env']}")
```

## Custom Tool Directories

The checker always honors `custom_tool_dirs` on top of the resolver's chain:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
checker = DependencyChecker(
    custom_tool_dirs=["~/.praisonai/tools", "./my-tools"]
)

# Tools in custom dirs will be found (source: "custom:<dir>")
result = checker.check_tool("my_custom_tool")
```

Custom directories are not part of the `ToolResolver` chain — they are checked unconditionally so template-local tool directories always resolve regardless of resolver availability.

## Related

<CardGroup cols={2}>
  <Card title="Tools Doctor" icon="stethoscope" href="/docs/cli/tools-doctor">
    Full tool availability diagnostics
  </Card>

  <Card title="Tool Resolver" icon="wrench" href="/docs/features/tool-resolver">
    Resolution chain and source labels
  </Card>

  <Card title="Tools" icon="wrench" href="/docs/cli/tools">
    Source label table and CLI reference
  </Card>
</CardGroup>
