ag2-shell-tool
Skill252 starsChanged 6 months agoApache-2.0View on GitHub
Give an AG2 beta `Agent` the ability to run shell commands. Covers `LocalShellTool` (client-side `subprocess`, works with any provider) and the provider-native `ShellTool` (Anthropic / OpenAI execution). Use when the user wants the Agent to execute commands, build/test code, manage files, or operate on a workspace. Always pair with sandboxing — `allowed`, `blocked`, `ignore`, or `readonly`.
- Reads credentials
- Deletes or force-pushes
We split this skill into the rules it gives an agent
1 rule. About 0 are common, 0 are distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈0
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 48
When a path is given, the directory is created if it does not exist and is not deleted on exit.
≈ “Common” is an estimate: at least 1 in 5 of the 308,232 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Shell tools
When to use
Two distinct tools, both named "shell" — pick deliberately:
| Need | Use | Why |
| Works with any model provider; full control over what runs and where | LocalShellTool | Client-side subprocess. You own the sandbox. |
| Provider-managed sandbox (container, network policy) on Anthropic / OpenAI | ShellTool | Server-side execution. No local subprocess. |
LocalShellTool is the workhorse. Reach for it unless you specifically need provider-managed isolation and you're on Anthropic or OpenAI.
60-second recipe — LocalShellTool
from autogen.beta import Agent
from autogen.beta.config import AnthropicConfig
from autogen.beta.tools import LocalShellTool
agent = Agent(
"coder",
"You write and run Python code.",
config=AnthropicConfig(model="claude-sonnet-4-6"),
tools=[LocalShellTool()],
)
reply = await agent.ask("Write a hello world script and run it.")
print(await reply.content())LocalShellTool is provider-agnostic — swap AnthropicConfig for OpenAIConfig(model="gpt-4.1"), GeminiConfig(model="gemini-2.5-pro"), etc. Make sure you've installed the matching ag2[<provider>] extra and set the matching env var (see ag2-quickstart → Prerequisites).
With no arguments, LocalShellTool creates a temporary working directory (prefixed ag2_shell_) and cleans it up when the process exits. Pass a path to use a specific directory:
from pathlib import Path
LocalShellTool("/tmp/my_project")
LocalShellTool(Path("/tmp/my_project"))When a path is given, the directory is created if it does not exist and is not deleted on exit. Inspect the resolved working directory via tool.workdir.
Sandboxing (LocalShellEnvironment)
For anything beyond a throwaway demo, use LocalShellEnvironment and lock down what the agent can do. Filtering is applied in this order on every call:
allowed— if set, the command must match at least one prefix.blocked— if set, the command must not match any prefix.ignore— literal path tokens in the command are checked against gitignore-style patterns; matches return"Access denied: <path>".- Execute via
subprocess.run.
from autogen.beta.tools import LocalShellTool
from autogen.beta.tools.shell import LocalShellEnvironment
sh = LocalShellTool(
LocalShellEnvironment(
path="/tmp/my_project",
allowed=["python", "uv run", "git"],
blocked=["rm -rf", "curl", "wget"],
ignore=["**/.env", "*.key", "secrets/**"],
timeout=30,
max_output=50_000,
)
)Read-only mode
For inspection-only access (cat, head, tail, ls, grep, find, git log, git diff, git status, …):
from autogen.beta.tools import LocalShellTool
from autogen.beta.tools.shell import LocalShellEnvironment
sh = LocalShellTool(LocalShellEnvironment(path="/my/codebase", readonly=True))Pass an explicit allowed=[...] to override the built-in read-only allowlist.
LocalShellEnvironment parameter reference
| Parameter | Default | Description |
path | None | Working dir. None → temp dir, deleted on exit |
cleanup | None | None → auto (True when path=None, False otherwise). Deletes path on process exit |
allowed | None | Whitelist of command prefixes. None → all commands allowed |
blocked | None | Blacklist of command prefixes |
ignore | None | Gitignore-style path patterns; matches block the command |
readonly | False | When True and allowed unset, restricts to a built-in read-only list |
env | None | Extra env vars merged into each command |
timeout | 60 | Per-command timeout in seconds (returns "Command timed out after Ns [exit code: 124]") |
max_output | 100_000 | Max characters returned (truncated output is suffixed [truncated: …]) |
Stateful multi-turn workspaces
Files persist in workdir across ask() calls, so the agent can build on prior work:
from autogen.beta.tools import LocalShellTool
from autogen.beta.tools.shell import LocalShellEnvironment
sh = LocalShellTool(LocalShellEnvironment(path="/tmp/counter_demo"))
agent = Agent("coder", "You manage files.", config=config, tools=[sh])
reply1 = await agent.ask("Create counter.txt with value 0")
reply2 = await reply1.ask("Increment the counter by 1")
reply3 = await reply2.ask("Read the counter and tell me the value")Provider-native ShellTool (Anthropic / OpenAI)
from autogen.beta.tools import ShellTool
agent = Agent("devops", config=AnthropicConfig(model="claude-sonnet-4-6"), tools=[ShellTool()])OpenAI lets you configure the execution environment:
from autogen.beta.config import OpenAIResponsesConfig
from autogen.beta.tools import ShellTool
from autogen.beta.tools.builtin.shell import ContainerAutoEnvironment, NetworkPolicy
agent = Agent(
"devops",
config=OpenAIResponsesConfig(model="gpt-4.1"),
tools=[
ShellTool(
environment=ContainerAutoEnvironment(
network_policy=NetworkPolicy(allowed_domains=["pypi.org"]),
),
),
],
)Environment options:
| Environment | Description |
ContainerAutoEnvironment | Provider-managed container with optional network policy |
ContainerReferenceEnvironment | Reference an existing container by ID |
ShellTool is not supported on Gemini — the request will raise UnsupportedToolError.
LocalShellTool vs ShellTool
LocalShellTool | ShellTool | |
| Execution | Client-side subprocess | Provider-side container |
| Provider support | Any provider | Anthropic, OpenAI |
| Environment control | Full (allowed, blocked, ignore, readonly, …) | Limited (provider-dependent) |
| Local FS access | Yes (you choose what's exposed) | No |
| Network control | Via blocked / allowed patterns | OpenAI: NetworkPolicy |
| Import | from autogen.beta.tools import LocalShellTool (env: from autogen.beta.tools.shell import LocalShellEnvironment) | from autogen.beta.tools import ShellTool |
Going deeper
website/docs/beta/tools/local_shell.mdx— fullLocalShellToolreference, command-filtering semantics.website/docs/beta/tools/builtin_tools.mdx#shell— provider-nativeShellToolsetup and environment configs.- For human-approval gating before each shell call, layer
approval_required()middleware (seeag2-hitl).
Common pitfalls
- Forgetting sandboxing in production —
LocalShellTool()with no environment runs anything anywhere with a 60s timeout. Setallowed,blocked, orreadonlyfor any non-trivial use. ignoreonly checks literal paths in the command string — variable substitution, command substitution (`cat secrets.key`), and dynamic glob expansion are not inspected. Layer inblocked=["cat", "less"]if you also want to block readers.- Trying to use
ShellToolon Gemini — unsupported, will raise. UseLocalShellToolinstead. - Using a hardcoded path that another process is also touching — multiple agents sharing
/tmp/my_projectwill race. Usetempfile.mkdtemp(prefix="...")for parallel runs. - Expecting
ShellToolto access local files — it doesn't; it runs in the provider's container. UseLocalShellToolfor anything on your filesystem. - Trusting the LLM with shell access — even sandboxed, write
prompts that scope what's allowed and consider pairing withapproval_required()for destructive operations.
In this repository15 other files it gives its agents.
- ag2-add-custom-toolSkill
- ag2-ag-uiSkill
- ag2-hitlSkill
- ag2-knowledge-and-memorySkill
- ag2-middlewareSkill
- ag2-multimodal-inputSkill
- ag2-observers-and-alertsSkill
- ag2-overviewSkill
- ag2-quickstartSkill
- ag2-structured-outputSkill
- ag2-subagent-delegationSkill
- ag2-telemetrySkill
- ag2-testingSkill
- ag2-use-builtin-toolsSkill
- calculatorSkill
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

