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 torun() 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_donewith that subtask’sstep_id(success=truemarks itcompleted,falsemarks itfailed) - its status changes to
completedorfailedsome other way - it uses up
max_subtask_loopsiterations, in which case it is markedfailedwith the reason recorded
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 least1, 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.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
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
Search
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_fileorupdate_fileinstead. - Commands that match a blocklist are refused. The blocklist covers recursive
rm, piping into a shell or interpreter, raw disk writes (including> /dev/null),sudoand other privilege changes, shutdown and reboot, reading/etc/passwd-style files,curl -dand similar exfiltration,printenv, and redirects into system folders such as/etcand/usr.
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, whenhandoffsis set. The handoff roster is appended to the system prompt.tool_search, whendynamic_tools=True. Onlycreate_plan,think,subtask_done,complete_taskandrespond_to_userstay loaded, and the rest are found on demand. Aftercreate_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.
"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:
read_file still records the file’s full length in memory. list_directory and your own tools are not capped.
Context compression between subtasks
Withcontext_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:
- Summarizes the conversation with one model call.
- Compacts
agent.short_memoryto the summary. Withpersistent_memory=True, it also archives and resetsMEMORY.md. - Rebuilds the request transcript as the summary plus the prompt for the subtask in progress.
context_compression=False to turn it off. See Agent Memory for the compressor’s settings.
System prompt
Whenmax_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.
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_loopscaps the cost of one stuck subtask.max_subtask_iterationscaps how many subtasks run. - Ask for a small plan in the task itself, for example “Keep the plan to three subtasks.”
- Restrict
selected_toolsto what the task needs. - Set
tool_call_summary=Falseto skip the extra summary call after each batch of your tools. - Set
context_lengthto tighten output caps and compression. - Point
WORKSPACE_DIRat a scratch folder, and runrun_bashtasks from a disposable working directory. - Read
agent.usageafter 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:
Related
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.