Hyperlight CodeAct

Hyperlight est le back-end actuellement documenté pour CodeAct dans Agent Framework. Il expose un execute_code outil soutenu par un runtime de bac à sable isolé et peut appeler des outils hôtes appartenant au fournisseur via call_tool(...).

Pour obtenir la vue d’ensemble au niveau du modèle, consultez CodeAct.

Pourquoi Hyperlight CodeAct

Les agents modernes sont souvent plus limités par la surcharge d’appel d’outils que par le modèle lui-même. Une tâche qui lit les données, effectue un calcul léger et assemble un résultat peut facilement se transformer en une chaîne de modèle -> outil -> modèle -> interactions des outils, même lorsque chaque étape individuelle est simple.

CodeAct, soutenu par Hyperlight, élimine cette boucle. Le modèle écrit un programme Python court, le bac à sable l’exécute une seule fois, et les outils appartenant au fournisseur sont accessibles à partir de l’intérieur du bac à sable avec call_tool(...). Dans les charges de travail représentatives nécessitant beaucoup d’outils, ce décalage peut réduire la latence d’environ moitié et l'utilisation de jetons de plus de 60 %, tout en conservant l’exécution isolée et auditable.

Get started

À venir.

Installer le package

pip install agent-framework-hyperlight --pre

agent-framework-hyperlight est fourni séparément de agent-framework-core, de sorte que vous n'utilisez l'environnement d'exécution sandbox que lorsque vous en avez besoin.

Note

Le package dépend des composants de sandbox Hyperlight. Si le back-end n’est pas encore publié pour votre plateforme actuelle, execute_code échoue quand il tente de créer le bac à sable.

Utilisez HyperlightCodeActProvider.

HyperlightCodeActProvider est le point d’entrée recommandé lorsque vous souhaitez que CodeAct soit ajouté automatiquement pour chaque exécution. Il injecte des instructions CodeAct limitées à l’exécution ainsi que l'outil execute_code, tout en empêchant les outils appartenant au fournisseur d’apparaître sur la surface des outils de l'agent direct.

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}")

Les outils enregistrés auprès du fournisseur sont disponibles à l’intérieur du sandbox via call_tool(...), mais ils ne sont pas exposés comme des outils d'agents directs. Le fournisseur expose également la gestion de style CRUD pour les outils, les montages de fichiers et les entrées de liste blanche sortante via des méthodes telles que add_tools(...), remove_tool(...), add_file_mounts(...), et add_allowed_domains(...).

Fonctionnement des approbations et des outils hôtes

Les outils Agent Framework contiennent un approval_mode paramètre qui contrôle s’ils peuvent être appelés automatiquement ou doivent suspendre pour l’approbation de l’utilisateur.

La principale différence entre l’inscription d’un outil HyperlightCodeActProvider et son inscription directement sur Agent(tools=...)la façon dont l’outil est appelé, et non l’endroit où la fonction Python s’exécute finalement :

  • Les outils inscrits HyperlightCodeActProvider(tools=...) sont masqués du modèle en tant qu’outils directs. Le modèle les atteint en écrivant un code qui appelle call_tool("name", ...) dans execute_code.
  • Les outils inscrits sur Agent(tools=...) sont exposés au modèle en tant qu’outils de première classe, et chaque appel direct respecte les propriétés propres de cet outil.

call_tool(...) est un pont vers les rappels de l'hôte ; ce n'est pas une réimplémentation dans un bac à sable d'un outil. Cela signifie que les outils appartenant au fournisseur s’exécutent toujours dans le processus hôte, avec le système de fichiers, le réseau et les informations d’identification auxquels le processus hôte lui-même peut accéder.

En règle générale :

  • Placez des outils bon marché, déterministes et sécurisés pour l'enchaînement sur le fournisseur afin que le modèle puisse composer de nombreux appels au cours d’un execute_code tour.
  • Conservez les opérations ayant des effets secondaires ou soumises à approbation en tant qu'outils d'agent direct, souvent avec approval_mode="always_require", afin que chaque invocation reste visible et puisse être approuvée individuellement.

Étant donné que les outils hôtes s'exécutent en dehors du bac à sable, file_mounts et allowed_domains restreignent le code en bac à sable lui-même, et non le rappel de l’hôte derrière call_tool(...). Lorsque vous avez besoin d’un accès contrôlé à une ressource sensible, préférez un outil hôte étroit à l’élargissement des autorisations de bac à sable.

