Interactive Tools
Default ACP, Edit, LSP, Search, Basic, and Clarify tools for interactive modes (TUI and prompt)
The coding agent can search the codebase with wired-in grep / glob / ast_grep_search — no shelling out to raw grep -rn.
# Coding agent searches the codebase automatically
praison "Find every call site of deprecated_fn under src/"This uses the ripgrep-backed grep, glob, and structural ast_grep_search tools that ship in the default interactive toolset.
Overview
PraisonAI interactive modes (praisonai tui launch and praison "prompt") now include ACP (Agentic Change Plan), Edit (targeted/fuzzy edits), LSP (Language Server Protocol), Search (ripgrep-backed grep/glob + structural ast_grep_search), and Clarify (human-in-the-loop question tool) tools by default.
This enables agents to:
- Create, edit, and delete files with plan/approve/apply/verify flow (ACP)
- Precisely edit files with a targeted find-and-replace engine (
edit_file) and atomic multi-file patches (apply_patch), backed by a 5-strategy fuzzy match ladder, SHA-256 staleness guard, BOM/CRLF preservation, and post-edit LSP/linter diagnostics. See File Editing for the engine details. - Analyze code with symbol listing, definition lookup, and reference finding (LSP)
- Search the codebase with ripgrep-backed text/file search and structural AST search (Search)
- Ask the user a focused clarifying question when genuinely blocked, instead of silently guessing (Clarify — gated on a live interactive TTY)
- Execute commands with safety guardrails
Default Tool Groups
| Group | Tools | Description |
|---|---|---|
| ACP | acp_create_file, acp_edit_file, acp_delete_file, acp_execute_command | Safe file operations with plan/approve/apply |
| Edit | edit_file, apply_patch | Targeted/fuzzy atomic edits with rollback (replaces whole-file rewrites as the primary edit path) |
| LSP | lsp_list_symbols, lsp_find_definition, lsp_find_references, lsp_get_diagnostics | Code intelligence |
| Search | grep, glob, ast_grep_search | Fast codebase search — ripgrep-backed text/file search + structural AST search |
| Basic | read_file, write_file, list_files, execute_command, internet_search | Standard tools. execute_command refuses shell operators unless PRAISON_SHELL enables a real shell — see Shell operators. Under PRAISON_SHELL=sandboxed every command runs contained |
| MCP | (discovered at runtime from mcp.servers) | Tools from configured MCP servers. Opt out with PRAISON_TOOLS_DISABLE=mcp; a server can never shadow a built-in tool name (built-in wins). See MCP tools in coding sessions |
| Clarify | clarify | Human-in-the-loop clarify tool — pauses the run to ask one focused question. Withheld in headless/non-TTY/CI/JSON runs; the core best-judgment fallback then handles ambiguity without blocking. |
The Clarify group is auto-gated: enabled in config by default, but only actually exposed to the LLM when the run is on a real interactive terminal (see Clarify Gating below). All other groups are unconditionally enabled by default.
All groups are enabled by default in interactive modes; you can disable individual groups per Disabling Tool Groups below.
Quick Start
# Run with all default tools (ACP + Edit + LSP + Search + Basic)
praison "Create a Python file that calculates fibonacci numbers"
# Launch TUI with all default tools
praisonai tui launchDisabling Tool Groups
CLI Flags
# Disable ACP tools (no file modification capabilities)
praison "Analyze this code" --no-acp
# Disable LSP tools (no code intelligence)
praison "Write a script" --no-lsp
# Disable both (basic tools only)
praison "Search the web" --no-acp --no-lsp
# TUI with disabled groups
praisonai tui launch --no-acp --no-lspThe --no-acp / --no-lsp flags disable those groups. There is no --no-edit flag and no --no-search flag — disable the edit or search group with the env var below or ToolConfig(enable_edit=False) / ToolConfig(enable_search=False) from Python. There is also no --no-clarify flag — turn the clarify tool off with PRAISON_NO_CLARIFY=1, PRAISON_TOOLS_DISABLE=clarify, or ToolConfig(enable_clarify=False).
Environment Variables
# Disable the fuzzy/atomic edit engine only (restores old whole-file-rewrite default)
export PRAISON_TOOLS_DISABLE=edit
praison "Hello world"
# Disable only the search group
export PRAISON_TOOLS_DISABLE=search
praison "Hello world"
# Disable multiple groups
export PRAISON_TOOLS_DISABLE=acp,edit,lsp,search,clarify
praison "Hello world"
# Force the clarify tool off even on a real terminal
export PRAISON_NO_CLARIFY=1
praison "Hello world"
# Set workspace
export PRAISON_WORKSPACE=/path/to/projectTo disable per-invocation, prefer the env var above; ToolConfig(enable_edit=False) from Python has the same effect.
Tool Details
ACP Tools (Agentic Change Plan)
ACP tools route file operations through a plan/approve/apply/verify flow:
User Request → Create Plan → Approve → Apply → Verify| Tool | Description |
|---|---|
acp_create_file | Create a new file with content |
acp_edit_file | Edit an existing file |
acp_delete_file | Delete a file (requires approval) |
acp_execute_command | Execute a shell command |
Safety Features:
- All destructive operations require approval
- Changes are tracked and can be verified
- Workspace boundary enforcement
Edit Tools (targeted, atomic edits)
The edit group wires the core edit_file / apply_patch engine into the default interactive toolset.
| Tool | Description |
|---|---|
edit_file | Targeted find-and-replace with a 5-strategy fuzzy match ladder; SHA-256 staleness guard via expected_hash; per-file lock; preserves LF/CRLF/BOM |
apply_patch | Atomic multi-file Add/Update/Delete with rollback on any failure |
When they run:
approval_mode="auto"— context-approved (matching the ACP tools). No blocking console prompt. The loader mergesedit_file/apply_patchinto the YAML-approved set viaadd_yaml_approved_tools(...), so pre-existing approvals are preserved (never clobbered). This standing approval is granted only when theeditgroup is in the requested tool list — a run that pins a non-edit tool list gets no edit approval.approval_mode="prompt"(whatpraisonai code --safewrites) — the normal HIGH-risk approval flow with diff preview applies on every call. The core@require_approvalgate prompts on a TTY and denies in non-TTY runs.approval_mode="manual"/"scoped"— same per-call approval flow asprompt.
Fail-closed on workspace containment: If Workspace(root=<workspace>) cannot be built, edit_file/apply_patch are not exposed at all and a WARNING is logged. Combined with auto-approval, an unbounded workspace could let an absolute path (e.g. /etc/hosts) escape the configured directory, so the loader refuses to expose the tools rather than exposing them unsafely. You will see:
WARNING praisonai_code.cli.features.interactive_tools: Edit tools disabled: workspace containment unavailable: <reason>See File Editing for the full engine — fuzzy ladder, staleness guard, post-edit diagnostics and formatting, and the apply_patch grammar. That page also covers force=True and expected_hash=... for advanced use.
Which file-editing path fires by default?
Both ACP file tools and the targeted-edit tools are available by default. This is which one runs when you don’t pin anything:
LSP Tools (Code Intelligence)
LSP tools provide semantic code analysis:
| Tool | Description |
|---|---|
lsp_list_symbols | List functions, classes, methods in a file |
lsp_find_definition | Find where a symbol is defined |
lsp_find_references | Find all references to a symbol |
lsp_get_diagnostics | Get errors and warnings |
Fallback Behavior:
- If LSP server is unavailable, tools fall back to regex-based extraction
- Results include
lsp_usedflag to indicate which method was used
Search Tools
The search group wires the ripgrep-backed core search builtins into the default interactive toolset, so the agent no longer shells out to a raw grep -rn.
| Tool | Description |
|---|---|
grep | Ripgrep-backed text search. Gitignore-aware, result-capped, truncation-safe. Falls back to Python when rg is not on PATH. |
glob | File-pattern search (e.g. **/*.py). Same fallback ladder. |
ast_grep_search | Structural / AST-aware code search via ast-grep. |
These are the same tools documented at Search Tools and AST-Grep Agent.
Which search tool fires?
Basic Tools
Standard file and search tools:
| Tool | Description | |
|---|---|---|
read_file | Read file content | |
write_file | Write content to file | |
list_files | List directory contents | |
execute_command | Run shell commands. Shell operators (>, `\ | , &&, $(…)) are refused unless PRAISON_SHELL enables a real shell — see below. Under sandboxed`, operators are also accepted by the ACP tool |
internet_search | Search the web |
Shell operators
execute_command runs subprocess.Popen(shell=False), so a shell operator would become a literal argument and report false success. To prevent that, operators are refused by default and only run when PRAISON_SHELL enables a real, approval-gated /bin/sh.
PRAISON_SHELL | Behaviour |
|---|---|
unset / off (default) | Operators refused; plain commands run as before |
sandboxed | Every command — with or without operators, including the ACP acp_execute_command path — runs in a real /bin/sh -c inside OS containment (Seatbelt/bwrap) |
unsafe | Operators run in a real /bin/sh -c, no containment |
See Shell Modes and OS Sandbox.
Clarify Tool (Human-in-the-Loop)
Clarify pauses the run to ask one focused question when the agent is genuinely blocked.
# The clarify tool appears automatically on an interactive terminal
praison "Build me a web scraper"🤔 Which language?
Choices:
1. python
2. rust
Your choice (number or text): 1The agent asks, you answer in your terminal, and the run resumes with your choice.
| Tool | Description | |
|---|---|---|
clarify | Async callable `clarify(question: str, choices: list[str] \ | None = None) -> str. Pauses the turn and reads the answer from the terminal via create_cli_clarify_handler(). A numbered menu is shown when choices is provided, free-text input otherwise. Ctrl+C / EOF returns “skip”`. |
Clarify Gating
The clarify tool is only exposed when all of these hold, checked in this order. If any gate fails, the tool is withheld entirely — the LLM never sees a clarify tool, so the core ClarifyHandler best-judgment fallback silently handles ambiguity instead of blocking on input().
PRAISON_NO_CLARIFY— unset or one of"",0,false,nokeeps the gate open;1,true,yesdisable clarify.CI— unset or one of"",0,false,nokeeps the gate open; any other truthy value disables clarify (CI runners can allocate PTYs even without a human present).PRAISON_OUTPUT_MODE— must not bejson,stream-json, oractions(structured/machine consumers never prompt).sys.stdin.isatty()andsys.stdout.isatty()— both must returnTrue(a real interactive terminal).
Python API
from praisonai.cli.features import (
get_interactive_tools,
ToolConfig,
TOOL_GROUPS,
)
# Get all default tools
tools = get_interactive_tools()
# Get tools with specific config
config = ToolConfig(
workspace="/path/to/project",
enable_acp=True,
enable_edit=True,
enable_lsp=True,
enable_search=True,
enable_clarify=True,
approval_mode="auto", # or "manual"
)
tools = get_interactive_tools(config=config)
# Disable specific groups
tools = get_interactive_tools(disable=["acp"])
# Disable only the clarify group
tools = get_interactive_tools(disable=["clarify"])
# or
tools = get_interactive_tools(config=ToolConfig(enable_clarify=False))
# Disable only the search group
tools = get_interactive_tools(disable=["search"])
# or
tools = get_interactive_tools(config=ToolConfig(enable_search=False))
# Restore old whole-file-rewrite default (no targeted-edit tools)
tools = get_interactive_tools(config=ToolConfig(enable_edit=False))
# Get only specific groups
tools = get_interactive_tools(groups=["basic"])Configuration
ToolConfig Options
| Option | Default | Description |
|---|---|---|
workspace | os.getcwd() | Working directory |
enable_acp | True | Enable ACP tools |
enable_edit | True | Enable the edit_file / apply_patch targeted-edit tools |
enable_lsp | True | Enable LSP tools |
enable_search | True | Enable the ripgrep-backed grep / glob / ast_grep_search tools |
enable_basic | True | Enable basic tools |
enable_clarify | True | Enable the human-in-the-loop clarify tool. Also runtime-gated on an interactive TTY — see Clarify Gating. |
approval_mode | "auto" | Approval mode: auto, prompt, manual, scoped |
Approval Modes
| Mode | Description |
|---|---|
prompt | Safe default under praisonai code --safe. Every HIGH-risk tool call is approved per-call (prompts on a TTY, denies without one) |
auto | Full privileges – all operations auto-approved (opt-in via --no-safe / --dangerously-skip-approval) |
manual | All write operations require explicit approval |
scoped | Safe operations auto-approved, dangerous ones (delete, shell) require approval |
Important: In prompt mode the in-wrapper ACP orchestrator still runs with approval_mode="auto" so plans are approved; the single approval point is the core @require_approval gate on each tool, which prompts on a TTY and denies in non-TTY runs. This avoids a second, non-interactive “Plan is not approved” refusal. Standing approval for edit_file / apply_patch is granted only when explicit auto mode is combined with an edit tool-group request. In manual / scoped modes the normal HIGH-risk approval flow with diff preview applies.
Fail-closed env parsing: ToolConfig.from_env() accepts auto / prompt / manual / scoped (case-insensitive, whitespace stripped). Any other non-empty value logs Unknown PRAISON_APPROVAL_MODE=...; using 'prompt' and falls back to prompt — it no longer silently keeps the permissive auto default.
Environment Variables
| Variable | Description |
|---|---|
PRAISON_TOOLS_DISABLE | Comma-separated groups to disable. Accepts: acp, edit, lsp, search, basic, clarify. Applied by ToolConfig.__post_init__, so direct constructions honor it too. |
PRAISON_NO_CLARIFY | Set to 1 / true / yes to force the clarify tool off even on a real terminal. Any other value / unset leaves the gate open. |
PRAISON_OUTPUT_MODE | When json, stream-json, or actions, the clarify tool is withheld so machine consumers never see a prompt. |
CI | Any truthy value (anything other than empty / 0 / false / no) withholds clarify, because CI runners can allocate pseudo-TTYs without a human present. |
PRAISON_WORKSPACE | Override workspace path |
PRAISON_APPROVAL_MODE | auto, prompt (safe default), manual, scoped. Unknown values become prompt with a warning. |
PYTHONIOENCODING | Set to utf-8 for Windows automation subprocess compatibility |
PRAISON_DEBUG | Set to 1 to enable debug logging |
Debug Logging
Enable debug logging to troubleshoot tool execution:
# Via CLI flag
praisonai chat --debug
# Via environment variable
export PRAISON_DEBUG=1
praisonai chat
# Via slash command during session
/debugDebug logs are written to ~/.praisonai/async_tui_debug.log.
Architecture
praison "prompt" / praisonai tui launch
│
▼
┌─────────────────────────────────────────────────────────────┐
│ get_interactive_tools() │
│ (Canonical source of truth) │
└─────────────────────────────────────────────────────────────┘
│
├── ACP Tools → ActionOrchestrator → Plan/Apply/Verify
│
├── Edit Tools → EditTools engine (fuzzy ladder + staleness guard + rollback)
│
├── LSP Tools → CodeIntelligenceRouter → LSP/Fallback
│
├── Search Tools → ripgrep (fallback: Python / grep -rn)
│
├── Clarify Tool → CLI ClarifyHandler → stdin prompt (gated on interactive TTY)
│
└── Basic Tools → Direct executionTesting ACP/LSP Tools
The interactive test framework allows you to test ACP and LSP tools in isolation with full tracing and assertions.
Tool Tracing
When running tests, all tool calls are captured in a structured trace:
{
"tool_name": "acp_create_file",
"args": ["hello.py", "print('hello')"],
"kwargs": {},
"result": "{\"success\": true, \"file_created\": \"hello.py\"}",
"success": true,
"duration": 0.234,
"timestamp": "2024-01-15T10:30:00Z"
}Testing Tool Calls
Use the CSV test runner to verify expected tool usage:
id,name,prompts,expected_tools,forbidden_tools
test_01,Create File,"Create hello.py",acp_create_file,acp_delete_file
test_02,Read Only,"Read the README",read_file,"acp_create_file,acp_edit_file"
test_03,Code Analysis,"List symbols in main.py",lsp_list_symbols,
test_04,Targeted Edit,"Rename getName to getEmail in user.py",edit_file,write_fileThe expected_tools / forbidden_tools mechanism applies to edit_file and apply_patch too — assert the targeted-edit path fires instead of a whole-file write_file.
Tool Assertions
The test harness supports two types of tool assertions:
- Expected Tools: Tools that MUST be called
expected_tools,acp_create_file,acp_edit_file- Forbidden Tools: Tools that MUST NOT be called
forbidden_tools,acp_delete_file,acp_execute_commandRunning Tool Tests
# Run the tools test suite
praisonai test interactive --suite tools
# Run with verbose output to see tool calls
praisonai test interactive --suite tools --verbose
# Keep artifacts to inspect tool traces
praisonai test interactive --suite tools --keep-artifactsInspecting Tool Traces
After running with --keep-artifacts, check the tool_trace.jsonl file:
# View tool trace for a specific test
cat artifacts/test_01/tool_trace.jsonl | jq .
# Count tool calls
wc -l artifacts/test_01/tool_trace.jsonl
# Filter by tool name
grep "acp_create_file" artifacts/test_01/tool_trace.jsonlTesting LSP Fallback
LSP tools gracefully fall back to regex when LSP server is unavailable:
id,name,prompts,expected_tools,workspace_fixture
lsp_01,List Symbols,"List all functions in utils.py",lsp_list_symbols,python_project
lsp_02,Find Definition,"Where is Calculator defined?",lsp_find_definition,python_projectThe test will pass regardless of whether LSP or regex fallback is used, as long as results are returned.
Network-Enabled Testing
For tests that require network access (e.g., GitHub operations), use the PRAISON_LIVE_NETWORK environment variable:
# Enable network operations
PRAISON_LIVE_NETWORK=1 praisonai test interactive --suite github-advancedCommand Allowlist
When PRAISON_LIVE_NETWORK=1 is set, the following commands are allowed:
| Category | Commands |
|---|---|
| Git | git |
| GitHub CLI | gh |
| Python | python, python3, pip, pip3, uv, pytest, ruff, black, mypy |
| Node | node, npm, npx |
| Build | make |
| Utilities | echo, cat, ls, pwd, head, tail, wc, grep, find, mkdir, touch, cp, mv |
Blocked Commands
The following commands are always blocked for safety:
rm -rf /, sudo, su, systemctl, shutdown, reboot, dd, mkfs, fdisk
curl | bash, wget | bash, fork bombsSecret Redaction
All artifacts automatically redact sensitive information:
- GitHub tokens (
ghp_,gho_,github_pat_*) - OpenAI keys (
sk-,sk-proj-) - AWS credentials (
AKIA*) - Bearer tokens
- Passwords and secrets in config
Related
- Agent-Centric Tools – ACP/LSP tool implementation
- LSP Code Intelligence – LSP details
- Search Tools – SDK-level
grep/globreference - AST-Grep Agent – SDK-level structural search reference
- Clarify Tool – SDK / bot / custom-handler side of the human-in-the-loop clarify feature
- Debug CLI – Debug commands
- Interactive TUI Testing – Test framework