Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Beta agent-framework-tools Python paketi, agent_framework.tools ad alanı üzerinden kabukta yürütme ve ortam farkındalığı araçları sağlar.
| Araç | Şu durumlarda kullanın: |
|---|---|
LocalShellTool |
Komutlar güvenilir veya tek tek onaylanmıştır ve aracı işleminin ana bilgisayar ortamında çalıştırılmalıdır. |
DockerShellTool |
Model tarafından oluşturulan kabuk komutları, OCI kapsayıcı yalıtımı gerektirir. |
ShellEnvironmentProvider |
Modelin etkin kabuk ailesine, işletim sistemine, çalışma dizinine ve yüklü CLI sürümlerine ihtiyacı vardır. |
ShellPolicy |
Onay veya yürütmeden önce bir izin listesi veya reddetme listesi ön filtresi istiyorsunuz. |
Warning
Kabuk yürütme dosyaları değiştirebilir, işlemleri başlatabilir, kimlik bilgilerine erişebilir ve dış sistemlerle iletişim kurabilir. Görevi destekleyen en az ayrıcalıklı yürütme katmanını kullanın.
Paketi yükle
dotnet add package Microsoft.Agents.AI.Tools.Shell --prerelease
Yerel kabuk ve ortam farkındalığını kullanma
LocalShellExecutor durum bilgisi olmayan ve kalıcı modları destekler.
ShellEnvironmentProvider etkin ortamı yoklar ve aracı bağlamı için yetkili kabuk yönergeleri ekler.
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 , komut ön filtrelemesi için de kullanılabilir.
DockerShellExecutor özel çalıştırılabilir örnek şu anda yayımlanmış değil.
Paketi yükle
pip install agent-framework-tools --pre
Paket, bir çalıştırma işlemi zaman aşımına uğradığında alt işlem ağaçlarını sonlandırmak için psutil yükler.
LocalShellTool komutunu kullanma
LocalShellTool komutları doğrudan ana sistem üzerinde çalıştırır. Varsayılan olarak kalıcı bir kabuk, 30 saniyelik zaman aşımı, çıktının 64 KiB ile sınırlandırılması, çalışma diziniyle sınırlandırma ve her komut için onay kullanır.
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())
OpenAI sağlayıcısı tarafından barındırılan kabuk transkript öğeleri, yerel bir kabuk yürütücüsü yapılandırıldığında bile bilgilendirici kalır. Yalnızca iyi biçimlendirilmiş açık bir local_shell_call ya da environment.type="local" ile işaretlenmiş bir kabuk çağrısı, yerel işlev ve onay yoluna girer.
LocalShellTool öğesini tek başına yapılandırmak, sağlayıcı tarafından barındırılan kabuk çağrılarının konakta yürütülmesine neden olmaz.
Her çağrının yeni bir işlemde çalıştırılması gerektiğinde kullanın mode="stateless" .
AGENT_FRAMEWORK_SHELL Çözümlenen kabuğu geçersiz kılmak için ortam değişkenini veya shell oluşturucu bağımsız değişkenini kullanın.
Önemli
LocalShellTool bir sandbox değildir. Onay birincil güvenlik sınırıdır. Onayın devre dışı bırakılması için acknowledge_unsafe=Truegerekir.
ile komutları kısıtla ShellPolicy
ShellPolicy, yürütmeden önce düzenli ifade izin ve engelleme listelerini uygular. Reddetme kuralları önceliklidir.
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
Komut ilkesi, güvenlik sınırı değil kullanılabilirlik ön filtresidir. Kabuk sözdizimi, takma adlar, değişkenler, yorumlayıcılar ve kodlanmış veri yükleri basit örüntü eşleştirmesini aşabilir.
Dize desenlerini tercih edin. Python, dizeleri regex altyapısını kullanarak derler ve her eşleşme için bir saniyelik süre sınırı uygular. Bir engelleme listesi zaman aşımı, komutun reddedilmesine neden olur; izin verilenler listesi zaman aşımı ise izin sağlamaz. Önceden derlenmiş regex.Pattern, aynı sınırı kullanır. Önceden derlenmiş bir standart kitaplık re.Pattern bayraklarını korur ancak kesintiye uğratılamaz, bu nedenle bu formdaki pahalı veya belirsiz ifadelerden kaçının.
ShellEnvironmentProvider ekle
ShellEnvironmentProvider kabuk ailesini, sürümünü, işletim sistemini, çalışma dizinini ve seçili CLI sürümlerini yoklar, ardından aracı çalışmadan önce bu bilgileri ekler. Varsayılan yoklama listesi , git, nodeve pythonşeklindedirdocker.
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)
DockerShellTool komutunu kullanma
DockerShellTool, PATH üzerinde Docker veya Podman gerektirir. Varsayılanlar ağı devre dışı bırakır, kök olmayan bir kullanıcı olarak çalışır, salt okunur bir kök dosya sistemi kullanır, özellikleri bırakır, belleği 512 MiB ile sınırlar ve kapsayıcıyı 256 işlemde kaplar.
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)
Varsayılan görüntü: mcr.microsoft.com/azurelinux/base/core:3.0. Podman kullanmak için docker_binary="podman" iletin.
DockerShellTool özel çalıştırılabilir örnek şu anda yayımlanmış değil.
Yalnızca yapılandırılan yalıtımı veya kaynak sınırlarını zayıflatmayan Docker seçenekleri için kullanın extra_run_args . Doğrulama uzun bayrakları, kısa bayrakları, ekli değerleri ve kümelenmiş kısa bayrakları tanır.
--memory
-m
/ , --network--volume-v, / --pids-limit-u, / ve --user gibi geçersiz kılmaları reddeder. Bunun yerine ilgili DockerShellTool oluşturucu seçeneğini kullanın.
Yürütme katmanı seçme
| Scenario | Araç | Yalıtım sınırı |
|---|---|---|
| Güvenilen geliştirme komutları | LocalShellTool |
Ana işlemde onay |
| Güvenilir olmayan kabuk komutları | DockerShellTool |
Varsayılan yalıtım bayraklarına sahip OCI kapsayıcısı |
| Shell olmadan güvenilmeyen üretilen kod | Hyperlight CodeAct | Hyperlight microVM |
Go, tool/shelltool aracılığıyla yerel kabukta yürütme ve ortamı yoklama olanağı sağlar. Bkz. Yerel kabuk aracını kullanın.
DockerShellTool rehberliği şu anda Go için mevcut değil.
Harness Agent ile kabuk araçlarını kullanmak
Yalın aracılar ve HarnessAgent, aynı iki parçalı kabuk yapılandırmasını kullanır: yürütücünün işlevini bir araç olarak kaydedin ve modelin kabuk, işletim sistemi, çalışma dizini ve CLI sürümü bağlamını alması gerektiğinde ShellEnvironmentProvider ekleyin.
HarnessAgent bir shell yürütücüsü oluşturmaz veya bir shell yürütücüsüne sahip değildir:
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, varsayılan olarak run_shell ve requireApproval: true adını kullanır.
LocalShellExecutor varsayılan olarak kalıcı mod, çıkış akışı başına 64 KiB üst sınır ve zaman aşımı yoktur; örnek, önerilen 30 saniyeyi LocalShellExecutor.DefaultTimeoutaçıkça kullanır.
ShellEnvironmentProviderOptions, varsayılan olarak git, dotnet, node, python ve docker öğelerini her yoklama için beş saniyelik zaman aşımıyla yoklar.
Kullanıcı oturumu başına bir kalıcı yürütücü oluşturun ve oturum sona erdiğinde bunu atın. Çalışma dizini, ortam, kabuk geçmişi, arka plan işleri ve komut kuyruğu paylaşıldığından, bunu kullanıcılar veya eşzamanlı konuşmalar arasında paylaşmayın.
ShellPolicy yalnızca ön filtredir; onayı etkin tutun, en az ayrıcalıklı kimlik bilgilerini kullanın ve komutların daha güçlü bir yalıtım sınırı gerektirdiğini tercih edin DockerShellExecutor .
Komut kabuğu araçları, ön sürüm Microsoft.Agents.AI.Tools.Shell paketinde sunulmaktadır.
HarnessAgent, Microsoft.Agents.AI.Harness aracılığıyla kullanılabilir.
Normal bir aracı için, kabuk işlevini client.get_shell_tool(func=shell.as_function()) ile oluşturun ve ShellEnvironmentProvider’i ayrı olarak ekleyin.
create_harness_agent geçirdiğinizde shell_executorher iki adımı da gerçekleştirir:
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 isteğe bağlıdır ve as_function() sunmalıdır. Fabrika, kabuk aracını ve ShellEnvironmentProvider öğesini yalnızca istemci SupportsShellTool öğesini uyguladığında ekler; aksi takdirde bir uyarı günlüğe kaydeder ve her ikisini de atlar.
shell_environment_provider_options isteğe bağlıdır ve yalnızca ile shell_executorkullanılır.
LocalShellTool varsayılan olarak kalıcı modu, 30 saniyelik zaman aşımını, 64 KiB birleşik çıktıyı, çalışma dizininin yeniden sabitlenmesini ve approval_mode="always_require" kullanır. Harness aracı onayı varsayılan olarak etkin olduğundan, AgentSession öğesini run öğesine iletin. Yürütücünün yaşam döngüsü çağıranın sorumluluğundadır; async with kullanın veya close() çağrısı yapın ve her kullanıcı oturumu için tek bir kalıcı araç oluşturun. Değiştirilebilir kabuk durumunu kullanıcılar veya eşzamanlı konuşmalar arasında paylaşmayın.
Ana bilgisayar kabuğu, korumalı alan değildir. Onayı etkin bırakın, en düşük ayrıcalığa sahip kimlik bilgilerini kullanın ve kapsayıcı yalıtımı için DockerShellTool kullanın. Onayı devre dışı bırakmak için approval_mode="never_require" ve acknowledge_unsafe=True gerekir; ShellPolicy tek başına bir güvenlik sınırı değildir.
create_harness_agent, agent-framework-core sürümünde yayınlanır. Kabuk entegrasyonu, ön sürüm agent-framework-tools paketi tarafından sağlanır ve etkinleştirildiğinde bir ExperimentalWarning üretir.
Paketlenmiş bir Go Harness şu anda mevcut değil. Yerel kabuk aracını ve ortam sağlayıcısını doğrudan yalın bir Go ajanı üzerinde birleştirin.