Note

Les outils appelés via call_tool(...) retournent leur valeur de Python native (dict, list, primitive ou objet personnalisé) directement à l’invité. Toute result_parser configuration effectuée sur un FunctionTool est destinée aux consommateurs LLM et ne s’exécute pas dans le chemin d’accès au bac à sable — appliquez la mise en forme à l’intérieur de la fonction de l’outil elle-même si vous en avez besoin pour les consommateurs dans le bac à sable.

Utiliser HyperlightExecuteCodeTool pour le câblage direct

Lorsque vous devez combiner execute_code avec des outils uniquement directs sur le même agent, privilégiez l'utilisation de HyperlightExecuteCodeTool au lieu du fournisseur. Pour les configurations fixes, vous pouvez générer les instructions CodeAct une fois et connecter l’outil directement :

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)

Ce modèle est utile lorsque la surface CodeAct est fixe et que vous n’avez pas besoin du cycle de vie du fournisseur à chaque exécution. Contrairement à HyperlightCodeActProvider, l’outil autonome n’injecte pas automatiquement des instructions d'incitation, vous devez donc ajouter vous-même la build_instructions(...) sortie aux instructions de l’agent.

Configurer les fichiers et l’accès sortant

Hyperlight peut exposer une arborescence en lecture seule /input et une zone modifiable /output pour les artefacts générés.

  • Utilisez workspace_root pour rendre un espace de travail disponible sous /input/.
  • Utilisez file_mounts pour mapper des chemins d’accès d’hôte spécifiques dans le bac à sable.
  • Permet allowed_domains d’activer l’accès sortant uniquement pour des cibles ou méthodes spécifiques.

file_mounts accepte soit une chaîne abrégée, soit une paire explicite (host_path, mount_path), ou un tuple nommé FileMount. allowed_domains accepte une chaîne cible, une paire explicite (target, method-or-methods) ou un AllowedDomain tuple nommé.

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

Recommandations sur les sorties

Pour exposer le texte à partir de execute_code, terminez le code par print(...); Hyperlight ne retourne pas automatiquement la valeur de la dernière expression.

Lorsque l’accès au système de fichiers est activé, écrivez des artefacts plus volumineux à la place de /output/<filename>. Les fichiers retournés sont attachés au résultat de l’outil, tandis que les fichiers sous /input sont disponibles pour la lecture dans le bac à sable.

Comparer CodeAct et l'appel direct d'outil

L’exemple de benchmark exécute la même tâche avec le même client, le même modèle, les outils, les invites et le schéma de sortie structuré une fois par l’appel d’outil traditionnel et une fois par le biais de CodeAct soutenu par Hyperlight. La seule différence est le câblage : outils directs et un seul execute_code outil soutenu par 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

Dans cet exemple, l’agent calcule les totaux généraux sur un jeu de données d’utilisateurs et de commandes en recherchant à plusieurs reprises des données et en effectuant des calculs légers. C’est exactement le type de workflow à plusieurs petites étapes où CodeAct peut supprimer la surcharge d’orchestration. L'exemple complet affiche le temps écoulé et l'utilisation des jetons pour les deux essais, vous permettant ainsi de comparer les performances dans votre propre environnement.

Limitations actuelles

Le package est encore en version alpha, et quelques contraintes valent la peine d'être prises en compte.

  1. La prise en charge de la plateforme suit les packages back-end Hyperlight publiés. Aujourd'hui, cela signifie que les environnements Linux et Windows sont pris en charge, tandis que les plateformes non prises en charge échoueront lors de la création du bac à sable.
  2. L’intégration actuelle exécute le code invité Python. La documentation .NET sera bientôt disponible.
  3. L’état de l’interpréteur en mémoire n’est pas conservé entre les appels distincts execute_code . Utilisez des fichiers montés et des artefacts /output lorsque les données doivent persister entre les appels.
  4. L’approbation s’applique à l’appel execute_code dans son ensemble, et non à chaque individu call_tool(...) à l’intérieur du même bloc de code.
  5. Les descriptions des outils, les annotations de paramètres et les formes de retour ont plus d'importance ici, car le modèle écrit du code conformément à ce contrat plutôt que de choisir des appels directs d’outils isolés.

Étapes suivantes