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 local/remote tool installs first. praisonai tools add refuses to install a tool package whose path is a local file or a github: reference unless PRAISONAI_ALLOW_LOCAL_TOOLS=true is set. The gate is the same one that governs tools.py autoload (see Security Environment Variables). Publishing a package to PyPI is not gated β€” pip install-style specs still work without the env var.

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 at add time. tools add inspects a candidate package with ast.parse β€” it does not import or execute the module. A malicious tools.py cannot run during install.
  • 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