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.

Introdução

Brevemente.

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.

async def main() -> None:
    """Run the provider-owned Hyperlight CodeAct sample."""
    # 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],
        middleware=[log_function_calls],
    )

    # 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."
    )
    print(f"{_CYAN}{'=' * 60}")
    print("Hyperlight CodeAct provider sample")
    print(f"{'=' * 60}{_RESET}")
    print(f"{_CYAN}User: {query}{_RESET}")
    result = await agent.run(query)
    print(f"{_CYAN}Agent: {result.text}{_RESET}")

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.

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

O exemplo de benchmark executa a mesma tarefa com o mesmo cliente, modelo, ferramentas, prompt e esquema de saída estruturado, uma vez através da chamada tradicional de ferramentas e outra através do CodeAct suportado por Hyperlight. A única diferença é a cablagem: ferramentas diretas versus uma única execute_code ferramenta apoiada por HyperlightCodeActProvider.

async def _run_traditional() -> tuple[float, AgentResponse]:
    agent = Agent(
        client=get_client(),
        name="TraditionalAgent",
        instructions=INSTRUCTIONS,
        tools=TOOLS,
        default_options={"response_format": UserGrandTotals},
    )
    start = time.perf_counter()
    result = await agent.run(BENCHMARK_PROMPT)
    elapsed = time.perf_counter() - start
    return elapsed, result


async def _run_codeact() -> tuple[float, AgentResponse]:
    codeact = HyperlightCodeActProvider(
        tools=TOOLS,
        approval_mode="never_require",
    )
    agent = Agent(
        client=get_client(),
        name="CodeActAgent",
        instructions=INSTRUCTIONS,
        context_providers=[codeact],
        default_options={"response_format": UserGrandTotals},
    )
    start = time.perf_counter()
    result = await agent.run(BENCHMARK_PROMPT)
    elapsed = time.perf_counter() - start
    return elapsed, result

Nessa amostra, o agente calcula totais globais num conjunto de dados de utilizadores e encomendas, consultando repetidamente dados e realizando cálculos leves. Esse é exatamente o tipo de fluxo de trabalho de muitos pequenos passos onde o CodeAct pode eliminar a sobrecarga de orquestração. O exemplo completo mostra o tempo decorrido e a utilização de tokens para ambas as execuções, permitindo-lhe comparar o formato de execução 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. A documentação do .NET ainda está a chegar em breve.
  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