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
Model tarafından oluşturulan kabuk komutlarına güvenilmemelidir. Yürütmeden önce bunları doğrulayın ve onaylayın. 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ı, standart çıkış ve standart hata için ayrı ayrı tutulan 64 KiB’lik sınırlar ve çalışma dizini yeniden bağlamayı kullanır.
as_function() üzerinden yapılan ajan çağrıları varsayılan olarak onay gerektirir.
run() için yapılan doğrudan çağrılar onay istemez.
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())
stdout doğrudan çağrıları, ayrı exit_code, stderr, truncated, timed_out, ShellResult ve run() alanlarına sahip bir duration_ms döndürür. shell OpenAI Yanıtları veya Foundry barındırma aracılığıyla çalıştığında, Agent Framework sağlayıcılar arası devamlılıkta standart çıkışı, standart hatayı, çıkış sonuçlarını ve zaman aşımı sonuçlarını korur. Sıfır dışı çıkışlar hata olarak kalır, standart hata ayrı kalır ve zaman aşımı başarılı bir çıkış olarak gösterilmez.
max_stdout_bytes veya max_stderr_bytes için bağımsız korumalı çıkış sınırlarını değiştirmek üzere pozitif DockerShellTool ve LocalShellTool değerleri ayarlayın.
Bu ayarlar, bir komutun üretebileceği miktarı değil, korunan çıkışı sınırlar.
Kesme bildirimleri ve UTF-8 yerine koyma karakteri, döndürülen metni yapılandırılan ham bayt izninden biraz daha büyük yapabilir.
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.
Kalıcı komutlar serileştirilir. Çıkış taşmasından sonra veya oturumu kurtarılamaz durumda bırakan bir zaman aşımından sonra, kuyruğa alınan komut yeni bir kabukta başlar ve sonlandırılan oturumdaki kabuk yerel değişkenlerini, işlevlerini ve çalışma dizini değişikliklerini kaybeder. Uygun şekilde kesintiye uğratılan POSIX zaman aşımı, mevcut kabuğu ve durumunu koruyabilir. Windows'ta zaman aşımı, kesintiye uğrayan komut tamamlanma işaretçisini yaysa bile her zaman mevcut kalıcı kabuğu kapatır.
close() çağrısı, kabuğu yeniden başlatmak yerine kapatmadan önce veya kapatma sırasında kuyruğa alınan komutları reddeder. Daha sonraki bir çağrı yeni bir oturum başlatabilir.
Önemli
LocalShellTool bir sandbox değildir. İnsan onayı bir gözden geçirme kapısı ekler, ancak kabuğu yalıtmaz. Aracı çağrıları için onayın devre dışı bırakılması acknowledge_unsafe=True gerektirir.
ile komutları kısıtla ShellPolicy
ShellPolicy yürütmeden önce komut metnine normal ifade izin verme ve reddetme listeleri uygular. Reddetme kuralları önceliklidir. Kabuğun sonuçta ne yürüttüğü veya dosya erişimini kısıtladığı incelenemez.
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",
# Unsafe for production as shown: these filters do not replace human approval or isolation.
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=("Use only these shell commands: ls, pwd, cat, git status/log/diff, python --version."),
tools=[client.get_shell_tool(func=shell.as_function())],
)
Warning
Örnek, insan onayını devre dışı bırakır ve yalnızca gizli bilgiler veya değerli veriler içermeyen yalıtılmış, tek kullanımlık bir ortam için uygundur. ve backticks gibi $(...) komut değiştirmeleri basit izin verme listesi desenlerini geçirebilir. Yalnızca komutun başlangıcıyla eşleşen desenler ek işlemlere de izin verebilir. Üretim için ayrı ayrı uygulanan yalıtım ve kısıtlı izinler kullanın. İnsan incelemesi ek bir kontrol sağlayabilir, ancak kabuğu izole etmez.
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 özel oluşturucu seçeneği olmadığında unsafe_extra_run_args kullanın.
Bu belirteçler Docker veya Podman komutuna aynen eklenir ve yapılandırılan yalıtım ve kaynak sınırlarını zayıflatabilir veya atlayabilir. Bunları geliştirici denetiminde tutun ve hiçbir zaman kullanıcı veya model çıkışından doldurmayın. Kullanılabilir olduğunda bunun yerine karşılık gelen 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 |
Yok; insan onayı varsayılan olarak etkindir |
| 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ı moda, 30 saniyelik bir zaman aşımına, standart çıkış ve standart hata için ayrı 64 KiB sınırlarına, çalışma dizini yeniden bağlamaya ve approval_mode="always_require"öğesine ayarlanı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.
Go harness varsayılan olarak bir kabuk aracı eklemez. Yapılandırmayı harness.AgentConfig'ye geçirmeden önce yerel kabuk aracını agent.Config.Tools öğesine ve ortam sağlayıcısını agent.Config.ContextProviders öğesine ekleyin. Yardımcı, çağıran tarafından sağlanan bu bileşenleri korur ve harness varsayılanlarını ekler.
Bkz. Kurulum ve onay gereksinimleri için Yerel kabuk aracını kullanın.