Hyperlight CodeAct

O Hyperlight é o backend atualmente documentado para o CodeAct no Agent Framework. Expõe uma execute_code ferramenta suportada por um runtime sandbox isolado e pode chamar, através de call_tool(...), as ferramentas hospedeiras pertencentes aos fornecedores.

Para a visão geral ao nível do padrão, veja CodeAct.

Porquê o Hyperlight CodeAct

Agentes modernos são frequentemente mais restritos pela sobrecarga na utilização de ferramentas do que pelo modelo em si. Uma tarefa que lê dados, realiza cálculos leves e monta um resultado pode facilmente transformar-se em uma cadeia de interações modelo-ferramenta-modelo-ferramenta>>>, mesmo quando cada passo individual é simples.

O CodeAct apoiado por Hyperlight colapsa esse ciclo. O modelo escreve um programa Python curto, o sandbox executa-o uma vez, e as ferramentas pertencentes ao fornecedor são acedidas a partir do interior do sandbox com call_tool(...). Em cargas de trabalho representativas e pesadas em ferramentas, essa mudança pode reduzir a latência aproximadamente para metade e o uso de tokens em mais de 60%, mantendo a execução isolada e auditável.

Instale o pacote

dotnet add package Microsoft.Agents.AI.Hyperlight --prerelease

Microsoft.Agents.AI.Hyperlight é distribuído separadamente das abstrações principais, pelo que só tens de incluir o ambiente de execução em sandbox quando precisares dele.

Importante

O pacote .NET está em pré-visualização. Depende do Hyperlight.HyperlightSandbox.Api pacote NuGet do hyperlight-dev/hyperlight-sandbox; até que essa dependência seja publicada para nuget.org o projeto não conseguirá restaurar. Monitorize o repositório sandbox upstream quanto à disponibilidade.

Observação

O Hyperlight requer virtualização de hardware no host: KVM no Linux ou a Plataforma Hipervisor do Windows (WHP) no Windows. O backend Wasm requer ainda um módulo guest Python do Hyperlight — defina HYPERLIGHT_PYTHON_GUEST_PATH com o respetivo caminho absoluto antes de executar.

Utilize HyperlightCodeActProvider

HyperlightCodeActProvider é o ponto de entrada recomendado quando queres que o CodeAct seja adicionado automaticamente em cada execução. É um AIContextProvider que injeta instruções CodeAct de âmbito de execução, bem como a ferramenta execute_code, mantendo as ferramentas pertencentes ao fornecedor fora da superfície direta de ferramentas do agente. O fornecedor aplica snapshot/restore em cada execução para que o sistema convidado arranque sempre de um estado limpo e conhecido em cada invocação.

Use a fábrica HyperlightCodeActProviderOptions.CreateForWasm(modulePath) para direcionar o Python convidado baseado em Wasm usado pelas amostras; CreateForJavaScript() também está disponível para o backend JavaScript.

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?"));

Observação

Apenas um HyperlightCodeActProvider pode ser associado a um determinado agente. O fornecedor utiliza uma chave de estado fixa, pelo que ChatClientAgenta validação da unicidade da chave de estado rejeita registos duplicados. HyperlightCodeActProvider implementa IDisposable; usa uma using declaração para que o sandbox subjacente seja libertado quando o agente já não for necessário.

Ferramentas, montagens de ficheiros e entradas da lista de permissões de saída podem ser fornecidas antecipadamente através de HyperlightCodeActProviderOptions (Tools, FileMounts, AllowedDomains, HostInputDirectory) ou geridas em tempo de execução através de AddTools(...), RemoveTools(...), ClearTools(), AddFileMounts(...) e AddAllowedDomains(...) do fornecedor, e dos correspondentes acessores Get*.

Como funcionam as aprovações e as ferramentas de alojamento

As ferramentas do Agent Framework transportam metadados de aprovação que controlam se podem ser invocadas automaticamente ou se têm de ser pausadas para aprovação do utilizador. No .NET, a aprovação é opcional, encapsulando um AIFunction em ApprovalRequiredAIFunction.

