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.

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

GroupToolsDescription
ACPacp_create_file, acp_edit_file, acp_delete_file, acp_execute_commandSafe file operations with plan/approve/apply
Editedit_file, apply_patchTargeted/fuzzy atomic edits with rollback (replaces whole-file rewrites as the primary edit path)
LSPlsp_list_symbols, lsp_find_definition, lsp_find_references, lsp_get_diagnosticsCode intelligence
Searchgrep, glob, ast_grep_searchFast codebase search — ripgrep-backed text/file search + structural AST search
Basicread_file, write_file, list_files, execute_command, internet_searchStandard 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
ClarifyclarifyHuman-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

bash
# 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 launch

Disabling Tool Groups

CLI Flags

bash
# 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-lsp

The --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

bash
# 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/project

To 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
ToolDescription
acp_create_fileCreate a new file with content
acp_edit_fileEdit an existing file
acp_delete_fileDelete a file (requires approval)
acp_execute_commandExecute 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.

ToolDescription
edit_fileTargeted 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_patchAtomic 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 merges edit_file/apply_patch into the YAML-approved set via add_yaml_approved_tools(...), so pre-existing approvals are preserved (never clobbered). This standing approval is granted only when the edit group is in the requested tool list — a run that pins a non-edit tool list gets no edit approval.
  • approval_mode="prompt" (what praisonai code --safe writes) — the normal HIGH-risk approval flow with diff preview applies on every call. The core @require_approval gate prompts on a TTY and denies in non-TTY runs.
  • approval_mode="manual" / "scoped" — same per-call approval flow as prompt.

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:

Diagram

Edit one spot in a file

Rename across files

Plan → approve → apply flow

Whole-file rewrite

🤖 Agent needs to change files

What kind of change?

edit_file — targeted, fuzzy, atomic
NEW default

apply_patch — multi-file atomic

acp_edit_file — unchanged

write_file / acp_create_file
still available

LSP Tools (Code Intelligence)

LSP tools provide semantic code analysis:

ToolDescription
lsp_list_symbolsList functions, classes, methods in a file
lsp_find_definitionFind where a symbol is defined
lsp_find_referencesFind all references to a symbol
lsp_get_diagnosticsGet errors and warnings

Fallback Behavior:

  • If LSP server is unavailable, tools fall back to regex-based extraction
  • Results include lsp_used flag 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.

ToolDescription
grepRipgrep-backed text search. Gitignore-aware, result-capped, truncation-safe. Falls back to Python when rg is not on PATH.
globFile-pattern search (e.g. **/*.py). Same fallback ladder.
ast_grep_searchStructural / AST-aware code search via ast-grep.

These are the same tools documented at Search Tools and AST-Grep Agent.

Which search tool fires?

Diagram

Text or regex in file contents

File names / paths by pattern

Code structure / AST pattern

🔍 Agent needs to search the codebase

What are you matching?

grep — ripgrep text search

glob — file-pattern search

ast_grep_search — structural search

Basic Tools

Standard file and search tools:

ToolDescription
read_fileRead file content
write_fileWrite content to file
list_filesList directory contents
execute_commandRun 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_searchSearch 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_SHELLBehaviour
unset / off (default)Operators refused; plain commands run as before
sandboxedEvery command — with or without operators, including the ACP acp_execute_command path — runs in a real /bin/sh -c inside OS containment (Seatbelt/bwrap)
unsafeOperators 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.

bash
# 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): 1

The agent asks, you answer in your terminal, and the run resumes with your choice.

Diagram

Clarify Flow

🤖 Agent blocked

❓ clarify question

💻 Terminal prompt

🙂 User answers

✅ Run resumes

ToolDescription
clarifyAsync 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().

Diagram

Yes

No

Yes

No

Yes

No

No

Yes

🤖 Interactive run starts

PRAISON_NO_CLARIFY truthy?

⚠️ Withhold clarify
best-judgment fallback

CI truthy?

PRAISON_OUTPUT_MODE
json / stream-json / actions?

stdin AND stdout isatty?

✅ Expose clarify tool

  1. PRAISON_NO_CLARIFY — unset or one of "", 0, false, no keeps the gate open; 1, true, yes disable clarify.
  2. CI — unset or one of "", 0, false, no keeps the gate open; any other truthy value disables clarify (CI runners can allocate PTYs even without a human present).
  3. PRAISON_OUTPUT_MODE — must not be json, stream-json, or actions (structured/machine consumers never prompt).
  4. sys.stdin.isatty() and sys.stdout.isatty() — both must return True (a real interactive terminal).

Python API

python
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

OptionDefaultDescription
workspaceos.getcwd()Working directory
enable_acpTrueEnable ACP tools
enable_editTrueEnable the edit_file / apply_patch targeted-edit tools
enable_lspTrueEnable LSP tools
enable_searchTrueEnable the ripgrep-backed grep / glob / ast_grep_search tools
enable_basicTrueEnable basic tools
enable_clarifyTrueEnable 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

ModeDescription
promptSafe default under praisonai code --safe. Every HIGH-risk tool call is approved per-call (prompts on a TTY, denies without one)
autoFull privileges – all operations auto-approved (opt-in via --no-safe / --dangerously-skip-approval)
manualAll write operations require explicit approval
scopedSafe 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

VariableDescription
PRAISON_TOOLS_DISABLEComma-separated groups to disable. Accepts: acp, edit, lsp, search, basic, clarify. Applied by ToolConfig.__post_init__, so direct constructions honor it too.
PRAISON_NO_CLARIFYSet 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_MODEWhen json, stream-json, or actions, the clarify tool is withheld so machine consumers never see a prompt.
CIAny truthy value (anything other than empty / 0 / false / no) withholds clarify, because CI runners can allocate pseudo-TTYs without a human present.
PRAISON_WORKSPACEOverride workspace path
PRAISON_APPROVAL_MODEauto, prompt (safe default), manual, scoped. Unknown values become prompt with a warning.
PYTHONIOENCODINGSet to utf-8 for Windows automation subprocess compatibility
PRAISON_DEBUGSet to 1 to enable debug logging

Debug Logging

Enable debug logging to troubleshoot tool execution:

bash
# Via CLI flag
praisonai chat --debug

# Via environment variable
export PRAISON_DEBUG=1
praisonai chat

# Via slash command during session
/debug

Debug 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 execution

Testing 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:

json
{
  "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:

csv
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_file

The 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:

  1. Expected Tools: Tools that MUST be called
csv
expected_tools,acp_create_file,acp_edit_file
  1. Forbidden Tools: Tools that MUST NOT be called
csv
forbidden_tools,acp_delete_file,acp_execute_command

Running Tool Tests

bash
# 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-artifacts

Inspecting Tool Traces

After running with --keep-artifacts, check the tool_trace.jsonl file:

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

Testing LSP Fallback

LSP tools gracefully fall back to regex when LSP server is unavailable:

csv
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_project

The 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:

bash
# Enable network operations
PRAISON_LIVE_NETWORK=1 praisonai test interactive --suite github-advanced

Command Allowlist

When PRAISON_LIVE_NETWORK=1 is set, the following commands are allowed:

CategoryCommands
Gitgit
GitHub CLIgh
Pythonpython, python3, pip, pip3, uv, pytest, ruff, black, mypy
Nodenode, npm, npx
Buildmake
Utilitiesecho, 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 bombs

Secret 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