Skip to main content
Set max_loops="auto" and the agent stops running a fixed number of loops. Instead, agent.run() hands the task to the autonomous loop. The agent writes a plan, works through it one subtask at a time with built-in tools and your own, and finishes with a summary. The loop lives in swarms/agents/autonomous_loop.py (AutonomousAgentLoop). Its tool schemas, prompts and tool handlers live in swarms/structs/autonomous_loop_utils.py.

Quick start

output_type="final" returns only the closing summary. With the default, "str-all-except-first", you get the whole conversation as a string. See Return value.

How a run works

Every call to run() starts a fresh loop. The plan, subtask statuses and think counter are reset, and the request transcript starts from the messages you pass to run() (if any) followed by the task.
Only the task and run(messages=...) seed the transcript. Turns from earlier runs, the constructor’s messages, and a MEMORY.md preload are kept in agent.short_memory, but autonomous runs do not send them. Pass prior turns to run(messages=...) when the agent should continue from them.
1

Planning

The agent sends the task with a planning prompt and asks the model to call create_plan. Each step in the plan has a step_id, a description, a priority (low, medium, high or critical) and optional dependencies. Dependencies that name an unknown step, or the step itself, are dropped with a warning.Planning ends on the first response that contains a tool call. Only create_plan and, when handoffs is set, handoff_task run in this phase. If no attempt produces a tool call within max_planning_attempts requests, the run raises an error.
2

Subtask execution

Your own tools are added to the tool list after planning. The loop then picks the first pending subtask whose dependencies have all completed, in plan order. priority is recorded but does not reorder the plan. A subtask whose dependency failed or was skipped is marked skipped.For each subtask the agent sends one execution prompt, then iterates. Each iteration checks the context compressor, calls the model once, and runs every tool call in the reply. A subtask ends when:
  • the model calls subtask_done with that subtask’s step_id (success=true marks it completed, false marks it failed)
  • its status changes to completed or failed some other way
  • it uses up max_subtask_loops iterations, in which case it is marked failed with the reason recorded
When a built-in tool raises, the run continues. The error goes back to the model as that tool’s result (ERROR: ... failed with ...) so it can correct itself on the next turn. Calls to your own tools that fail are retried up to tool_retry_attempts times.The model can call create_plan again at any point to revise the plan. Steps are merged by step_id. Finished steps keep their status and summary, pending steps are updated, and pending steps left out of the new list are dropped.Execution ends when every subtask is completed, failed or skipped, when no subtask can run, or once max_subtask_iterations subtasks have run. A successful complete_task call during execution ends it at once and moves to the summary.
3

Final summary

The agent makes one more model call with a summary prompt that asks for complete_task. If the model calls it, a “Task Completion Summary” with a breakdown of every subtask is recorded. If not, the agent assembles a “Task Execution Summary” from the subtask statuses and the model’s reply.Both paths return the conversation shaped by output_type.

Iteration budgets

Three constructor parameters bound the loop. Each must be at least 1, or Agent() raises ValueError.
int
default:"5"
How many requests the planning phase may make to get a plan before the run fails.
int
default:"100"
Ceiling on how many subtasks the execution phase runs across the whole run. Each pass of the outer loop runs one subtask. Once that many have run, execution stops and the run moves to the final summary. It matters most when the model keeps adding steps by revising the plan.
int
default:"20"
Ceiling on model calls spent inside any one subtask. A subtask that reaches it is marked failed, and subtasks that depend on it are skipped.
Worst case, a run makes max_planning_attempts + max_subtask_iterations × max_subtask_loops + 1 model calls. With the defaults that is 5 + 2,000 + 1. Extra calls on top of that come from:
  • tool_call_summary=True (the default), which summarizes each batch of your own tool results with a separate model call
  • the context compressor, which makes one summarizer call each time it fires
  • sub-agents, which run on their own budgets
The think streak limit is an attribute, not a constructor parameter. agent.max_consecutive_thinks defaults to 2. When the model calls think that many times in a row, the loop adds a message telling it to act, then resets the count.

Built-in tools

These are the tools the loop adds. Relative paths in the file and search tools resolve against the agent’s workspace, agent.workspace.dir, which is $WORKSPACE_DIR/agents/{agent-name}-{id12}/. When WORKSPACE_DIR is unset it defaults to ./agent_workspace. Absolute paths are used as given.

Control

Files

Shell

run_bash runs in the Python process’s current working directory, not the agent workspace. Before running, it checks each command:
  • Commands longer than 512 characters are refused. When the command contains a heredoc or a redirect, the refusal tells the model to write the content with create_file or update_file instead.
  • Commands that match a blocklist are refused. The blocklist covers recursive rm, piping into a shell or interpreter, raw disk writes (including > /dev/null), sudo and other privilege changes, shutdown and reboot, reading /etc/passwd-style files, curl -d and similar exfiltration, printenv, and redirects into system folders such as /etc and /usr.
