Skip to main content
PraisonAI provides two primary execution approaches: Autonomy (agent-driven results) and Interactive (human-driven sessions). Understanding the distinction between Iterative (autonomous loop) and Interactive (manual loop) is key to building complex workflows.

At a Glance: Iterative vs. Interactive

While the names sound similar, they represent the two sides of “who drives the loop”:

Execution Mode

AutonomyConfig has a mode field that controls execution behavior:
autonomy=True now defaults to caller mode — one chat() call wrapped in AutonomyResult. No wasteful iteration loop. Use mode="iterative" or level="full_auto" for multi-turn autonomous loops.

Execution Flow Comparison

Caller Mode (default for autonomy=True)

Iterative Mode (default for full_auto)

When mode="iterative", the agent runs a multi-turn loop with safety infrastructure:
Key insight: All three modes use the same inner tool loop. The difference is what wraps it — nothing (interactive), an AutonomyResult wrapper (caller), or a multi-turn retry loop (iterative).

Interactive Mode Flow

In interactive mode, the human drives the loop — each message is a single-turn chat() call:
The Loop Driver Distinction:
  • Interactive Mode: The human provides the prompt, the agent responds once, and the human decides the next prompt.
  • Iterative Mode: The agent provides its own prompts to itself in a loop until it detects the task is complete.
  • Caller Mode: A simplified “one-shot” interaction that returns rich metadata.

Feature Comparison

Key insight: Caller mode gives you AutonomyResult metadata (.success, .iterations, .duration_seconds) without the overhead of the iterative loop — ideal for most use cases.

Speed Profile

Init Overhead (one-time)

With autonomy=True (defaults), init overhead is < 5ms since track_changes=False and observe=False by default.

Per-Iteration Overhead

Per-iteration overhead is ~0.5ms — negligible compared to LLM API calls (typically 1-30 seconds each). The real speed difference is the number of LLM calls, not framework overhead.

End-to-End Comparison

Important Behavioral Differences

Return type: AutonomyResult.__str__() returns .output, so print(result) works the same. But code that does if result: or len(result) may break — AutonomyResult is always truthy and has no __len__. Use str(result) or result.output.
Early completion risk: If the LLM says "I'm done searching" mid-task, keyword-based detection might stop early. For multi-step tasks, the tool completion signal is the primary mechanism — the model naturally stops calling tools when done. For explicit control, use structured completion signals:
Approval with autonomy=True: Default level is "suggest", which does NOT auto-approve tools. Only level="full_auto" auto-wires AutoApproveBackend.

Two-Layer Tool Architecture

Tools are provisioned at two independent layers. The CLI wrapper assembles tool lists and passes them as tools=[...] to the SDK’s Agent() constructor:

What each layer provides

ACP Tools Performance: ACP tools (acp_edit_file, acp_execute_command) go through a complex orchestration flow and can be slow (174s+ per operation). In autonomy mode (--autonomy full_auto), ACP tools are disabled by default for speed. Use --acp flag to explicitly enable them when needed.

CLI Wrapper (praisonai)

13 tools via get_interactive_tools():
  • ACP (4): create/edit/delete files, execute commands (disabled by default in autonomy)
  • LSP (4): symbols, definitions, references, diagnostics
  • Basic (5): read/write files, list, execute, search
Used by: praisonai tui, praisonai "prompt"

Core SDK (praisonaiagents)

16 tools when autonomy=True via AUTONOMY_PROFILE:
  • file_ops (7): read/write/list/copy/move/delete/info
  • shell (3): execute_command, list_processes, get_system_info
  • web (3): internet_search, search_web, web_crawl
  • code_intelligence (3): ast_grep search/rewrite/scan
Used by: Agent(autonomy=True) in Python

Built-in ToolProfiles

The SDK ships with composable profiles in tools/profiles.py:

Tools by entry point

Design Principles

The current architecture follows a layered separation pattern:
1

Core SDK stays minimal

The praisonaiagents package provides the agent runtime, tool execution, and LLM integration — but does not bundle default tools. This keeps the SDK lightweight and avoids opinionated defaults.
2

CLI wrapper adds batteries

The praisonai wrapper package adds ACP, LSP, file operations, and search tools for CLI users. It assembles toolsets and passes them as tools=[...] to the Agent constructor.
3

Tools are data, not hardcoded

Interactive tools are defined as groups in interactive_tools.py with a TOOL_GROUPS dictionary. New tools are added to a group, and all consumers automatically get them.

Why this is the best approach

The Core SDK has zero dependency on the CLI wrapper. Users embedding praisonaiagents in their own applications bring exactly the tools they need — no surprise defaults, no bloat.
Each entry point assembles its own toolset. praisonai tui loads ACP + LSP + Basic. praisonai tracker run loads a broader set. SDK users pass their own tools. This is intentional — different contexts need different capabilities.
interactive_tools.py with get_interactive_tools() is the canonical provider. Both tui/app.py and main.py call this single function. Adding a new interactive tool means editing one file.

When to Use Each Mode

No Autonomy

Fastest — agent explains but doesn’t act.

Caller Mode

One turn — agent acts immediately with tools.

Iterative Mode

Multi-turn — agent self-corrects until done.

Extending Tools

Combine built-in profiles or register custom ones:

Adding tools for CLI users

Add tools to interactive_tools.py:

Adding tools for SDK users

Pass tools directly — the SDK is tool-agnostic:

Autonomy Concepts

Configuration, stages, and doom loop detection

Autonomous Loops

Execution loop details and async support

Interactive Tools

ACP, LSP, and basic tool reference

Autonomy Modes

Suggest, auto-edit, and full-auto modes