A principal diferença entre registar uma ferramenta em HyperlightCodeActProvider e registrá-la diretamente no agente é a forma como a ferramenta é invocada, e não onde a função acaba por ser executada:

  • As ferramentas registadas em HyperlightCodeActProviderOptions.Tools são ocultas do modelo como ferramentas diretas. O modelo acede a eles escrevendo código que chama call_tool("name", ...) dentro de execute_code.
  • As ferramentas registadas diretamente no agente (por exemplo, via AsAIAgent(tools: [...])) são disponibilizadas ao modelo como ferramentas de primeira classe, e cada chamada direta respeita os metadados de aprovação da própria ferramenta.

call_tool(...) é uma ponte de retorno para os callbacks do sistema anfitrião; não é uma reimplementação no ambiente isolado da ferramenta. Isto significa que as ferramentas pertencentes ao fornecedor continuam a ser executadas no processo anfitrião, com qualquer sistema de ficheiros, rede e credenciais a que o próprio processo anfitrião possa aceder.

O CodeActApprovalMode enum determina como a própria ferramenta execute_code é aprovada:

  • CodeActApprovalMode.NeverRequire (predefinição): a aprovação é propagada das ferramentas registadas. Se alguma ferramenta do registo estiver envolvida em ApprovalRequiredAIFunction, execute_code também requer aprovação; caso contrário, não requer.
  • CodeActApprovalMode.AlwaysRequire: execute_code requer sempre aprovação do utilizador antes da invocação.

Como regra geral:

  • Coloque ferramentas baratas, determinísticas e seguras de encadear no fornecedor para que o modelo possa compor muitas chamadas numa só execute_code vez.
  • Inclua operações ApprovalRequiredAIFunction de efeito secundário ou sensíveis (e considere mantê-las como ferramentas de agente direto) para que cada invocação permaneça visível e aprovável individualmente.

A amostra seguinte regista duas ferramentas seguras (fetch_docs, query_data) mais uma ferramenta sensível send_email envolvida em ApprovalRequiredAIFunction. Como pelo menos uma ferramenta registada requer aprovação, o modo padrão NeverRequire faz execute_code com que ele próprio precise de aprovação sempre que é invocado.

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],
    });

Porque as ferramentas de host correm fora do sandbox, FileMounts e AllowedDomains restringem o código que está sandboxed, não o callback do host por trás de call_tool(...). Quando precisar de acesso controlado a um recurso sensível, prefira uma ferramenta de anfitrião específica em vez de alargar permissões de sandbox.

Use HyperlightExecuteCodeFunction para cablagem direta

Quando precisar de misturar execute_code com ferramentas exclusivamente diretas no mesmo agente, ou a configuração da sandbox for fixa ao longo da vida útil do agente, use HyperlightExecuteCodeFunction em vez do provedor. É uma instância autónoma AIFunction que captura uma única captura instantânea das opções fornecidas aquando da construção e a reutiliza em cada invocação.

Ao contrário de HyperlightCodeActProvider, a função autónoma não injeta automaticamente orientações do prompt, pelo que é da sua responsabilidade adicionar manualmente a saída BuildInstructions(...) às instruções do agente. Passe toolsVisibleToModel: false quando as ferramentas registadas só são acessíveis através de call_tool(...), e true quando as mesmas ferramentas também estiverem expostas diretamente ao modelo.

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 também implementa IDisposable. Quando a configuração requer aprovação (por ApprovalMode ou porque uma ferramenta configurada está ela própria encapsulada em ApprovalRequiredAIFunction), a instância expõe um proxy ApprovalRequiredAIFunction através de AITool.GetService(...), que é a forma como o restante framework identifica os requisitos de aprovação.

Configurar ficheiros e acesso de saída

A hiperluz pode expor uma árvore de apenas /input leitura e uma área gravável /output para artefactos gerados.

  • Use HostInputDirectory para disponibilizar um diretório anfitrião em /input/.
  • Utilize FileMounts para mapear caminhos específicos do anfitrião no sandbox através de new FileMount(hostPath, mountPath).
  • Use AllowedDomains para permitir o acesso de saída apenas para destinos ou métodos específicos através de 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);

As mesmas coleções FileMounts e AllowedDomains, bem como ferramentas, também podem ser modificadas em tempo de execução através de AddFileMounts(...), RemoveFileMounts(...), AddAllowedDomains(...) e RemoveAllowedDomains(...) em HyperlightCodeActProvider.

Orientação de saída

Para apresentar texto de execute_code, termine o código guest com print(...); o Hyperlight não devolve automaticamente o valor da última expressão.

