Skip to content

Commit 4d6301a

Browse files
committed
[FEAT][Bash tool for agent.auto] [Docs]
1 parent 6adbe17 commit 4d6301a

8 files changed

Lines changed: 263 additions & 5 deletions

File tree

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# Run Bash Tool Tutorial
2+
3+
Use the **`run_bash`** tool so an autonomous agent can run shell commands on the terminal.
4+
5+
## When to use it
6+
7+
- The agent needs to run CLI commands (e.g. `ls`, `python script.py`, `git status`).
8+
- You use `max_loops="auto"` and want the agent to have terminal access.
9+
- You want to keep other tools restricted and only add bash execution.
10+
11+
## Enable the tool
12+
13+
Include `"run_bash"` in `selected_tools` when creating the agent:
14+
15+
```python
16+
from swarms import Agent
17+
18+
agent = Agent(
19+
agent_name="Terminal-Agent",
20+
agent_description="Agent that can run bash commands on the terminal",
21+
model_name="anthropic/claude-sonnet-4-5",
22+
max_loops="auto",
23+
dynamic_context_window=True,
24+
selected_tools=[
25+
"create_plan",
26+
"think",
27+
"subtask_done",
28+
"complete_task",
29+
"respond_to_user",
30+
"read_file",
31+
"list_directory",
32+
"run_bash",
33+
],
34+
)
35+
```
36+
37+
## Run a task
38+
39+
The agent will plan and call `run_bash` when it needs to run a command:
40+
41+
```python
42+
result = agent.run(
43+
task="Use the terminal to list the current directory, then run 'echo Hello from bash' and report the output."
44+
)
45+
print(result)
46+
```
47+
48+
## Tool parameters
49+
50+
| Parameter | Type | Description |
51+
|--------------------|---------|-------------|
52+
| `command` | string | The bash/shell command to run (e.g. `ls -la`, `python script.py`). |
53+
| `timeout_seconds` | integer | (Optional) Max seconds to wait; default is 60. |
54+
55+
Commands run in the agent’s workspace directory when available. Stdout and stderr are returned; long-running commands should use a higher `timeout_seconds` or be avoided.
56+
57+
## Example file
58+
59+
A full runnable example is in the repo:
60+
61+
```
62+
v9_examples/example_autonomous_looper_run_bash.py
63+
```
64+
65+
## See also
66+
67+
- [Autonomous Looper Tools](autonomous_looper_tools.md) – Configuring `selected_tools`
68+
- [Agent Reference](../swarms/structs/agent.md)`selected_tools` and autonomous loop

docs/examples/autonomous_looper_tools.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ The `selected_tools` parameter gives you fine-grained control over which tools t
2525
| `read_file` | Read the contents of a file |
2626
| `list_directory` | List files and directories in a path |
2727
| `delete_file` | Delete a file (use with caution) |
28+
| `run_bash` | Execute bash/shell commands on the terminal (returns stdout/stderr) |
29+
| `create_sub_agent` | Create specialized sub-agents for delegation |
30+
| `assign_task` | Assign tasks to sub-agents for asynchronous execution |
2831

2932
## Usage
3033

