Skip to main content
Drop Markdown, YAML, or Python files into .praisonai/agents/, .praisonai/commands/, and .praisonai/tools/ to extend the CLI without writing packaging code. The user runs praisonai run --agent researcher; discovery loads custom agents, slash commands, and project-local tools from .praisonai/.

How It Works

Quick Start

Skip the boilerplate — praisonai init scaffolds a working .praisonai/ with a starter agent and command, then read on to customise.
1

Create an agent file

2

Run the agent

3

Create a command file

4

Run the command

How discovery works

Project definitions override user definitions on name collision.

Agent definitions

Files: .praisonai/agents/*.md or *.yaml

Scoping permissions

Three built-in agents (build, plan, review) are available without any file — see Agent Presets & Modes.
Add mode: to a definition for instant read-only or review scoping:
For finer control, use the permission: block:
See Agent Presets & Modes for the full modes reference, permission syntax, and precedence rules.

Supported mode: values

mode: subagent marks an agent as delegatable from other agents at run time (see Named Agent Delegation). It is a marker only — it does not apply any permission changes and is ignored when computing permissions. Every other mode: value still flows through the permission engine as before.

Command templates

Files: .praisonai/commands/*.md

Opt-in live shell substitution

!`cmd` is disabled by default. Enable with any one of:
  1. PRAISONAI_ALLOW_SHELL=true environment variable
  2. commands.allow_shell: true in .praisonai/config.yaml
  3. Per-command frontmatter allow_shell: true
Safety bounds: 30s timeout, 100KB max stdout, runs in the template’s working directory. Non-zero exit raises ShellSubstitutionError. !`cmd` inside $ARGUMENTS or @file contents is never executed — only markers in the original template run.

Project-local tools

Drop any .py file into .praisonai/tools/ and every praisonai run in that project auto-loads its tools — no --tools flag, no packaging, no imports in your agent code.
That is the whole feature. The rest of this section is detail.
Loading a tool file executes its Python. Auto-load is gated by PRAISONAI_ALLOW_LOCAL_TOOLS=true — the same opt-in that guards every local tool in the CLI. Without it, .praisonai/tools/ is skipped entirely.

How discovery works

What gets loaded

Precedence & opt-out

A richer example — private helpers stay private

Scaffold with praisonai init

The scaffolded example.py is a commented @tool stub — uncomment or replace it in place.

Making an agent delegatable

Mark an agent with mode: subagent so a running primary agent can hand it sub-tasks by name.
Now a running primary agent (praisonai run --agent lead) can call spawn_subagent(agent_name="researcher", …) and this agent runs the sub-task under its own model/tools/permissions. See Named Agent Delegation.

Agent vs command vs skill vs rule

Slash commands

Custom commands auto-register in interactive mode as CommandKind.CUSTOM. Disable with SlashCommandHandler(discover_custom=False). Custom commands appear automatically in Telegram / Discord / autocomplete when your bot restarts, filtered by the same CommandAccessPolicy that gates execution. See Native / Autocomplete.

Inside praisonai code too

The same .praisonai/commands/*.md files work as /name inside praisonai code, the REPL, and the async TUI. A unified CommandRegistry aggregates built-ins, your custom commands, skills, MCP prompts, and pip-installed praisonai.commands packs into one namespace:
This runs the exact interpolated template that praisonai run --command mydeploy staging would — byte-for-byte parity between interactive and CLI. See Slash Commands → Unified Command Registry.

Python API

discover_project_tools() returns a list of tool callables (empty unless PRAISONAI_ALLOW_LOCAL_TOOLS=true). For metadata, CustomDefinitionsDiscovery().list_tools() returns CustomTool(name, path, callable, source) records where name is the namespaced <module>.<func>.

Best Practices

Commit .praisonai/agents/, .praisonai/commands/, and .praisonai/tools/ to git. Every teammate and CI run picks up the same tool set on the next praisonai run — no pip install and no --tools flag.
.praisonai/tools/_helpers.py is skipped entirely. Inside a loaded file, functions without @tool are only fallback-loaded when the file has no @tool at all — so decorating your public entry points keeps private helpers off the LLM’s tool list.
Use ~/.praisonai/ for personal shortcuts that should not override team agents.
!`cmd` requires an explicit opt-in gate (allow_shell: true, config, or PRAISONAI_ALLOW_SHELL). $(...) is always escaped — use !`cmd` only when you need live output like git diff.
Run praisonai init to scaffold .praisonai/agents/, .praisonai/commands/, and .praisonai/tools/ before hand-writing files.

Run CLI

—agent and —command flags

Agent CLI

List and inspect custom agents

Command CLI

List and preview commands

Slash Commands

Interactive custom commands

Init CLI

Scaffold .praisonai/ in one command

Tools

The @tool decorator and building custom tools

Agent Presets & Modes

Built-in presets and per-agent permission scoping

Named Agent Delegation

Delegate named sub-tasks to your agents with mode: subagent