The blocklist is a guard, not a sandbox. File tools accept absolute paths and run_bash runs with your process’s permissions. Run untrusted tasks in a container or a throwaway working directory, or leave run_bash and delete_file out of selected_tools.

Sub-agents

A sub-agent uses the parent’s model_name and gets the parent’s tools. It runs with max_loops=5 when it has tools and max_loops=1 when it does not, never "auto", so sub-agents cannot start loops of their own. print_on and verbose follow the parent.

Tools added by other settings

  • handoff_task, when handoffs is set. The handoff roster is appended to the system prompt.
  • tool_search, when dynamic_tools=True. Only create_plan, think, subtask_done, complete_task and respond_to_user stay loaded, and the rest are found on demand. After create_plan, up to eight tools that match the plan are loaded ahead of time. See Dynamic Tool Loading.
  • Tools from your MCP servers (mcp_url, mcp_urls, mcp_config, mcp_configs), callable during execution.
  • Your own tools, added once planning is done.

Choose tools with selected_tools

selected_tools="all" (the default) offers every built-in tool. Pass a list to keep only the ones you name. The filter applies to built-in tools only. Your own tools, MCP tools and handoff_task are added regardless.
Keep create_plan and subtask_done in the list. Without create_plan the agent has no way to make a plan. Without subtask_done a subtask can only end by using up max_subtask_loops, which marks it failed. Leaving out complete_task is safe: the agent then builds the summary itself.
Listing "think" is not enough to get the think tool. It also needs think_tool=True.

The think tool

bool
default:"False"
Offers the think tool in autonomous runs. A think call costs a full model round-trip to produce reasoning most models can write inline next to their actions, so it is off by default. When it is off, the system prompt tells the model the tool is unavailable and to reason inline.
thinking_tokens does not remove the think tool. If you set think_tool=True while thinking_tokens is set (it defaults to 1024), the agent logs a suggestion to turn think_tool off, because the model already reasons natively.

Output caps

read_file, run_bash, grep and glob cap their output by tokens, counted with the agent’s own model tokenizer. The budget is a quarter of context_length. When the agent has no context length to share, the budget is 4,096 tokens. The loop sends its whole transcript on every request, so one oversized result would be paid for on every later call. Cut output ends with a marker such as:
The marker tells the model how much it is missing so it can narrow the search. read_file still records the file’s full length in memory. list_directory and your own tools are not capped.
context_length defaults to the model’s input window, which can be very large (over a million tokens for gpt-5.4). Set context_length lower to tighten both the output caps and the point at which compression fires.

Context compression between subtasks

With context_compression=True (the default), the loop checks the agent’s ContextCompressor at the top of every subtask iteration. That is the one point where every tool call has been answered, so the transcript can be replaced safely. When the conversation reaches 90% of context_length, the compressor:
  1. Summarizes the conversation with one model call.
  2. Compacts agent.short_memory to the summary. With persistent_memory=True, it also archives and resets MEMORY.md.
  3. Rebuilds the request transcript as the summary plus the prompt for the subtask in progress.
Compression does not run during planning or the final summary. Set context_compression=False to turn it off. See Agent Memory for the compressor’s settings.

System prompt

When max_loops="auto", Agent() appends the autonomous-loop prompt to your system_prompt. That prompt describes the three phases and the control tools. When think_tool=False, it ends with a note that the think tool is unavailable. The prompt carries a Time: line with the current date and time. It is built when the agent is constructed, not when swarms is imported, so each new agent gets the current time. A long-lived agent keeps the time it was built with.

Streaming

run_stream() and arun_stream() go through run(), so an agent with max_loops="auto" enters the autonomous loop when streamed. You receive the text tokens of every model call in the loop: planning, each subtask iteration and the summary.
You can also pass streaming_callback to run(), or set it on the agent.

Return value

run() returns agent.short_memory shaped by output_type, whichever way the summary was produced.

Keep a run bounded

  • Lower the budgets. max_subtask_loops caps the cost of one stuck subtask. max_subtask_iterations caps how many subtasks run.
  • Ask for a small plan in the task itself, for example “Keep the plan to three subtasks.”
  • Restrict selected_tools to what the task needs.
  • Set tool_call_summary=False to skip the extra summary call after each batch of your tools.
  • Set context_length to tighten output caps and compression.
  • Point WORKSPACE_DIR at a scratch folder, and run run_bash tasks from a disposable working directory.
  • Read agent.usage after a run to see the provider’s token counts for the agent’s own model calls. Sub-agents track their own usage. See Token Usage.
stopping_condition and stopping_func apply to integer max_loops only. The autonomous loop does not check them. This agent has one custom tool, three iteration budgets and a short tool list:

Autonomous Looper Tools

Example selected_tools setups for common agent roles.

Autonomous Looper with Bash

Give an autonomous agent terminal access with run_bash.

Dynamic Tool Loading

Defer tool schemas behind tool_search.

Agent Memory

Context compression, MEMORY.md and where files are written.

ToolManager

How the agent sets up, parses and runs tool calls.

Agent Reference

Every Agent constructor parameter.