@@ -79,6 +82,30 @@ agent = Agent(
7982
)
8083
```
8184

85+
### File Operations + Terminal (run_bash)
86+
87+
Enable file operations and terminal command execution:
88+
89+
```python
90+
agent = Agent(
91+
agent_name="File-and-Terminal-Agent",
92+
model_name="anthropic/claude-sonnet-4-5",
93+
max_loops="auto",
94+
selected_tools=[
95+
"create_plan",
96+
"think",
97+
"subtask_done",
98+
"complete_task",
99+
"respond_to_user",
100+
"create_file",
101+
"update_file",
102+
"read_file",
103+
"list_directory",
104+
"run_bash",
105+
],
106+
)
107+
```
108+
82109
### Minimal Configuration
83110

84111
```python
@@ -153,6 +180,28 @@ analysis_agent = Agent(
153180
)
154181
```
155182

183+
### Terminal / DevOps Agent (With run_bash)
184+
For agents that need to run shell commands (e.g. scripts, CLI tools, git):
185+
186+
```python
187+
terminal_agent = Agent(
188+
agent_name="Terminal-Agent",
189+
max_loops="auto",
190+
selected_tools=[
191+
"create_plan",
192+
"think",
193+
"subtask_done",
194+
"complete_task",
195+
"respond_to_user",
196+
"read_file",
197+
"list_directory",
198+
"run_bash",
199+
],
200+
)
201+
```
202+
203+
See [Run Bash Tool Tutorial](autonomous_looper_run_bash_tutorial.md) for a step-by-step guide.
204+
156205
## Best Practices
157206

158207
1. **Start Restrictive**: Begin with a minimal set of tools and add more as needed
@@ -169,6 +218,7 @@ analysis_agent = Agent(
169218

170219
## See Also
171220

221+
- [Run Bash Tool Tutorial](autonomous_looper_run_bash_tutorial.md) – Using `run_bash` to execute terminal commands
172222
- [Autonomous Loop Documentation](./autonomous_loop.md)
173223
- [Agent Configuration Guide](./agent_configuration.md)
174224
- [Tool System Overview](./tools.md)

docs/mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,7 @@ nav:
328328
- Overview: "swarms_tools/overview.md"
329329
- BaseTool Reference: "swarms/tools/base_tool.md"
330330
- MCP Client Utils: "swarms/tools/mcp_client_call.md"
331+
- Run Bash Tool Tutorial: "examples/autonomous_looper_run_bash_tutorial.md"
331332

332333
- Vertical Tools:
333334
- Finance: "swarms_tools/finance.md"

docs/swarms/structs/agent.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ The `Agent` class establishes a conversational loop with a language model, allow
143143
| `mode` | `Literal["interactive", "fast", "standard"]` | Execution mode: "interactive" for real-time interaction, "fast" for optimized performance, "standard" for default behavior. |
144144
| `publish_to_marketplace` | `bool` | Boolean indicating whether to publish the agent's prompt to the Swarms marketplace. |
145145
| `marketplace_prompt_id` | `Optional[str]` | Unique UUID identifier of a prompt from the Swarms marketplace. When provided, the agent will automatically fetch and load the prompt as the system prompt. |
146-
| `selected_tools` | `Optional[Union[str, List[str]]]` | Controls which tools are available in autonomous mode (`max_loops="auto"`). Use `"all"` for all tools or provide a list of specific tool names. Available tools: `"create_plan"`, `"think"`, `"subtask_done"`, `"complete_task"`, `"respond_to_user"`, `"create_file"`, `"update_file"`, `"read_file"`, `"list_directory"`, `"delete_file"`, `"create_sub_agent"`, `"assign_task"`. |
146+
| `selected_tools` | `Optional[Union[str, List[str]]]` | Controls which tools are available in autonomous mode (`max_loops="auto"`). Use `"all"` for all tools or provide a list of specific tool names. Available tools: `"create_plan"`, `"think"`, `"subtask_done"`, `"complete_task"`, `"respond_to_user"`, `"create_file"`, `"update_file"`, `"read_file"`, `"list_directory"`, `"delete_file"`, `"run_bash"`, `"create_sub_agent"`, `"assign_task"`. |
147147

148148
## `Agent` Methods
149149

@@ -848,6 +848,7 @@ When `max_loops="auto"` and `interactive=False`, the agent has access to special
848848
| `read_file` | Read the contents of a file | `file_path` (str) |
849849
| `list_directory` | List files and directories in a specified path | `directory_path` (str, optional) |
850850
| `delete_file` | Delete a file (with safety checks) | `file_path` (str) |
851+
| `run_bash` | Execute a bash/shell command on the terminal (returns stdout/stderr) | `command` (str), `timeout_seconds` (int, optional, default 60) |
851852
| `create_sub_agent` | Create specialized sub-agents for task delegation | `agents` (array): list of agent specs with `agent_name` (str), `agent_description` (str), `system_prompt` (str, optional) |
852853
| `assign_task` | Assign tasks to sub-agents for asynchronous execution | `assignments` (array): list with `agent_id` (str), `task` (str), `task_id` (str, optional); `wait_for_completion` (bool, optional) |
853854

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
"""
2+
Example: Autonomous looper using the run_bash tool
3+
4+
This example shows an agent with max_loops="auto" that can execute
5+
terminal commands via the run_bash tool. The agent plans and runs
6+
shell commands to complete the task.
7+
"""
8+
9+
from swarms import Agent
10+
11+
# Agent with autonomous looping and terminal (bash) access
12+
agent = Agent(
13+
agent_name="Terminal-Agent",
14+
agent_description="Agent that can plan tasks and run bash commands on the terminal",
15+
model_name="anthropic/claude-sonnet-4-5",
16+
dynamic_temperature_enabled=True,
17+
max_loops="auto",
18+
dynamic_context_window=True,
19+
selected_tools=[
20+
"create_plan",
21+
"think",
22+
"subtask_done",
23+
"complete_task",
24+
"respond_to_user",
25+
"read_file",
26+
"list_directory",
27+
"run_bash",
28+
],
29+
top_p=None,
30+
)
31+
32+
if __name__ == "__main__":
33+
result = agent.run(
34+
task="Use the terminal to list the current directory, and see what files are in it."
35+
)
36+
print(result)

swarms/structs/agent.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
list_directory_tool,
7878
read_file_tool,
7979
respond_to_user_tool,
80+
run_bash_tool,
8081
update_file_tool,
8182
)
8283
from swarms.structs.conversation import Conversation
@@ -276,8 +277,8 @@ class Agent:
276277
Example: skills_dir="./skills" loads from ./skills/*/SKILL.md
277278
selected_tools (Union[str, List[str]]): Tools to enable for the autonomous looper when max_loops="auto".
278279
Available tools: "create_plan", "think", "subtask_done", "complete_task", "respond_to_user",
279-
"create_file", "update_file", "read_file", "list_directory", "delete_file", "create_sub_agent",
280-
"assign_task".
280+
"create_file", "update_file", "read_file", "list_directory", "delete_file", "run_bash",
281+
"create_sub_agent", "assign_task".
281282
Defaults to "all" (all tools enabled). Pass a list of tool names to restrict tools, or "all"
282283
for unrestricted access. Use this to control which tools the agent can use during autonomous execution.
283284
@@ -2297,6 +2298,9 @@ def _run_autonomous_loop(
22972298
"delete_file": lambda **kwargs: delete_file_tool(
22982299
self, **kwargs
22992300
),
2301+
"run_bash": lambda **kwargs: run_bash_tool(
2302+
self, **kwargs
2303+
),
23002304
"create_sub_agent": lambda **kwargs: create_sub_agent_tool(
23012305
self, **kwargs
23022306
),

swarms/structs/autonomous_loop_utils.py

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,14 @@
2020
- read_file: Read file contents
2121
- list_directory: List directory contents
2222
- delete_file: Delete files
23+
- run_bash: Execute bash/shell commands on the terminal
2324
- create_sub_agent: Create specialized sub-agents for delegation
2425
- assign_task: Assign tasks to sub-agents asynchronously
2526
"""
2627

2728
import asyncio
2829
import os
30+
import subprocess
2931
from typing import Any, Dict, List
3032
from loguru import logger
3133

@@ -392,6 +394,27 @@ def get_autonomous_planning_tools() -> List[Dict[str, Any]]:
392394
},
393395
},
394396
},
397+
{
398+
"type": "function",
399+
"function": {
400+
"name": "run_bash",
401+
"description": "Execute a bash/shell command on the terminal. Use this to run system commands, scripts, or any shell operations. Returns stdout and stderr.",
402+
"parameters": {
403+
"type": "object",
404+
"properties": {
405+
"command": {
406+
"type": "string",
407+
"description": "The bash/shell command to execute (e.g. 'ls -la', 'python script.py')",
408+
},
409+
"timeout_seconds": {
410+
"type": "integer",
411+
"description": "Maximum seconds to wait for the command (default: 60). Use to avoid hanging on long-running commands.",
412+
},
413+
},
414+
"required": ["command"],
415+
},
416+
},
417+
},
395418
{
396419
"type": "function",
397420
"function": {
@@ -802,6 +825,79 @@ def delete_file_tool(agent: Any, file_path: str, **kwargs) -> str:
802825
return error_msg
803826

804827

828+
def run_bash_tool(
829+
agent: Any, command: str, timeout_seconds: int = 60, **kwargs
830+
) -> str:
831+
"""
832+
Execute a bash/shell command on the terminal.
833+
834+
Args:
835+
agent: The agent instance
836+
command: The bash/shell command to execute
837+
timeout_seconds: Maximum seconds to wait (default: 60)
838+
**kwargs: Additional arguments
839+
840+
Returns:
841+
str: Command stdout and stderr, or error message
842+
"""
843+
try:
844+
# Run in process cwd (where the user started the script) so commands like
845+
# ls -la and python script.py see the project directory, not the agent workspace.
846+
result = subprocess.run(
847+
command,
848+
shell=True,
849+
capture_output=True,
850+
text=True,
851+
timeout=timeout_seconds,
852+
cwd=None, # use process current working directory
853+
encoding="utf-8",
854+
errors="replace",
855+
)
856+
857+
stdout = result.stdout or ""
858+
stderr = result.stderr or ""
859+
860+
output_parts = []
861+
if stdout:
862+
output_parts.append(f"stdout:\n{stdout}")
863+
if stderr:
864+
output_parts.append(f"stderr:\n{stderr}")
865+
if not output_parts:
866+
output_parts.append("(no output)")
867+
868+
result_msg = (
869+
f"Command exited with code {result.returncode}\n"
870+
+ "\n".join(output_parts)
871+
)
872+
873+
# Add to memory
874+
agent.short_memory.add(
875+
role="Terminal",
876+
content=f"Executed: {command[:100]}{'...' if len(command) > 100 else ''} -> exit {result.returncode}",
877+
)
878+
879+
if agent.verbose:
880+
logger.info(f"Executed bash command: {command[:80]}...")
881+
882+
return result_msg.strip()
883+
except subprocess.TimeoutExpired:
884+
error_msg = f"Error: Command timed out after {timeout_seconds} seconds"
885+
logger.error(error_msg)
886+
agent.short_memory.add(
887+
role="Terminal",
888+
content=f"Timeout: {command[:80]}...",
889+
)
890+
return error_msg
891+
except Exception as e:
892+
error_msg = f"Error executing command: {str(e)}"
893+
logger.error(error_msg)
894+
agent.short_memory.add(
895+
role="Terminal",
896+
content=f"Error: {error_msg}",
897+
)
898+
return error_msg
899+
900+
805901
def create_sub_agent_tool(
806902
agent: Any, agents: List[Dict[str, str]], **kwargs
807903
) -> str:

v9_examples/example_autonomous_looper_tools.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
- read_file: Read file contents
1616
- list_directory: List directory contents
1717
- delete_file: Delete files
18+
- run_bash: Execute bash/shell commands on the terminal
1819
"""
1920

2021
from swarms import Agent
@@ -47,10 +48,10 @@
4748
],
4849
)
4950

50-
# Example 3: Agent with file operations but no planning
51+
# Example 3: Agent with file operations and terminal (bash) access
5152
agent_file_ops = Agent(
5253
agent_name="File-Operations-Agent",
53-
agent_description="Agent with file operations capabilities",
54+
agent_description="Agent with file operations and terminal execution capabilities",
5455
model_name="anthropic/claude-sonnet-4-5",
5556
dynamic_temperature_enabled=True,
5657
max_loops="auto",
@@ -65,6 +66,7 @@
6566
"update_file",
6667
"read_file",
6768
"list_directory",
69+
"run_bash",
6870
],
6971
)
7072

0 commit comments

Comments
 (0)