Observed since 20 Oct, 22:00 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
Built-in tools for the Microsoft Agent Framework (local shell, and more).
Beta built-in tools for the Microsoft Agent Framework. A home for first-party
Python tools that plug into any chat client's shell / function surface. The
first tool is LocalShellTool.
pip install agent-framework-tools --pre
LocalShellTool quick startimport asyncio
from agent_framework import Agent
from agent_framework.openai import OpenAIChatClient
from agent_framework.tools import LocalShellTool
async def main() -> None:
client = OpenAIChatClient(model="gpt-5.4-nano")
async with LocalShellTool() as shell:
agent = Agent(
client=client,
instructions="You are a helpful assistant that can run shell commands.",
tools=[client.get_shell_tool(func=shell.as_function())],
)
result = await agent.run("Print the current working directory.")
print(result.text)
asyncio.run(main())
cd, export,
and shell functions persist across tool invocations.mode="stateless"): each command runs in a fresh subprocess.
LocalShellToolis not a sandbox. It runs commands directly on the host with the agent process's permissions. Human approval provides a check before agent-requested commands run, but does not isolate the shell. Production use needs separately enforced isolation and restricted permissions. For untrusted input use a sandboxed executor, such asDockerShellToolfor shell commands — see alsoagent-framework-hyperlight.
Defenses (in priority order):
as_function() with approval_mode="always_require" (the default),
commands require approval through a user_input_request before they run.
Disabling this requires acknowledge_unsafe=True. Direct calls to
run() do not request approval, regardless of the configured approval mode.psutil, so child
processes (make, watchers, network tools) cannot survive the timeout. On
Windows, a timed-out persistent session is closed even if the interrupted
command emits its completion marker. The next command starts a fresh shell;
shell-local variables and working-directory changes from that session are lost.on_command=…) for SIEM / append-only logs.ShellPolicy(denylist=[...], allowlist=[...]). Empty by default. This is a UX pre-filter, not a
security boundary — operators are expected to supply patterns that
match their workload (and they can be defeated by trivial obfuscation
such as \rm -rf /, ${RM:=rm} -rf /, python -c "…", encoded
payloads, or PowerShell-native equivalents). Isolation must be enforced
separately, for example by the sandbox tier (DockerShellTool);
neither approval nor command filters isolate the shell. See
tests/test_security.py for the documented residual risk surface.Command-text filtering with ShellPolicy and required human approval:
[!WARNING] The filters below can allow embedded commands, including
$(...)and backticks, and do not enforce read-only access. Review the full command before approving it. Approval does not isolate the shell: commands still run with the application's permissions.
from agent_framework.tools import LocalShellTool, ShellPolicy
shell = LocalShellTool(
policy=ShellPolicy(allowlist=[r"^ls\b", r"^cat\b", r"^git status$"]),
approval_mode="always_require",
)
Expose this tool to the agent through shell.as_function() and handle its
approval requests with human review. Calling shell.run() directly does not
request approval.
pwsh -NoProfile -Command - (falls back to powershell.exe)./bin/bash --noprofile --norc (falls back to /bin/sh).shell= constructor argument or the
AGENT_FRAMEWORK_SHELL environment variable.ShellEnvironmentProvider — context providerA model talking to a PowerShell session will sometimes default to bash
syntax (export FOO=bar, ls -la, > /dev/null) and vice versa.
ShellEnvironmentProvider is an AIContextProvider that probes the live
shell once per session — family, version, OS, working directory, and a
configurable list of CLI tools (git, node, python, docker by
default) — and injects a system-prompt block describing the shell idiom
to use and the available CLIs.
from agent_framework.tools import (
LocalShellTool,
ShellEnvironmentProvider,
ShellEnvironmentProviderOptions,
)
shell = LocalShellTool()
provider = ShellEnvironmentProvider(
shell,
ShellEnvironmentProviderOptions(probe_tools=("git", "uv", "node")),
)
agent = Agent(
client=client,
tools=[client.get_shell_tool(func=shell.as_function())],
context_providers=[provider],
)
Probe failures from expected error types (timeouts, policy rejections,
spawn failures) are recorded as None fields in the snapshot rather
than raised; a missing CLI never fails the agent. A failed first probe
does not poison the cache — the next call retries.
DockerShellTool — sandboxed tierWhen commands originate from untrusted input (e.g. the model is acting on
prompt-injected document content), prefer DockerShellTool. With the
default isolation flags and a trusted container runtime, the container
is the intended security boundary and approval gating becomes optional.
import asyncio
from agent_framework.tools import DockerShellTool
async def main() -> None:
async with DockerShellTool(
image="mcr.microsoft.com/azurelinux/base/core:3.0",
approval_mode="never_require", # container is the boundary
) as shell:
result = await shell.run("uname -a && id")
print(result.stdout)
asyncio.run(main())
Defaults applied to every container:
--network none — no host or external network.--user 65534:65534 — runs as nobody:nogroup.--read-only root filesystem; only mounted host paths are writable.--cap-drop ALL and --security-opt no-new-privileges.--memory 512m, --pids-limit 256, ephemeral tmpfs /tmp.To expose a host directory, pass host_workdir="/path" (mounted
read-only by default; mount_readonly=False to allow writes). Swap the
container runtime with docker_binary="podman".
| Use case | Tool | Sandbox |
|---|---|---|
| Run code (untrusted) | HyperlightCodeActProvider.execute_code (agent-framework-hyperlight) | Hyperlight WASM microVM |
| Run shell (untrusted) | DockerShellTool | OCI container (network-off, non-root, capabilities dropped) |
| Run shell (trusted dev) | LocalShellTool | None; human approval for agent calls by default |
agent-framework-hyperlightagent-framework-hyperlight is a code sandbox (a single WASM guest
loaded into a microVM, called via a hostcall ABI — there is no kernel,
userland, or shell binary inside). It is the right tier for executing
generated code. For sandboxing shell commands, the realistic tier is
OCI, which DockerShellTool provides.
Download counts and popularity will appear here as the collector receives them.
| Version | Published | Direct dependencies | Open version |
|---|---|---|---|
| 1.0.0b261015 | 15 Oct 2026 | 2 |
This describes our collected data; it is not a security assessment.
Observed since 20 Oct, 22:00 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package:19d838b892534fdebd878f334e9a4b7441e7d43190643435e1509abf4b756a7d