agentleFS
ag2aiag2ai/build-with-ag2/.agents/skills/ag2-shell-tool/SKILL.md

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
  1. Very specific:

    When a path is given, the directory is created if it does not exist and is not deleted on exit.

    line 48

≈ “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.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Shell tools

When to use

Two distinct tools, both named "shell" — pick deliberately:

NeedUseWhy
Works with any model provider; full control over what runs and whereLocalShellToolClient-side subprocess. You own the sandbox.
Provider-managed sandbox (container, network policy) on Anthropic / OpenAIShellToolServer-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:

  1. allowed — if set, the command must match at least one prefix.
  2. blocked — if set, the command must not match any prefix.
  3. ignore — literal path tokens in the command are checked against gitignore-style patterns; matches return "Access denied: <path>".
  4. 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

ParameterDefaultDescription
pathNoneWorking dir. None → temp dir, deleted on exit
cleanupNoneNone → auto (True when path=None, False otherwise). Deletes path on process exit
allowedNoneWhitelist of command prefixes. None → all commands allowed
blockedNoneBlacklist of command prefixes
ignoreNoneGitignore-style path patterns; matches block the command
readonlyFalseWhen True and allowed unset, restricts to a built-in read-only list
envNoneExtra env vars merged into each command
timeout60Per-command timeout in seconds (returns "Command timed out after Ns [exit code: 124]")
max_output100_000Max 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:

EnvironmentDescription
ContainerAutoEnvironmentProvider-managed container with optional network policy
ContainerReferenceEnvironmentReference an existing container by ID

ShellTool is not supported on Gemini — the request will raise UnsupportedToolError.

LocalShellTool vs ShellTool

LocalShellToolShellTool
ExecutionClient-side subprocessProvider-side container
Provider supportAny providerAnthropic, OpenAI
Environment controlFull (allowed, blocked, ignore, readonly, …)Limited (provider-dependent)
Local FS accessYes (you choose what's exposed)No
Network controlVia blocked / allowed patternsOpenAI: NetworkPolicy
Importfrom 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 — full LocalShellTool reference, command-filtering semantics.
  • website/docs/beta/tools/builtin_tools.mdx#shell — provider-native ShellTool setup and environment configs.
  • For human-approval gating before each shell call, layer approval_required() middleware (see ag2-hitl).

Common pitfalls

  • Forgetting sandboxing in production — LocalShellTool() with no environment runs anything anywhere with a 60s timeout. Set allowed, blocked, or readonly for 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 in blocked=["cat", "less"] if you also want to block readers.
  • Trying to use ShellTool on Gemini — unsupported, will raise. Use LocalShellTool instead.
  • Using a hardcoded path that another process is also touching — multiple agents sharing /tmp/my_project will race. Use tempfile.mkdtemp(prefix="...") for parallel runs.
  • Expecting ShellTool to access local files — it doesn't; it runs in the provider's container. Use LocalShellTool for anything on your filesystem.
  • Trusting the LLM with shell access — even sandboxed, write prompts that scope what's allowed and consider pairing with approval_required() for destructive operations.

Download now (ZIP)

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
What did you use it for? e.g. Reviewing pull requests in a Rails app

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.