Autonomy vs Interactive

Understand how autonomy and interactive modes differ, their tool systems, and the recommended architecture

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

TermDriverParadigmBest For
InteractiveπŸ‘€ HumanChat / TUIExploratory work, manual guidance
Iterative🧠 AgentAutonomy (mode=”iterative”)Self-correction, multi-step automation
Callerβ€”Single-turn responseQuick actions, direct pipelines

Execution Mode

AutonomyConfig has a mode field that controls execution behavior:

LevelDefault ModeBehavior
"suggest" (default)"caller"Single chat() β†’ AutonomyResult
"auto_edit""caller"Single chat() + auto-approve edits
"full_auto""iterative"run_autonomous() loop with completion detection

Execution Flow Comparison

Caller Mode (default for autonomy=True)

Diagram
Tool Executorchat()agent.start()UserTool Executorchat()agent.start()Usermode=”caller”agent.start(prompt)Single chat(prompt)Execute tool callsTool resultsLLM responseAutonomyResult(reason=”caller_mode”, iterations=1)

Iterative Mode (default for full_auto)

When mode="iterative", the agent runs a multi-turn loop with safety infrastructure:

Diagram
LLMInner Tool Loopchat()run_autonomous()agent.start()UserLLMInner Tool Loopchat()run_autonomous()agent.start()Usermode=”iterative”loop[Model decides what tools to call]Model stopped calling toolsTools used + response produced = doneagent.start(prompt)Route to autonomous loopchat(prompt)_chat_completion(messages, tools)prompt + toolstool_calls=[search, write_file]Execute tools, collect resultstool resultsSummary response (no more tools)Final responseResponse textβœ… AutonomyResult(reason=”tool_completion”)

Interactive Mode Flow

In interactive mode, the human drives the loop β€” each message is a single-turn chat() call:

Diagram
Tool Executorchat()AgentTUI / CLIUserTool Executorchat()AgentTUI / CLIUserloop[Human-driven loop]Start interactive sessionLoad tools (ACP + LSP + Basic)Create Agent(tools=[…])Type messageExpand @file mentionsagent.start(prompt)Single chat(prompt)Execute tool callsTool resultsLLM responseResponse stringStream response/exit

Feature Comparison

DimensionCaller Mode (autonomy=True)Iterative Mode (full_auto)Interactive (no autonomy)
Primary DriverApplication Code🧠 Agent (Internal Loop)πŸ‘€ Human (External Loop)
Turns1 (single chat())Up to max_iterationsSingle turn per interaction
Complexity MgtSimple pipelinesAutomated self-correctionManual refinement
Return typeAutonomyResultAutonomyResultstr
Self-correctionβŒβœ… Doom loop + recovery❌ (Human corrects)
Session persistenceManualAuto-saves each iterationManual
ObservabilityStandardBuilt-in event emissionStandard

Speed Profile

Init Overhead (one-time)

ComponentCostNotes
AutonomyConfig()~0msSimple dataclass
AutonomyTrigger()~1-2msLazy imports EscalationTrigger
DoomLoopTracker()~1msLazy imports DoomLoopDetector
FileSnapshot~50-200msOnly if track_changes=True
ObservabilityHooks~1msOnly if observe=True

Per-Iteration Overhead

OperationCost
Timeout check~0ΞΌs
Doom-loop check~0.1ms
Action recording~0.1ms
Completion detection~0.1ms
Session auto-save0-5ms
Total~0.5ms

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

MetricNon-AutonomyAutonomy
Minimum LLM calls11 (if completion detected on first turn)
Maximum LLM calls120 (default max_iterations)
Typical for multi-step task1 (all tools in one turn)1-3 (re-injects if not “done”)
Overhead per call0~0.5ms

Important Behavioral Differences

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:

Diagram

CLI Wrapper (praisonai)

Core SDK (praisonaiagents)

uses

extends

tools=[…]

tools=[…]

tools/profiles.py
ToolProfile system
6 built-in profiles

AUTONOMY_PROFILE
16 tools (composite)

tools/init.py
TOOL_MAPPINGS: 50+ tools
(lazy-load registry)

agent.py
autonomy default injection

_resolve_tool_names()
(string β†’ function)

interactive_tools.py
TOOL_GROUPS: 13 tools

tracker.py
AUTONOMY_DEFAULT_TOOLS: 30 tools

register_profile()
ACP + LSP profiles

What each layer provides

Built-in ToolProfiles

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

ProfileToolsDescription
code_intelligence3ast-grep search, rewrite, scan
file_ops7read, write, list, copy, move, delete, get_file_info
shell3execute_command, list_processes, get_system_info
web3internet_search, search_web, web_crawl
code_exec4execute_code, analyze_code, format_code, lint_code
schedule3schedule_add, schedule_list, schedule_remove
autonomy16Composite: file_ops + shell + web + code_intelligence

Tools by entry point

Entry PointTools AvailableSource
praisonai tui13 (ACP + LSP + Basic)CLI wrapper
praisonai "prompt"13 + autonomy (16)CLI wrapper + SDK
praisonai tracker run30 (expanded set)tracker.py
Agent(autonomy=True) in Python16 (AUTONOMY_PROFILE)Core SDK
Agent() in Python0 (user-provided only)β€”

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

SDK independence

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.

Composable toolsets

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.

Single source of truth

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

ModeBest ForExample PromptWhat Happens
No autonomyQuestions, explanations, advice“Explain authentication patterns”Agent answers from knowledge β€” doesn’t touch files or run tools
Caller (default)Single-shot automation, pipelines“Search for X and save results to file”Agent uses tools in one turn, returns AutonomyResult with metadata
IterativeMulti-step self-correction, buildβ†’testβ†’fix“Refactor auth module and verify tests pass”Agent loops until task is complete, with doom loop protection

Extending Tools

Using ToolProfiles (recommended)

Combine built-in profiles or register custom ones:

python
from praisonaiagents.tools.profiles import (
    resolve_profiles, register_profile, ToolProfile
)

# Combine built-in profiles
tools = resolve_profiles("file_ops", "web", "shell")
agent = Agent(tools=tools)

# Register a custom profile (e.g., from CLI wrapper)
register_profile(ToolProfile(
    name="acp",
    tools=["acp_create_file", "acp_edit_file",
           "acp_delete_file", "acp_execute_command"],
    description="Agentic Change Plan tools",
))

# Now use it alongside built-in profiles
tools = resolve_profiles("autonomy", "acp", "lsp")

Adding tools for CLI users

Add tools to interactive_tools.py:

python
# In praisonai/cli/features/interactive_tools.py
TOOL_GROUPS = {
    "basic": [read_file, write_file, ...],
    "acp": [acp_create_file, ...],
    "lsp": [lsp_list_symbols, ...],
    "my_group": [my_custom_tool],  # Add new group
}

Adding tools for SDK users

Pass tools directly β€” the SDK is tool-agnostic:

python
from praisonaiagents import Agent

def my_tool(query: str) -> str:
    """My custom tool."""
    return "result"

agent = Agent(
    instructions="Use tools wisely",
    tools=[my_tool],
    autonomy=True  # Gets 16 AUTONOMY_PROFILE tools + your tools
)

Related