Quando o acesso ao sistema de ficheiros estiver ativado, escreva artefactos maiores em /output/<filename> em vez disso. Os ficheiros devolvidos são anexados ao resultado da ferramenta, enquanto os ficheiros abaixo /input estão disponíveis para leitura dentro do sandbox.

Limitações atuais

Este pacote ainda está em versão preliminar, e convém ter em conta no planeamento algumas restrições:

  1. O pacote depende de Hyperlight.HyperlightSandbox.Api, que ainda não foi publicado em nuget.org. Até que isso seja lançado, a restauração do projeto falhará.
  2. O suporte da plataforma segue os pacotes de backend Hyperlight publicados: ambientes suportados de Linux (KVM) e Windows (WHP). Plataformas não suportadas ou back-ends de virtualização em falta falham ao criar o sandbox.
  3. O backend atual do Wasm executa um módulo convidado Python especificado por HYPERLIGHT_PYTHON_GUEST_PATH. O backend JavaScript (CreateForJavaScript()) está disponível para código convidado em JavaScript.
  4. O estado do interpretador em memória não persiste entre chamadas distintas execute_code. Use ficheiros montados e /output artefactos quando é necessário que os dados sejam mantidos entre chamadas.
  5. A aprovação aplica-se à execute_code invocação como um todo, não a cada indivíduo call_tool(...) dentro do mesmo bloco de código.
  6. Descrições de ferramentas, anotações de parâmetros e formas de retorno importam mais aqui porque o modelo está a escrever código em conformidade com esse contrato em vez de optar por chamadas diretas de ferramentas isoladas.
  7. Ainda não existe um equivalente em .NET ao exemplo de benchmark em Python — consulte o separador Python para a infraestrutura de comparação publicada.

Instale o pacote

pip install agent-framework-hyperlight --pre

agent-framework-hyperlight Vem separadamente de agent-framework-core, por isso só assumes o tempo de execução sandbox quando precisares.

Observação

O pacote depende dos componentes sandbox da Hyperlight. Se o backend ainda não for publicado para a tua plataforma atual, execute_code falha quando tenta criar o sandbox.

Utilize HyperlightCodeActProvider

HyperlightCodeActProvider é o ponto de entrada recomendado quando queres que o CodeAct seja adicionado automaticamente em cada execução. Injeta instruções CodeAct com escopo de tempo de execução juntamente com a ferramenta execute_code, mantendo as ferramentas pertencentes ao fornecedor fora da interface direta de ferramentas do agente.

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)

As ferramentas registadas no fornecedor estão disponíveis dentro do sandbox através de call_tool(...), mas não são expostas como ferramentas de agente direto. O fornecedor também expõe gestão ao estilo CRUD para ferramentas, montagens de ficheiros e entradas de listas de permissões de saída através de métodos como add_tools(...), remove_tool(...), add_file_mounts(...), e add_allowed_domains(...).

Como funcionam as aprovações e as ferramentas de alojamento

As ferramentas do Agent Framework contêm um approval_mode que controla se podem ser invocadas automaticamente ou se devem pausar para aprovação do utilizador.

A principal diferença entre registar uma ferramenta em HyperlightCodeActProvider e registar diretamente em Agent(tools=...) é como a ferramenta é invocada, e não onde a função Python acaba por correr:

  • As ferramentas registadas em HyperlightCodeActProvider(tools=...) são ocultas do modelo como ferramentas diretas. O modelo acede a eles escrevendo código que chama call_tool("name", ...) dentro de execute_code.
  • As ferramentas são registadas em Agent(tools=...) e apresentadas ao modelo como ferramentas de primeira classe, e cada chamada direta respeita a própria approval_mode de cada ferramenta.

call_tool(...) é uma ponte de retorno para os callbacks do sistema anfitrião; não é uma reimplementação no ambiente isolado da ferramenta. Isto significa que as ferramentas pertencentes ao fornecedor continuam a ser executadas no processo anfitrião, com qualquer sistema de ficheiros, rede e credenciais a que o próprio processo anfitrião possa aceder.

Como regra geral:

  • Coloque ferramentas baratas, determinísticas e seguras de encadear no fornecedor para que o modelo possa compor muitas chamadas numa só execute_code vez.
  • Mantenha operações de efeito secundário ou submetidas a aprovação como ferramentas diretas do agente, muitas vezes com approval_mode="always_require", para que cada invocação se mantenha individualmente visível e passível de aprovação.

