
Ag2 Shell Tool
- 33 installs
- 8 repo stars
- Updated July 27, 2026
- ag2ai/ag2-skills
ag2-shell-tool is a Claude Code skill that gives an AG2 beta Agent the ability to run shell commands with sandboxing.
About
This skill gives an AG2 beta Agent the ability to run shell commands. It covers SandboxShellTool, a client-side subprocess via LocalEnvironment that works with any provider, and the provider-native ShellTool for OpenAI Responses server-side execution. A developer uses it when the agent needs to execute commands, build or test code, or operate on a workspace, always paired with sandboxing filters.
- Gives an AG2 beta Agent the ability to run shell commands
- SandboxShellTool works with any provider; ShellTool is OpenAI Responses server-side
- Pairs with sandboxing filters: allowed, blocked, ignore, and readonly
Ag2 Shell Tool by the numbers
- 33 all-time installs (skills.sh)
- Ranked #8,975 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 1, 2026 (Skillselion catalog sync)
ag2-shell-tool capabilities & compatibility
Free skill; requires an LLM provider API key to run the agent.
- Capabilities
- shell tool · code execution · sandboxing · agent tool
- Works with
- openai · anthropic
- Use cases
- orchestration · testing · debugging
- Pricing
- Bring your own API key
What ag2-shell-tool says it does
Give an AG2 beta `Agent` the ability to run shell commands.
**`SandboxShellTool` is the workhorse**. Reach for it unless you specifically need provider-managed isolation and you're on OpenAI Responses.
npx skills add https://github.com/ag2ai/ag2-skills --skill ag2-shell-toolAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 33 |
|---|---|
| repo stars | ★ 8 |
| Last updated | July 27, 2026 |
| Repository | ag2ai/ag2-skills ↗ |
What it does
Let an AG2 beta agent run shell commands to build, test, or operate on a workspace, with sandboxing filters.
Who is it for?
Developers who want an AG2 agent to execute commands, build/test code, or operate on a workspace.
Skip if: Relying on blocked filters as a security boundary; the docs note they are best-effort only.
When should I use this skill?
The user wants the agent to execute commands, build/test code, manage files, or operate on a workspace.
What you get
The agent runs shell commands in a sandboxed working directory with allowed/blocked/ignore/readonly filters.
By the numbers
- 4 sandbox filter modes (allowed, blocked, ignore, readonly)
- 2 shell tools (SandboxShellTool, ShellTool)
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 | SandboxShellTool | Client-side subprocess (via LocalEnvironment). You own the sandbox. |
| Provider-managed sandbox (container, network policy) on OpenAI Responses | ShellTool | Server-side execution. No local subprocess. |
`SandboxShellTool` is the workhorse. Reach for it unless you specifically need provider-managed isolation and you're on OpenAI Responses.
60-second recipe — SandboxShellTool
from autogen.beta import Agent
from autogen.beta.config import AnthropicConfig
from autogen.beta.tools import SandboxShellTool
agent = Agent(
"coder",
"You write and run Python code.",
config=AnthropicConfig(model="claude-sonnet-4-6"),
tools=[SandboxShellTool()],
)
reply = await agent.ask("Write a hello world script and run it.")
print(await reply.content())SandboxShellTool 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, SandboxShellTool defaults to a LocalEnvironment() that creates a temporary working directory (prefixed ag2_sandbox_) and cleans it up when the process exits. Pass a LocalEnvironment with a path to use a specific directory:
from pathlib import Path
from autogen.beta.tools import LocalEnvironment, SandboxShellTool
SandboxShellTool(LocalEnvironment("/tmp/my_project"))
SandboxShellTool(LocalEnvironment(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 (LocalEnvironment + tool-level filters)
For anything beyond a throwaway demo, lock down what the agent can do. The environment (LocalEnvironment) decides where commands run and carries backend config (path, timeout, max_output, env_vars); the tool (SandboxShellTool) decides the agent-facing policy (allowed / blocked / ignore / readonly). Filtering is applied in this order on every call:
1. allowed — if set, the command must match at least one prefix. In this restricted mode, shell operators (>, >>, |, ;, &&, ||, ` `, $() are also rejected. 2. blocked — if set, the command must not match any prefix. Best-effort only (head-command prefix match; chaining can bypass it). 3. ignore — literal path tokens in the command are checked against gitignore-style patterns; matches return "Access denied: <path>". 4. Execute via the environment's subprocess`.
from autogen.beta.tools import LocalEnvironment, SandboxShellTool
sh = SandboxShellTool(
LocalEnvironment(
path="/tmp/my_project",
timeout=30,
max_output=50_000,
),
allowed=["python", "uv run", "git"],
blocked=["rm -rf", "curl", "wget"],
ignore=["**/.env", "*.key", "secrets/**"],
)Read-only mode
For inspection-only access (cat, head, tail, ls, grep, find, git log, git diff, git status, …):
from autogen.beta.tools import LocalEnvironment, SandboxShellTool
sh = SandboxShellTool(LocalEnvironment(path="/my/codebase"), readonly=True)Pass an explicit allowed=[...] to override the built-in read-only allowlist.
Parameter reference
LocalEnvironment (the environment — where and how commands run):
| Parameter | Default | Description |
|---|---|---|
path | None | Working dir. None → temp dir (prefix ag2_sandbox_), deleted on exit |
cleanup | None | None → auto (True when path=None, False otherwise). Deletes path on close |
timeout | 60 | Per-command timeout in seconds (returns "Command timed out after Ns" with exit code 124) |
max_output | 100_000 | Max characters returned (truncated output is suffixed [truncated: …]) |
env_vars | None | Extra env vars merged into each command |
SandboxShellTool (the tool — agent-facing command policy):
| Parameter | Default | Description |
|---|---|---|
environment | None | The backend. None → LocalEnvironment() (local subprocess, temp dir) |
allowed | None | Whitelist of command prefixes. None → all commands allowed |
blocked | None | Blacklist of command prefixes (best-effort, not a security boundary) |
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 |
Stateful multi-turn workspaces
Files persist in workdir across ask() calls, so the agent can build on prior work:
from autogen.beta.tools import LocalEnvironment, SandboxShellTool
sh = SandboxShellTool(LocalEnvironment(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 (OpenAI Responses only)
ShellTool is a provider-executed capability flag. Only the OpenAI Responses API runs shell server-side. Anthropic's bash tool is client-side and is rejected with UnsupportedToolError — use SandboxShellTool there. Gemini is also unsupported.
from autogen.beta.config import OpenAIResponsesConfig
from autogen.beta.tools import ShellTool
agent = Agent("devops", config=OpenAIResponsesConfig(model="gpt-4.1"), tools=[ShellTool()])OpenAI lets you configure the execution environment:
from autogen.beta.config import OpenAIResponsesConfig
from autogen.beta.tools import ContainerAutoEnvironment, NetworkPolicy, ShellTool
agent = Agent(
"devops",
config=OpenAIResponsesConfig(model="gpt-4.1"),
tools=[
ShellTool(
environment=ContainerAutoEnvironment(
network_policy=NetworkPolicy(allowed_domains=["pypi.org"]),
),
),
],
)Environment options (OpenAI-only):
| Environment | Description |
|---|---|
ContainerAutoEnvironment | Provider-managed container with optional NetworkPolicy |
ContainerReferenceEnvironment | Reference an existing container by ID |
SandboxShellTool vs ShellTool
SandboxShellTool | ShellTool | |
|---|---|---|
| Execution | Client-side subprocess | Provider-side container |
| Provider support | Any provider | OpenAI Responses only |
| 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 SandboxShellTool, LocalEnvironment | from autogen.beta.tools import ShellTool |
Going deeper
website/docs/beta/tools/sandbox.mdx— fullSandboxShellTool/LocalEnvironmentreference, 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 —
SandboxShellTool()with no filters runs anything anywhere with a 60s timeout. Setallowed,blocked, orreadonlyfor any non-trivial use. - `ignore` only 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. - `blocked` is best-effort, not a security boundary — it only matches the head command's prefix, so chaining (
echo x; rm -rf ~) bypassesblocked=["rm"]. Useallowed/readonlyor an isolated container backend for real isolation. - Trying to use `ShellTool` on Anthropic or Gemini — unsupported, will raise
UnsupportedToolError. UseSandboxShellToolinstead. - Using a hardcoded path that another process is also touching — multiple agents sharing
/tmp/my_projectwill race. Usetempfile.mkdtemp(prefix="...")for parallel runs. - Expecting `ShellTool` to access local files — it doesn't; it runs in the provider's container. Use
SandboxShellToolfor 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.
Related skills
FAQ
Which shell tool works with any provider?
SandboxShellTool, a client-side subprocess via LocalEnvironment; ShellTool is OpenAI Responses server-side only.
Are blocked filters a security boundary?
No, blocked is best-effort head-command prefix matching and command chaining can bypass it.