Skip to main content
One command installs a tool package and tells you exactly which tools became available — or exits non-zero if none did. Previously a package could pip install cleanly yet expose no resolvable tools — a silent failure. tools add turns that into a surfaced non-zero exit.

Quick Start

1

Install a tool package

praisonai-my-tools is a placeholder — replace it with a real pip requirement spec.
2

Upgrade an installed package

3

Verify without installing

--dry-run skips installation and reports whether any new tool would resolve from what’s already installed.
Enable code execution during install first. praisonai tools add refuses to install a tool package when the source is a local file path, a github: reference, or a bare package name unless PRAISONAI_ALLOW_LOCAL_TOOLS=true is set. All three branches run user code — a local file executes on load, a github: fetch downloads then loads, and a bare package name is resolved on sys.path and its __init__ runs at import time. The gate is the same one that governs tools.py autoload (see Security Environment Variables). A published pip install-style spec that is already installed and is only being resolved by name goes through the same import, so the gate applies there too.
On refusal of a bare package name, the CLI prints:
and returns {"success": False, "error": "PRAISONAI_ALLOW_LOCAL_TOOLS not set"}.

How It Works

The command snapshots resolvable tools, installs, builds a fresh resolver, then reports the diff.
Discovery constructs a fresh ToolResolver(). Calling resolver.invalidate() alone is not enough — it only clears the per-name resolution cache, not instance-level availability caches (like whether praisonai_tools is importable). A new instance re-evaluates those against the now-updated environment.

Security

  • No code execution for the github: inspection path. The github: download inspects a candidate tools.py with ast.parse — it does not execute that downloaded file. But the fetch itself and the load run under the same opt-in.
  • Package-name branch executes __init__ on resolve. praisonai tools add <name> when <name> is neither a local path nor a github: reference calls importlib.import_module(<name>) to inspect the package. That runs its top-level code — which is exactly why it is now gated behind PRAISONAI_ALLOW_LOCAL_TOOLS=true.
  • github: downloads are locked down: HTTPS raw URLs only (raw.githubusercontent.com / raw.github.com), no redirect follow, a 1 MiB size cap, and the on-disk filename is derived from the URL’s last path segment as a safe single basename (no directory traversal).
  • No --sha256 flag — the PR that hardened this path deliberately left it out to avoid a new CLI knob. Rely on PyPI signing or your own out-of-band verification if you need a pinned artefact.

Options


How the Installer Is Chosen

Installation is pinned to the interpreter running the CLI so the package lands where discovery will look. See plugins add → How the Installer Is Chosen for the shared decision diagram — both commands use the same _resolve_installer() logic.

Exit Codes


Output Shape

A successful run prints a Rich table titled Registered N tool(s) from <package>, with the tool’s resolution source:
Source values come from ToolResolver.list_available_sources() and are one of: On --dry-run the title verb is Discovered instead of Registered.

Common Patterns

When uv is present, the package is pinned to the CLI interpreter so a fresh resolver sees it.

Best Practices

If you script installs yourself, build a new ToolResolver() after installing — invalidate() clears only the per-name cache, not instance-level availability caches.
A package can install cleanly yet expose no tools. --dry-run exits non-zero when discovery finds nothing new.
The default pins to the CLI interpreter so the tools are resolvable by the same process. Reach for --global only when you want the system environment.
Run praisonai tools list to see every resolvable tool and its source, not just what this command added.

plugins add

Install a plugin package and verify it registered

Tool Source Registry

Plug third-party tool sources via entry points

Tool Resolver

Single source of truth for loading tools

Tool Discovery Order

How Agent resolves tool names at runtime