Skip to main content
Autonomous loops let agents work iteratively on complex tasks, automatically stopping when they signal completion or reach limits.
Mode matters: Autonomous loops use mode="iterative". This is the default for level="full_auto". With autonomy=True (default level), mode is "caller" (single chat) — set mode="iterative" explicitly or use level="full_auto" to enable loops.
The most common completion path is tool completion — the model calls tools to do the work, then produces a summary without requesting more tools. This is the same mechanism ChatGPT and Claude use.

Quick Start

from praisonaiagents import Agent

# full_auto defaults to mode="iterative"
agent = Agent(
    name="builder",
    instructions="Build the requested feature",
    autonomy="full_auto"
)

result = agent.start("Create a REST API with user authentication")

print(f"Success: {result.success}")
print(f"Iterations: {result.iterations}")
Unified API: When mode="iterative", agent.start() automatically runs the autonomous loop with 16 default tools (file ops, shell, web search, ast-grep) via the AUTONOMY_PROFILE. No need to call run_autonomous() separately!

How It Works

Behind the scenes: The inner tool loop handles ALL tool calls in a single turn. The model keeps calling tools until it’s satisfied, then stops. The outer loop detects this and returns immediately — no unnecessary extra iterations.

Key Features

Completion Promise

Agent signals “done” with a promise tag containing TEXT

Context Clearing

Fresh memory each iteration forces file-based state

Doom Loop Detection

Automatically stops on repeated identical actions

Iteration Limits

Prevents runaway execution with configurable max

Configuration

AutonomyConfig Options

OptionTypeDefaultDescription
max_iterationsint20Maximum loop iterations
completion_promisestrNoneText to detect in promise tags
clear_contextboolFalseClear chat history between iterations
doom_loop_thresholdint3Repeated actions before stopping
levelstr"suggest"Autonomy level: suggest, auto_edit, full_auto
auto_escalateboolTrueAutomatically escalate task complexity
observeboolFalseEmit observability events

Using Config Dict

agent = Agent(
    name="worker",
    instructions="Complete the task",
    autonomy={
        "max_iterations": 30,
        "completion_promise": "FINISHED",
        "clear_context": True,
        "doom_loop_threshold": 5
    }
)

CLI Usage

praisonai loop "Build a REST API" -n 5

CLI Options

FlagDescription
-n, --max-iterationsMaximum iterations (default: 10)
-p, --completion-promisePromise text to signal completion
-c, --clear-contextClear chat history between iterations
-t, --timeoutTimeout in seconds
-m, --modelLLM model to use
-v, --verboseShow verbose output

Result Object

result = agent.start(prompt)  # when autonomy=True

# Available fields
result.success          # bool - Task completed successfully
result.output           # str - Final response
result.completion_reason # str - "tool_completion", "promise", "caller_mode", "max_iterations", "doom_loop", "timeout", "error"
result.iterations       # int - Number of iterations executed
result.duration_seconds # float - Total execution time
result.started_at       # str - ISO 8601 timestamp when execution started
result.actions          # list - Actions taken each iteration
result.error            # str | None - Error message if failed

How Completion Detection Works

Completion Reasons

The model used tools to complete the task and then produced a summary response without requesting more tools. This is the most reliable completion signal — it’s the same mechanism used by ChatGPT and all major LLM APIs.
Agent was in caller mode (autonomy=True default). Single chat() call wrapped in AutonomyResult.
Agent output contained a promise tag with TEXT matching the configured promise.
Agent output contained completion keywords like “task completed” or “done”.
The model produced text without calling any tools for 2+ consecutive turns — indicates it has nothing left to do.
Reached the maximum iteration limit without completion signal.
Detected repeated identical actions (agent stuck in a loop).
Execution exceeded the configured timeout.
Doom loop recovery exhausted — task needs human guidance.
An error occurred during execution.

Best Practices

1

Use Completion Promises

Always set a completion_promise for reliable termination instead of relying on keyword detection.
2

Enable Context Clearing for Long Tasks

Use clear_context=True for tasks that should rely on file state rather than conversation memory.
3

Set Reasonable Limits

Configure max_iterations based on task complexity. Start low and increase if needed.
4

Include Promise in Instructions

Tell the agent to output the promise tag when done:
instructions="When finished, output DONE in a promise tag"

Async Execution

Run autonomous loops asynchronously for concurrent agent execution:
import asyncio
from praisonaiagents import Agent

async def main():
    agent = Agent(
        name="async_worker",
        instructions="Complete the task. Output <promise>DONE</promise> when finished.",
        autonomy={
            "max_iterations": 10,
            "completion_promise": "DONE",
        }
    )
    
    # astart() automatically uses autonomous loop when autonomy=True
    result = await agent.astart("Build a calculator")
    
    print(f"Success: {result.success}")
    print(f"Started: {result.started_at}")

asyncio.run(main())
When autonomy=True, astart() automatically routes to the async autonomous loop, enabling true concurrent execution of multiple agents.

Memory Integration

Autonomous loops automatically save sessions between iterations when memory is enabled. This ensures progress is persisted even if the loop is interrupted.
from praisonaiagents import Agent

agent = Agent(
    name="persistent_worker",
    instructions="Work on the task. Output <promise>DONE</promise> when finished.",
    autonomy={
        "completion_promise": "DONE",
        "max_iterations": 20,
    },
    memory=True,
    auto_save="project_session",
)

# Unified API — start() handles everything!
result = agent.start("Refactor the auth module")
# Session is auto-saved after every iteration
_auto_save_session() is a no-op when memory or auto_save is not configured, so there is zero overhead for agents without memory.

Example: Self-Improving Code

from praisonaiagents import Agent

agent = Agent(
    name="improver",
    instructions="""You are a code improvement agent.
    
    1. Read the current code
    2. Identify one improvement
    3. Make the change
    4. Verify it works
    5. If no more improvements needed, output <promise>OPTIMIZED</promise>
    """,
    autonomy={
        "max_iterations": 10,
        "completion_promise": "OPTIMIZED",
        "clear_context": True,
    },
    tools=[read_file, write_file, run_tests]
)

# Just call start() - autonomy config handles everything!
result = agent.start("Optimize the performance of src/utils.py")

if result.success:
    print(f"Code optimized in {result.iterations} iterations")
    print(f"Started: {result.started_at}")
else:
    print(f"Stopped: {result.completion_reason}")