Porque as ferramentas de host correm fora do sandbox, file_mounts e allowed_domains restringem o código que está sandboxed, não o callback do host por trás de call_tool(...). Quando precisar de acesso controlado a um recurso sensível, prefira uma ferramenta de anfitrião específica em vez de alargar permissões de sandbox.

Observação

Ferramentas invocadas através de call_tool(...) retornam o seu valor nativo de Python (dict, list, objeto primitivo ou personalizado) diretamente ao convidado. Qualquer result_parser configurado num FunctionTool é destinado a consumidores voltados para LLM e não executa no caminho da sandbox — aplique a formatação dentro da função da própria ferramenta se precisar para consumidores dentro do sandbox.

Use HyperlightExecuteCodeTool para cablagem direta

Quando precisar de misturar execute_code com ferramentas exclusivamente diretas no mesmo agente, use HyperlightExecuteCodeTool em vez do fornecedor. Para configurações fixas, podes compilar as instruções do CodeAct uma vez e ligar a ferramenta diretamente:

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)

Este padrão é útil quando a superfície do CodeAct é fixa e não é necessário o ciclo de vida do fornecedor em cada execução. Ao contrário de HyperlightCodeActProvider, a ferramenta autónoma não injeta automaticamente a orientação de prompt, por isso é responsável por adicionar a saída build_instructions(...) às instruções do agente por si próprio.

Configurar ficheiros e acesso de saída

A hiperluz pode expor uma árvore de apenas /input leitura e uma área gravável /output para artefactos gerados.

  • Use workspace_root para disponibilizar um espaço de trabalho em /input/.
  • Use file_mounts para mapear caminhos específicos do host no ambiente de sandbox.
  • Use allowed_domains para permitir o acesso de saída apenas para alvos ou métodos específicos.

file_mounts aceita uma sequência abreviada, um par explícito (host_path, mount_path) ou uma FileMount tupla nomeada. allowed_domains aceita uma cadeia de caracteres como alvo, um par explícito (target, method-or-methods) ou uma AllowedDomain tupla nomeada.

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"),
    ],
)

Orientação de saída

Para mostrar texto a partir de execute_code, terminar o código com print(...); O hiperluz não devolve automaticamente o valor da última expressão.

Quando o acesso ao sistema de ficheiros estiver ativado, escreva artefactos maiores em /output/<filename> em vez disso. Os ficheiros devolvidos são anexados ao resultado da ferramenta, enquanto os ficheiros abaixo /input estão disponíveis para leitura dentro do sandbox.

Compare o CodeAct e a chamada direta de ferramentas

A comparação conceitual é a mesma que para qualquer backend do CodeAct: o mesmo cliente, modelo, ferramentas, prompt e esquema de saída estruturado podem ser interligados quer através da invocação tradicional de ferramentas quer através do CodeAct assente no Hyperlight. A única diferença é a superfície da ferramenta — ferramentas diretas versus uma única execute_code ferramenta apoiada por HyperlightCodeActProvider:

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",
        ),
    ],
)

Para cargas de trabalho que calculam totais num conjunto de dados, consultando repetidamente dados e efetuando processamento leve — muitos passos pequenos, encadeáveis — o CodeAct pode eliminar a sobrecarga de orquestração. Cronometre ambas as execuções e inspecione o ChatResponse.usage devolvido para comparar o tempo decorrido e a utilização de tokens no seu próprio ambiente.

Limitações atuais

Este pacote ainda é alfa, e há algumas limitações que valem a pena planear:

  1. O suporte à plataforma segue os pacotes de backend Hyperlight publicados. Hoje isso significa ambientes Linux e Windows suportados; Plataformas não suportadas falham ao criar o sandbox.
  2. A integração atual executa código convidado em Python.
  3. O estado do interpretador em memória não persiste entre chamadas distintas execute_code. Use ficheiros montados e /output artefactos quando é necessário que os dados sejam mantidos entre chamadas.
  4. A aprovação aplica-se à execute_code invocação como um todo, não a cada indivíduo call_tool(...) dentro do mesmo bloco de código.
  5. Descrições de ferramentas, anotações de parâmetros e formas de retorno importam mais aqui porque o modelo está a escrever código em conformidade com esse contrato em vez de optar por chamadas diretas de ferramentas isoladas.

Passos seguintes