Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Beta balíček agent-framework-tools Python poskytuje nástroje pro spouštění shellových příkazů a práci s prostředím prostřednictvím agent_framework.tools jmenného prostoru.
| nástroj | Použijte ji, když |
|---|---|
LocalShellTool |
Příkazy jsou důvěryhodné nebo jednotlivě schválené a měly by se spouštět v hostitelském prostředí procesu agenta. |
DockerShellTool |
Příkazy prostředí generované modelem vyžadují izolaci kontejneru OCI. |
ShellEnvironmentProvider |
Model potřebuje informace o aktivní rodině shellu, operačním systému, pracovním adresáři a nainstalovaných verzích CLI. |
ShellPolicy |
Chcete předběžný filtr seznamu povolených nebo blokovaných položek před schválením nebo spuštěním. |
Warning
Spouštění příkazů v shellu může upravovat soubory, spouštět procesy, přistupovat k přihlašovacím údajům a komunikovat s externími systémy. Použijte úroveň spouštění s nejnižšími oprávněními, která podporuje úlohu.
Nainstalujte balíček
dotnet add package Microsoft.Agents.AI.Tools.Shell --prerelease
Používejte místní shell a znalost prostředí
LocalShellExecutor podporuje bezstavové a trvalé režimy.
ShellEnvironmentProvider zkoumá aktivní prostředí a přidává do kontextu agenta autoritativní pokyny pro shell.
using Azure.AI.Projects;
using Azure.Identity;
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.Tools.Shell;
using Microsoft.Extensions.AI;
var endpoint = Environment.GetEnvironmentVariable("FOUNDRY_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("FOUNDRY_PROJECT_ENDPOINT is not set.");
var deploymentName = Environment.GetEnvironmentVariable("FOUNDRY_MODEL") ?? "gpt-5.4-mini";
// WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production.
// In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid
// latency issues, unintended credential probing, and potential security risks from fallback mechanisms.
var aiProjectClient = new AIProjectClient(new Uri(endpoint), new DefaultAzureCredential());
const string Instructions = """
You are an agent with a single tool: run_shell. Use it to satisfy the
user's request. Do not describe what you would do — actually run the
commands. Reply with the final answer derived from real output.
""";
// --------------------------------------------------------------------
// 1. Stateless mode — each call gets a fresh shell.
// --------------------------------------------------------------------
Console.WriteLine("### Stateless mode\n");
await using (var statelessShell = new LocalShellExecutor(new() { Mode = ShellMode.Stateless, AcknowledgeUnsafe = true }))
{
var envProvider = new ShellEnvironmentProvider(statelessShell);
var statelessAgent = aiProjectClient.AsAIAgent(new ChatClientAgentOptions
{
ChatOptions = new()
{
ModelId = deploymentName,
Instructions = Instructions,
Tools = [statelessShell.AsAIFunction(requireApproval: false)],
},
AIContextProviders = [envProvider],
});
// --------------------------------------------------------------------
// 2. Persistent mode — one shell, reused across calls. State carries.
// --------------------------------------------------------------------
Console.WriteLine("\n### Persistent mode\n");
await using (var persistentShell = new LocalShellExecutor(new() { Mode = ShellMode.Persistent, AcknowledgeUnsafe = true }))
{
var envProvider = new ShellEnvironmentProvider(persistentShell);
var persistentAgent = aiProjectClient.AsAIAgent(new ChatClientAgentOptions
{
ChatOptions = new()
{
ModelId = deploymentName,
Instructions = Instructions,
Tools = [persistentShell.AsAIFunction(requireApproval: false)],
},
AIContextProviders = [envProvider],
});
var persistentSession = await persistentAgent.CreateSessionAsync();
// State carries across calls in persistent mode: cd into temp, then
// verify the next call sees the new CWD.
Console.WriteLine(await persistentAgent.RunAsync("Change directory into the system temp folder, then print the current working directory.", persistentSession));
Console.WriteLine();
Console.WriteLine(await persistentAgent.RunAsync("In a NEW shell call, print the current working directory again. Tell me whether it still matches the temp folder.", persistentSession));
Console.WriteLine();
// Same idea with an exported variable: set in one call, read in the next.
Console.WriteLine(await persistentAgent.RunAsync("Set the environment variable DEMO_TOKEN to the value 'hello-world'.", persistentSession));
Console.WriteLine();
Console.WriteLine(await persistentAgent.RunAsync("Print the current value of DEMO_TOKEN. Tell me exactly what value the shell reports.", persistentSession));
Console.WriteLine();
PrintSnapshot(envProvider.CurrentSnapshot!);
}
ShellPolicy je také k dispozici pro předběžné filtrování příkazů. Samostatná spustitelná ukázka DockerShellExecutor momentálně není publikována.
Nainstalujte balíček
pip install agent-framework-tools --pre
Balíček nainstaluje psutil, aby při překročení časového limitu běhu ukončil stromy podřízených procesů.
Použijte LocalShellTool
LocalShellTool spustí příkazy přímo na hostiteli. Ve výchozím nastavení používá trvalý shell, 30sekundový časový limit, ořezávání výstupu na 64 KiB, omezení na pracovní adresář a schvalování každého příkazu.
import asyncio
from typing import Any
from agent_framework import Agent, Message
from agent_framework.openai import OpenAIChatClient
from agent_framework.tools import LocalShellTool
from dotenv import load_dotenv
# Load environment variables from .env file
load_dotenv()
async def main() -> None:
print("=== OpenAI Agent with LocalShellTool Example ===")
print("NOTE: Commands will execute on your local machine.\n")
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 to help the user.",
tools=[client.get_shell_tool(func=shell.as_function())],
)
query = "Use the shell tool to execute `python --version` and show only the command output."
print(f"User: {query}")
result = await run_with_approvals(query, agent)
if isinstance(result, str):
print(f"Agent: {result}\n")
return
if result.text:
print(f"Agent: {result.text}\n")
else:
printed = False
for message in result.messages:
for content in message.contents:
if content.type == "function_result" and content.result:
print(f"Agent (tool output): {content.result}\n")
printed = True
if not printed:
print("Agent: (no text output returned)\n")
async def run_with_approvals(query: str, agent: Agent) -> Any:
"""Run the agent and handle shell approvals outside tool execution."""
current_input: str | list[Any] = query
while True:
result = await agent.run(current_input)
if not result.user_input_requests:
return result
next_input: list[Any] = [query]
rejected = False
for user_input_needed in result.user_input_requests:
if user_input_needed.function_call is None:
continue
print(
f"\nShell request: {user_input_needed.function_call.name}"
f"\nArguments: {user_input_needed.function_call.arguments}"
)
user_approval = await asyncio.to_thread(input, "\nApprove shell command? (y/n): ")
approved = user_approval.strip().lower() == "y"
next_input.append(Message("assistant", [user_input_needed]))
next_input.append(Message("user", [user_input_needed.to_function_approval_response(approved)]))
if not approved:
rejected = True
break
if rejected:
print("\nShell command rejected. Stopping without additional approval prompts.")
return "Shell command execution was rejected by user."
current_input = next_input
if __name__ == "__main__":
asyncio.run(main())
Použijte mode="stateless" , když by se každé volání mělo spustit v novém procesu. Chcete-li přepsat určený shell, použijte proměnnou prostředí AGENT_FRAMEWORK_SHELL nebo argument konstruktoru shell.
Důležité
LocalShellTool není sandbox. Schválení je primární hranicí zabezpečení. Zakázání schválení vyžaduje acknowledge_unsafe=True.
Omezení příkazů pomocí ShellPolicy
ShellPolicy před spuštěním uplatní seznamy povolených a zakázaných regulárních výrazů. Pravidla zamítnutí mají přednost.
import asyncio
from agent_framework import Agent
from agent_framework.openai import OpenAIChatClient
from agent_framework.tools import LocalShellTool, ShellPolicy
from dotenv import load_dotenv
load_dotenv()
async def main() -> None:
client = OpenAIChatClient(model="gpt-5.4-nano")
shell = LocalShellTool(
mode="stateless",
approval_mode="never_require",
acknowledge_unsafe=True,
policy=ShellPolicy(
allowlist=[
r"^ls(\s|$)",
r"^pwd$",
r"^cat\s[^|;&]+$",
r"^git\s+(status|log|diff)(\s|$)",
r"^python\s+--version$",
],
),
timeout=10,
)
agent = Agent(
client=client,
instructions=(
"You can run a narrow set of read-only shell commands (ls, pwd, cat, "
"git status/log/diff, python --version). Anything else will be rejected."
),
tools=[client.get_shell_tool(func=shell.as_function())],
)
query = "Summarise the current directory and print the Python version."
print(f"User: {query}")
result = await agent.run(query)
print(f"Agent: {result.text}")
Warning
Zásada příkazů je předběžný filtr použitelnosti, nikoli bezpečnostní hranice. Syntaxe prostředí, aliasy, proměnné, interprety a zakódované datové části můžou obejít jednoduché porovnávání vzorů.
Přidejte ShellEnvironmentProvider
ShellEnvironmentProvider zjišťuje rodinu shellu, jeho verzi, operační systém, pracovní adresář a verze vybraných rozhraní příkazového řádku a poté tyto informace vloží ještě před spuštěním agenta. Výchozí seznam sond je git, node, python a docker.
import asyncio
from agent_framework import Agent
from agent_framework.openai import OpenAIChatClient
from agent_framework.tools import (
LocalShellTool,
ShellEnvironmentProvider,
ShellEnvironmentProviderOptions,
)
from dotenv import load_dotenv
load_dotenv()
def _print_snapshot(label: str, provider: ShellEnvironmentProvider) -> None:
snapshot = provider.current_snapshot
if snapshot is None:
print(f"[{label}] no snapshot captured")
return
print(f"\n[{label}] snapshot:")
print(f" family = {snapshot.family.value}")
print(f" os = {snapshot.os_description}")
print(f" shell_version = {snapshot.shell_version}")
print(f" working_directory = {snapshot.working_directory}")
for tool, version in snapshot.tool_versions.items():
print(f" {tool:<17} = {version}")
async def _ask(agent: Agent, query: str) -> None:
print(f"\nUser: {query}")
result = await agent.run(query)
if result.text:
print(f"Agent: {result.text}")
async def main() -> None:
client = OpenAIChatClient(model="gpt-5.4-nano")
options = ShellEnvironmentProviderOptions(
probe_tools=("git", "python", "uv", "node"),
)
print("=== stateless mode ===")
async with LocalShellTool(
mode="stateless",
approval_mode="never_require",
acknowledge_unsafe=True,
) as shell:
provider = ShellEnvironmentProvider(shell, options)
agent = Agent(
client=client,
instructions="Use the shell tool to answer the user's question.",
tools=[client.get_shell_tool(func=shell.as_function())],
context_providers=[provider],
)
await _ask(agent, "Show me the current working directory.")
await _ask(agent, "Now `cd ..` then show the working directory again.")
await _ask(agent, "Show the working directory once more — did `cd` persist?")
_print_snapshot("stateless", provider)
print("\n=== persistent mode ===")
async with LocalShellTool(
mode="persistent",
confine_workdir=False,
approval_mode="never_require",
acknowledge_unsafe=True,
) as shell:
provider = ShellEnvironmentProvider(shell, options)
agent = Agent(
client=client,
instructions="Use the shell tool to answer the user's question.",
tools=[client.get_shell_tool(func=shell.as_function())],
context_providers=[provider],
)
await _ask(agent, "Show me the current working directory.")
await _ask(agent, "Now `cd ..` then show the working directory again.")
await _ask(agent, "Show the working directory once more — did `cd` persist?")
_print_snapshot("persistent", provider)
Použijte DockerShellTool
DockerShellTool vyžaduje Docker nebo Podman na PATH. Výchozí nastavení zakazuje síťovou komunikaci, spouští se pod nerootovským uživatelem, používá kořenový souborový systém pouze pro čtení, odebírá linuxové capability, omezuje paměť na 512 MiB a omezuje kontejner na 256 procesů.
from agent_framework.tools import DockerShellTool
async with DockerShellTool(
image="mcr.microsoft.com/azurelinux/base/core:3.0",
approval_mode="never_require",
) as shell:
result = await shell.run("uname -a && id")
print(result.stdout)
Výchozí obrázek je mcr.microsoft.com/azurelinux/base/core:3.0. Předejte docker_binary="podman" pro použití Podmanu. Samostatná spustitelná DockerShellTool ukázka není v současnosti k dispozici.
Zvolte úroveň provádění
| Scenario | nástroj | Hranice izolace |
|---|---|---|
| Důvěryhodné vývojové příkazy | LocalShellTool |
Schválení v hostitelském procesu |
| Nedůvěryhodné příkazy shellu | DockerShellTool |
Kontejner OCI s výchozími příznaky izolace |
| Nedůvěryhodný vygenerovaný kód bez shellu | Hyperlight CodeAct | Hyperlight microVM |
Go poskytuje spouštění příkazů v lokálním shellu a zjišťování informací o prostředí prostřednictvím tool/shelltool. Viz Použijte nástroj místního shellu.
DockerShellTool Pokyny nejsou aktuálně k dispozici pro Go.
Používejte nástroje shellu s Harness Agent
Běžní agenti a HarnessAgent používají stejné dvoudílné nastavení shellu: zaregistrujte funkci executoru jako nástroj a přidejte ShellEnvironmentProvider, když má model obdržet kontext shellu, operačního systému, pracovního adresáře a verze CLI.
HarnessAgent nevytváří ani nespravuje shellový exekutor:
using System.IO;
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.Tools.Shell;
using Microsoft.Extensions.AI;
await using var shell = new LocalShellExecutor(new LocalShellExecutorOptions
{
WorkingDirectory = Directory.GetCurrentDirectory(),
Timeout = LocalShellExecutor.DefaultTimeout,
});
AIAgent agent = chatClient.AsHarnessAgent(new HarnessAgentOptions
{
AIContextProviders = [new ShellEnvironmentProvider(shell)],
ChatOptions = new ChatOptions
{
Tools = [shell.AsAIFunction(requireApproval: true)],
},
});
AsAIFunction má jako výchozí hodnotu název run_shell a requireApproval: true.
LocalShellExecutor výchozí hodnota pro trvalý režim, limit 64 KiB na výstupní datový proud a bez časového limitu; příklad explicitně používá doporučenou 30sekundundu LocalShellExecutor.DefaultTimeout.
ShellEnvironmentProviderOptions ve výchozím nastavení zkouší git, dotnet, node, python a docker, s pětisekundovým časovým limitem pro každou sondu.
Vytvořte jeden trvalý exekutor pro každou uživatelskou relaci a vyřaďte ho po skončení relace. Nesdílejte ho mezi uživateli ani souběžnými konverzacemi, protože se sdílí pracovní adresář, prostředí, historie prostředí, úlohy na pozadí a fronta příkazů.
ShellPolicy je pouze předběžný filtr; ponechte schvalování zapnuté, používejte přihlašovací údaje s nejnižšími oprávněními a upřednostněte DockerShellExecutor, když příkazy vyžadují silnější hranici izolace.
Nástroje prostředí jsou k dispozici v předběžné verzi Microsoft.Agents.AI.Tools.Shell balíčku.
HarnessAgent je k dispozici od Microsoft.Agents.AI.Harness.
Pro běžného agenta vytvořte pomocí client.get_shell_tool(func=shell.as_function()) funkci shellu a ShellEnvironmentProvider přidejte samostatně.
create_harness_agent provede oba kroky, když předáte shell_executor:
from agent_framework import create_harness_agent
from agent_framework.tools import LocalShellTool, ShellEnvironmentProviderOptions
async with LocalShellTool() as shell:
agent = create_harness_agent(
client=client,
shell_executor=shell,
shell_environment_provider_options=ShellEnvironmentProviderOptions(
probe_tools=("git", "python"),
),
)
session = agent.create_session()
response = await agent.run("Inspect the current repository.", session=session)
shell_executor je volitelné a musí zpřístupňovat as_function(). Továrna přidá shellový nástroj a ShellEnvironmentProvider pouze tehdy, když klient implementuje SupportsShellTool; jinak zapíše varování do protokolu a přeskočí obě položky.
shell_environment_provider_options je nepovinný a používá se pouze s shell_executor.
LocalShellTool výchozí hodnota pro trvalý režim, 30sekundový časový limit, kombinovaný výstup 64-KiB, opětovné ukotvení pracovního adresáře a approval_mode="always_require". Protože je schválení nástrojů v Harness ve výchozím nastavení povoleno, předejte AgentSession do run. Volající spravuje životní cyklus executoru; použijte async with nebo zavolejte close() a pro každou uživatelskou relaci vytvořte jeden trvalý nástroj. Nesdílejte měnitelný stav shellu mezi uživateli ani souběžnými konverzacemi.
Hostitelské prostředí není sandbox. Povolte schválení, používejte nejméně privilegované přihlašovací údaje a používejte DockerShellTool je pro izolaci kontejnerů. Zakázání schvalování vyžaduje approval_mode="never_require" a acknowledge_unsafe=True; samotné ShellPolicy není bezpečnostní hranicí.
create_harness_agent vychází v agent-framework-core. Integraci se shellem zajišťuje předběžný balíček agent-framework-tools a při povolení generuje ExperimentalWarning.
Balíčkovaná verze Go Harness není v současné době k dispozici. Vytvořte nástroj místního prostředí a poskytovatele prostředí přímo v prostém agentu Go.