Hyperlight 是 Agent Framework 中目前有文件記錄的 CodeAct 後端。 它暴露了一個由獨立沙盒執行環境支援的 execute_code 工具,並可透過 call_tool(...) 呼叫提供者擁有的主機工具。
此整合採用 CodeAct 模式:提供者貢獻程式碼執行工具,並管理每次執行的執行環境。
關於模式層級的概述,請參見 CodeAct。
為什麼選擇 Hyperlight CodeAct
現代 Agent 受到的限制通常更多來自於工具呼叫的額外負荷,而不是模型本身。 一個讀取資料、執行輕度計算並組合結果的任務,很容易演變成一連串模型-> 工具-> 模型-> 工具的互動鏈,即使每個步驟都很簡單。
Hyperlight 支援的 CodeAct 會消除該迴圈。 模型會寫入一個簡短的 Python 程式,沙箱會執行它一次,並從沙箱內部透過call_tool(...)觸達提供者擁有的工具。 在具代表性的工具密集型工作負載中,這種轉移可將延遲約減半,代幣使用量減少超過 60%,同時保持執行隔離與可稽核。
安裝套件
dotnet add package Microsoft.Agents.AI.Hyperlight --prerelease
Microsoft.Agents.AI.Hyperlight是獨立於核心抽象之外發佈的,因此您只需在需要時才引入沙箱執行階段。
這很重要
.NET 套件目前還在預覽階段。 它相依於來自 Hyperlight.HyperlightSandbox.Apihyperlight-dev/hyperlight-sandbox 的 NuGet 套件;在該相依套件發佈到 nuget.org 之前,專案將無法還原。 追蹤上游沙盒儲存庫的可用狀態。
備註
Hyperlight 需要主機上的硬體虛擬化:Linux 上的 KVM 或 Windows 的 Windows 虛擬機平台(WHP)。
Wasm 後端還需要一個 Hyperlight Python guest 模組——在執行前將 HYPERLIGHT_PYTHON_GUEST_PATH 設定為其絕對路徑。
使用 HyperlightCodeActProvider
HyperlightCodeActProvider是當您想為每次執行自動新增 CodeAct 時的建議進入點。 它是一個會注入執行範圍內 CodeAct 指令以及execute_code工具的AIContextProvider,同時將提供者擁有的工具排除在直接 Agent 工具介面外。 提供者會在每次執行時套用快照/還原,讓訪客每次呼叫都從已知的乾淨狀態開始。
使用HyperlightCodeActProviderOptions.CreateForWasm(modulePath)工廠來針對樣本所使用的 Wasm 型 Python 客體;對於 JavaScript 後端也提供CreateForJavaScript()。
using Azure.AI.OpenAI;
using Azure.Identity;
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.Hyperlight;
using OpenAI.Chat;
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT")
?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
var deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-5.4-mini";
var guestPath = Environment.GetEnvironmentVariable("HYPERLIGHT_PYTHON_GUEST_PATH")
?? throw new InvalidOperationException("HYPERLIGHT_PYTHON_GUEST_PATH is not set.");
using var codeAct = new HyperlightCodeActProvider(
HyperlightCodeActProviderOptions.CreateForWasm(guestPath));
AIAgent agent = new AzureOpenAIClient(new Uri(endpoint), new DefaultAzureCredential())
.GetChatClient(deploymentName)
.AsAIAgent(new ChatClientAgentOptions()
{
ChatOptions = new()
{
Instructions = "You are a helpful assistant. When the user asks something quantitative, "
+ "write Python and call `execute_code` instead of guessing.",
},
AIContextProviders = [codeAct],
});
Console.WriteLine(await agent.RunAsync("What is the 20th Fibonacci number?"));
備註
對於特定的代理程式,只能附加一個 HyperlightCodeActProvider。 提供者使用固定狀態金鑰,因此 ChatClientAgent的狀態金鑰唯一性驗證會拒絕重複註冊。
HyperlightCodeActProvider 實作 IDisposable;使用 using 宣告,當代理不再需要時,底層沙箱會被釋放。
工具、檔案掛載及出站允許清單項目可透過 HyperlightCodeActProviderOptions(Tools、FileMounts、AllowedDomains、HostInputDirectory)預先提供,或透過提供者的 AddTools(...)、RemoveTools(...)、ClearTools()、AddFileMounts(...)、AddAllowedDomains(...) 以及對應的 Get* 存取子在執行階段管理。
審核與主機工具的運作方式
代理框架工具攜帶審核的元資料,控制是否能自動調用或必須暫停以供使用者核准。 在 .NET 中,若要選擇使用核准機制,可透過將AIFunction裝合在ApprovalRequiredAIFunction中來達成。
在代理上註冊工具 HyperlightCodeActProvider 與直接在代理上註冊的主要差別在於工具 的呼叫方式,而非函式最終執行的位置:
- 註冊在
HyperlightCodeActProviderOptions.Tools上的工具不會作為直接工具向模型顯示。 模型透過在execute_code內部寫入呼叫call_tool("name", ...)的程式碼來觸達它們。 - 直接註冊在 Agent 上的工具 (例如透過
AsAIAgent(tools: [...])) 會作為第一類工具呈現給模型,且每一次直接呼叫都會遵循該工具本身的核准中繼資料。
call_tool(...)是通往主機的橋樑;並非工具在沙箱內的重新實作。 這表示提供者擁有的工具仍可在主機程序中執行,使用主機程序能存取的任何檔案系統、網路和憑證。
CodeActApprovalMode列舉會控制execute_code工具本身的核准方式:
-
CodeActApprovalMode.NeverRequire(預設:核准會從註冊工具中傳遞。 如果登錄檔中的任何工具被包裹在ApprovalRequiredAIFunction,execute_code也需核准;否則則無需核准。 -
CodeActApprovalMode.AlwaysRequire:execute_code在呼叫前,總是需要使用者的批准。
一般來說:
- 將便宜、具決定性且可安全串連的工具放在提供者端,讓模型能夠在一個
execute_code回合中組合許多呼叫。 - 將具有副作用或敏感的操作封裝在
ApprovalRequiredAIFunction中(並考慮改為保留為直接的代理程式工具),以便讓每次叫用都能個別保持可見且可核准。
下一個範例會註冊兩個安全工具(fetch_docs、query_data),以及一個封裝在 send_email 中的敏感 ApprovalRequiredAIFunction 工具。 由於至少有一個註冊工具需要核准,預設 NeverRequire 模式會讓 execute_code 自己在每次被調用時都必須核准。
AIFunction fetchDocs = AIFunctionFactory.Create(
(string topic) => $"Docs for {topic}: (...)",
name: "fetch_docs",
description: "Fetch documentation for a given topic.");
AIFunction queryData = AIFunctionFactory.Create(
(string query) => $"Rows for `{query}`: []",
name: "query_data",
description: "Run a read-only SQL-like query against the sample store.");
AIFunction sendEmail = new ApprovalRequiredAIFunction(
AIFunctionFactory.Create(
(string to, string subject) => $"Sent '{subject}' to {to}.",
name: "send_email",
description: "Send an email on behalf of the user."));
var options = HyperlightCodeActProviderOptions.CreateForWasm(guestPath);
options.Tools = [fetchDocs, queryData, sendEmail];
using var codeAct = new HyperlightCodeActProvider(options);
AIAgent agent = new AzureOpenAIClient(new Uri(endpoint), new DefaultAzureCredential())
.GetChatClient(deploymentName)
.AsAIAgent(new ChatClientAgentOptions()
{
ChatOptions = new()
{
Instructions = "You are a helpful assistant. Prefer orchestrating your work in a single "
+ "`execute_code` block using `call_tool(...)` over issuing many direct tool calls.",
},
AIContextProviders = [codeAct],
});
因為主機工具運行在沙盒之外,FileMounts 和 AllowedDomains 限制的是沙盒程式碼本身,而不是 call_tool(...) 背後的主機回調。 當你需要對敏感資源的受控存取時,建議使用狹窄的主機工具,而不是擴大沙盒權限。
使用HyperlightExecuteCodeFunction進行直接接線
當你需要在同一個代理程式上同時混用 execute_code 與僅支援 direct 的工具,或沙盒設定在代理程式的整個生命週期內固定不變時,請改用 HyperlightExecuteCodeFunction,不要使用 provider。 它是獨立的 AIFunction,會在建構時擷取所提供選項的單一快照,並在每次叫用時重複使用該快照。
與 HyperlightCodeActProvider不同,獨立函式不會自動注入提示指引,因此你必須自行將 BuildInstructions(...) 輸出加入代理指令中。 當已註冊的工具只能透過 toolsVisibleToModel: false 存取時,請傳入 call_tool(...);如果相同的工具也直接提供給模型,則請傳入 true。
AIFunction calculate = AIFunctionFactory.Create(
(double a, double b) => a * b,
name: "multiply",
description: "Multiply two numbers.");
var options = HyperlightCodeActProviderOptions.CreateForWasm(guestPath);
options.Tools = [calculate];
using var executeCode = new HyperlightExecuteCodeFunction(options);
var instructions =
"You are a helpful assistant. When math is involved, solve it by writing Python "
+ "and calling `execute_code` instead of computing values yourself.\n\n"
+ executeCode.BuildInstructions(toolsVisibleToModel: false);
AIAgent agent = new AzureOpenAIClient(new Uri(endpoint), new DefaultAzureCredential())
.GetChatClient(deploymentName)
.AsAIAgent(instructions: instructions, tools: [executeCode]);
HyperlightExecuteCodeFunction 也會實作 IDisposable。 當設定需要核准(依據 ApprovalMode,或因為某個已設定的工具本身被包裝在 ApprovalRequiredAIFunction 中)時,該實例會透過 ApprovalRequiredAIFunction 提供一個 AITool.GetService(...) 代理,而框架的其餘部分也是藉此發現核准需求。
設置檔案與外部存取
Hyperlight 可以公開一個唯讀的/input樹狀結構,以及一個針對產生的成品的可寫入/output區域。
- 使用
HostInputDirectory,讓主機目錄可在/input/下使用。 - 可透過
FileMounts將特定主機路徑映射到沙盒new FileMount(hostPath, mountPath)中。 - 使用
AllowedDomains僅允許透過new AllowedDomain(target, methods)對特定目標或以特定方法進行對外存取。
var options = HyperlightCodeActProviderOptions.CreateForWasm(guestPath);
options.Tools = [compute];
options.FileMounts =
[
new FileMount("/host/data", "/input/data"),
new FileMount("/host/models", "/sandbox/models"),
];
options.AllowedDomains =
[
new AllowedDomain("https://api.github.com"),
new AllowedDomain("https://internal.api.example.com", ["GET"]),
];
using var codeAct = new HyperlightCodeActProvider(options);
相同的 FileMounts 和 AllowedDomains 集合以及工具,也可以在執行階段透過 AddFileMounts(...) 上的 RemoveFileMounts(...)、AddAllowedDomains(...)、RemoveAllowedDomains(...) 和 HyperlightCodeActProvider 進行修改。
輸出導引
若要從 execute_code 輸出文字,請以 print(...) 結束來賓程式碼;Hyperlight 不會自動回傳最後一個運算式的值。
啟用檔案系統存取時,請改將較大的成品改為寫入/output/<filename>。 回傳的檔案會附加在工具結果中,而下方 /input 的檔案則可在沙盒內閱讀。
目前的限制
此套件仍屬預覽階段,有幾項限制值得規劃:
- 該套件相依於
Hyperlight.HyperlightSandbox.Api,但該套件尚未發佈到 nuget.org。在它發佈之前,專案還原將會失敗。 - 平台支援遵循已發佈的 Hyperlight 後端套件:支援 Linux(KVM)與 Windows(WHP)環境。 不支援的平台或缺少虛擬化後端,建立沙盒時會失敗。
- 目前的 Wasm 後端會執行由
HYPERLIGHT_PYTHON_GUEST_PATH指定的 Python 客體模組。 JavaScript 後端(CreateForJavaScript())可供 JavaScript 來賓程式碼使用。 - 記憶體直譯器的狀態不會在不同
execute_code呼叫間持續存在。 當資料需要在跨呼叫期間存留時,請使用掛載的檔案和/output成品。 - 批准適用於整個
execute_code調用,而不是同一程式碼區塊內的每個call_tool(...)。 - 工具描述、參數註解和回傳形狀在這裡更重要,因為模型是根據該合約寫程式碼,而非選擇孤立的直接工具呼叫。
- 目前尚無 Python 基準測試範例的 .NET 對應版本——請參閱已發佈的比較工具 Python 標籤。
安裝套件
pip install agent-framework-hyperlight --pre
agent-framework-hyperlight與agent-framework-core分別獨立發佈,因此您只有在需要時才引入沙箱執行階段。
備註
此套件依賴 Hyperlight 沙盒元件。 如果後端還沒為你目前的平台發佈, execute_code 當它嘗試建立沙盒時會失敗。
使用 HyperlightCodeActProvider
HyperlightCodeActProvider是當您想為每次執行自動新增 CodeAct 時的建議進入點。 它會注入執行範圍內的 CodeAct 指令以及execute_code工具,同時將提供者擁有的工具排除在直接 Agent 工具介面外。
import os
from agent_framework import Agent
from agent_framework.foundry import FoundryChatClient
from agent_framework.hyperlight import HyperlightCodeActProvider
from azure.identity import AzureCliCredential
# 1. Create the Hyperlight-backed provider and register sandbox tools on it.
codeact = HyperlightCodeActProvider(
tools=[compute, fetch_data],
approval_mode="never_require",
)
# 2. Create the client and the agent.
agent = Agent(
client=FoundryChatClient(
project_endpoint=os.environ["FOUNDRY_PROJECT_ENDPOINT"],
model=os.environ["FOUNDRY_MODEL"],
credential=AzureCliCredential(),
),
name="HyperlightCodeActProviderAgent",
instructions="You are a helpful assistant.",
context_providers=[codeact],
)
# 3. Run a request that should use execute_code plus provider-owned tools.
query = (
"Fetch all users, find admins, multiply 7*(3*2), and print the users, "
"admins, and multiplication result. Use execute_code and call_tool(...) "
"inside the sandbox."
)
result = await agent.run(query)
print(result.text)
在提供者上註冊的工具可以透過call_tool(...)在沙箱內部使用,但它們不會作為直接的 Agent 工具公開。 提供者也透過add_tools(...)、remove_tool(...)、add_file_mounts(...)和add_allowed_domains(...)等方法,提供工具、檔案掛載及外站允許清單條目之 CRUD 式管理。
審核與主機工具的運作方式
代理框架工具具有approval_mode來控制是否可以自動調用或需要暫停以供使用者批准。
註冊工具於 HyperlightCodeActProvider 和直接註冊於 Agent(tools=...) 之間的主要差別在於工具的呼叫方式,而非 Python 函式最終的執行地點:
- 在
HyperlightCodeActProvider(tools=...)上註冊的工具不會作為直接工具向模型顯示。 模型透過在execute_code內部寫入呼叫call_tool("name", ...)的程式碼來觸達它們。 - 註冊在
Agent(tools=...)上的工具會作為第一類工具呈現給模型,且每一次直接呼叫都會遵循該工具本身的approval_mode。
call_tool(...)是通往主機的橋樑;並非工具在沙箱內的重新實作。 這表示提供者擁有的工具仍可在主機程序中執行,使用主機程序能存取的任何檔案系統、網路和憑證。
一般來說:
- 將便宜、具決定性且可安全串連的工具放在提供者端,讓模型能夠在一個
execute_code回合中組合許多呼叫。 - 將會產生副作用或受核准控制的作業保留為直接的 Agent 工具,通常搭配
approval_mode="always_require",以確保每一次叫用都是個別可見且可進行核准。
因為主機工具運行在沙盒之外,file_mounts 和 allowed_domains 限制的是沙盒程式碼本身,而不是 call_tool(...) 背後的主機回調。 當你需要對敏感資源的受控存取時,建議使用狹窄的主機工具,而不是擴大沙盒權限。
備註
透過 call_tool(...) 呼叫的工具會直接回傳其原生的 Python 值,包括 dict、list、原始物件或自訂物件,給客戶端。
FunctionTool上設定的任何result_parser都是針對面向 LLM 的取用者所設計,且不會在沙箱路徑中執行 — 若您需要供沙箱內的取用者使用,請直接在工具函式本身內部套用格式設定。
使用HyperlightExecuteCodeTool進行直接接線
當您需要在同一個 Agent 上混合使用execute_code和僅限直接呼叫的工具時,請改用HyperlightExecuteCodeTool而非提供者。 對於固定配置,你可以先建立一次 CodeAct 指令,然後直接接線工具:
from agent_framework.hyperlight import HyperlightExecuteCodeTool
execute_code = HyperlightExecuteCodeTool(
tools=[compute],
approval_mode="never_require",
)
codeact_instructions = execute_code.build_instructions(tools_visible_to_model=False)
當 CodeAct 表面固定且不需要每次執行都使用提供者生命週期時,此模式非常有用。 與 HyperlightCodeActProvider不同,獨立工具不會自動注入提示指引,因此你必須自行將輸出加入 build_instructions(...) 代理指令中。
設置檔案與外部存取
Hyperlight 可以公開一個唯讀的/input樹狀結構,以及一個針對產生的成品的可寫入/output區域。
- 使用
workspace_root來使工作區域在/input/下可用。 - 用
file_mounts來將特定的主機路徑映射到沙盒。 - 使用
allowed_domains來僅針對特定目標或方法啟用輸出存取。
file_mounts接受簡略字串、明確的(host_path, mount_path)配對,或FileMount具名 Tuple。
allowed_domains接受字串目標、明確的(target, method-or-methods)配對,或AllowedDomain具名 Tuple。
from agent_framework.hyperlight import HyperlightCodeActProvider
codeact = HyperlightCodeActProvider(
tools=[compute],
file_mounts=[
"/host/data",
("/host/models", "/sandbox/models"),
],
allowed_domains=[
"api.github.com",
("internal.api.example.com", "GET"),
],
)
輸出導引
要從 execute_code 中呈現文字,則以 print(...) 分號結尾。Hyperlight 不會自動回傳最後一個表達式的值。
啟用檔案系統存取時,請改將較大的成品改為寫入/output/<filename>。 回傳的檔案會附加在工具結果中,而下方 /input 的檔案則可在沙盒內閱讀。
比較 CodeAct 與直接工具呼叫
概念上的比較與任何 CodeAct 後端相同:相同的客戶端、模型、工具、提示詞與結構化輸出架構,可以透過傳統工具呼叫或 Hyperlight 支援的 CodeAct 連接。 唯一的差別在於工具介面 — 直接工具與由HyperlightCodeActProvider支援的單一execute_code工具:
from agent_framework import Agent
from agent_framework.foundry import FoundryChatClient
from agent_framework.hyperlight import HyperlightCodeActProvider
# Direct tool calling: the model picks one tool at a time per turn.
direct = Agent(
client=FoundryChatClient(...),
instructions="...",
tools=[fetch_data, compute],
)
# Hyperlight-backed CodeAct: the model writes one program per turn that
# orchestrates the same tools through call_tool(...).
codeact = Agent(
client=FoundryChatClient(...),
instructions="...",
context_providers=[
HyperlightCodeActProvider(
tools=[fetch_data, compute],
approval_mode="never_require",
),
],
)
對於透過反覆查找資料並執行輕度計算(許多小且可串接步驟)來計算資料集總額的工作負載,CodeAct 可以消除編排的負擔。 使用碼錶裝合這兩次執行,並檢查傳回的ChatResponse.usage,以便在您自己的環境中比較經過的時間與權杖使用量。
目前的限制
這個套件仍處於 alpha 階段,有幾個限制值得規劃:
- 平台支援遵循已發佈的 Hyperlight 後端套件。 如今,這代表支援的 Linux 和 Windows 環境;未支援的平台在建立沙盒時會失敗。
- 目前的系統整合執行 Python 客戶端程式碼。
- 記憶體直譯器的狀態不會在不同
execute_code呼叫間持續存在。 當資料需要在跨呼叫期間存留時,請使用掛載的檔案和/output成品。 - 批准適用於整個
execute_code調用,而不是同一程式碼區塊內的每個call_tool(...)。 - 工具描述、參數註解和回傳形狀在這裡更重要,因為模型是根據該合約寫程式碼,而非選擇孤立的直接工具呼叫。
備註
Go 對此功能的支援即將推出。 最新狀態請參閱 Agent Framework Go 倉庫 。