chore: import upstream snapshot with attribution
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
dotnet-build-and-test / dotnet-test-functions (push) Has been cancelled
dotnet-build-and-test / paths-filter (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Debug, windows-latest, net9.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Release, ubuntu-latest, net10.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Release, ubuntu-latest, net8.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Release, windows-latest, net472) (push) Has been cancelled
dotnet-build-and-test / dotnet-test (Release, integration, true, ubuntu-latest, net10.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-test (Release, integration, true, windows-latest, net472) (push) Has been cancelled
dotnet-build-and-test / dotnet-foundry-hosted-it (push) Has been cancelled
dotnet-build-and-test / dotnet-build-and-test-check (push) Has been cancelled
dotnet-build-and-test / Integration Test Report (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 13:39:25 +08:00
commit db620d33df
5151 changed files with 925932 additions and 0 deletions
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) Microsoft Corporation.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE
+139
View File
@@ -0,0 +1,139 @@
# agent-framework-hyperlight
Hyperlight-backed CodeAct integrations for Microsoft Agent Framework.
## Installation
```bash
pip install agent-framework-hyperlight --pre
```
This package depends on `hyperlight-sandbox`, the packaged Python guest, and the
Wasm backend package on supported platforms. If the backend is not published for
your current platform yet, `execute_code` will fail at runtime when it tries to
create the sandbox.
## Quick start
### Context provider (recommended)
Use `HyperlightCodeActProvider` to automatically inject the `execute_code` tool
and CodeAct instructions into every agent run. Tools registered on the provider
are available inside the sandbox via `call_tool(...)` but are **not** exposed as
direct agent tools.
```python
from agent_framework import Agent, tool
from agent_framework_hyperlight import HyperlightCodeActProvider
@tool
def compute(operation: str, a: float, b: float) -> float:
"""Perform a math operation."""
ops = {"add": a + b, "subtract": a - b, "multiply": a * b, "divide": a / b}
return ops[operation]
codeact = HyperlightCodeActProvider(
tools=[compute],
approval_mode="never_require",
)
agent = Agent(
client=client,
name="CodeActAgent",
instructions="You are a helpful assistant.",
context_providers=[codeact],
)
result = await agent.run("Multiply 6 by 7 using execute_code.")
```
### Standalone tool
Use `HyperlightExecuteCodeTool` directly when you want full control over how the
tool is added to the agent. This is useful when mixing sandbox tools with
direct-only tools on the same agent.
```python
from agent_framework import Agent, tool
from agent_framework_hyperlight import HyperlightExecuteCodeTool
@tool
def send_email(to: str, subject: str, body: str) -> str:
"""Send an email (direct-only, not available inside the sandbox)."""
return f"Email sent to {to}"
execute_code = HyperlightExecuteCodeTool(
tools=[compute],
approval_mode="never_require",
)
agent = Agent(
client=client,
name="MixedToolsAgent",
instructions="You are a helpful assistant.",
tools=[send_email, execute_code],
)
```
### Manual static wiring
For fixed configurations where provider lifecycle overhead is unnecessary, build
the CodeAct instructions once and pass them to the agent at construction time:
```python
execute_code = HyperlightExecuteCodeTool(
tools=[compute],
approval_mode="never_require",
)
codeact_instructions = execute_code.build_instructions(tools_visible_to_model=False)
agent = Agent(
client=client,
name="StaticWiringAgent",
instructions=f"You are a helpful assistant.\n\n{codeact_instructions}",
tools=[execute_code],
)
```
### File mounts and network access
Mount host directories into the sandbox and allow outbound HTTP to specific
domains:
```python
from agent_framework_hyperlight import HyperlightCodeActProvider, FileMount
codeact = HyperlightCodeActProvider(
tools=[compute],
file_mounts=[
"/host/data", # shorthand — same path in sandbox
("/host/models", "/sandbox/models"), # explicit host → sandbox mapping
FileMount("/host/config", "/sandbox/config"), # named tuple
],
allowed_domains=[
"api.github.com", # all methods
("internal.api.example.com", "GET"), # GET only
],
)
```
## Notes
- This package is intentionally separate from `agent-framework-core` so CodeAct
usage and installation remain optional. With `agent-framework-core[all]` (or
the meta `agent-framework`) installed it is also reachable through the
lazy-loading namespace `agent_framework.hyperlight`.
- `file_mounts` accepts a single string shorthand, an explicit `(host_path,
mount_path)` pair, or a `FileMount` named tuple. The host-side path in the
explicit forms may be a `str` or `Path`. Use the explicit two-value form when
the host path differs from the sandbox path.
- `allowed_domains` accepts a single string target such as `"github.com"` to
allow all backend-supported methods, an explicit `(target, method_or_methods)`
tuple such as `("github.com", "GET")`, or an `AllowedDomain` named tuple.
- Tools registered with the sandbox return their native Python value
(`dict`, `list`, primitives, or custom objects) directly to the guest via the
Hyperlight FFI. Any `result_parser` configured on a `FunctionTool` is
intended for LLM-facing consumers and does not run on the sandbox path —
apply formatting inside the tool function itself if you need it for
in-sandbox consumers.
@@ -0,0 +1,24 @@
# Copyright (c) Microsoft. All rights reserved.
from __future__ import annotations
import importlib.metadata
from ._execute_code_tool import HyperlightExecuteCodeTool
from ._provider import HyperlightCodeActProvider
from ._types import AllowedDomain, AllowedDomainInput, FileMount, FileMountInput
try:
__version__ = importlib.metadata.version(__name__)
except importlib.metadata.PackageNotFoundError:
__version__ = "0.0.0"
__all__ = [
"AllowedDomain",
"AllowedDomainInput",
"FileMount",
"FileMountInput",
"HyperlightCodeActProvider",
"HyperlightExecuteCodeTool",
"__version__",
]
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,139 @@
# Copyright (c) Microsoft. All rights reserved.
from __future__ import annotations
from collections.abc import Sequence
from agent_framework import FunctionTool
from ._types import AllowedDomain
def _format_tool_summaries(tools: Sequence[FunctionTool]) -> str:
if not tools:
return "- No tools are currently registered inside the sandbox."
lines: list[str] = []
for tool_obj in tools:
parameters = tool_obj.parameters().get("properties", {})
parameter_names = [name for name in parameters if isinstance(name, str)]
parameter_summary = ", ".join(parameter_names) if parameter_names else "none"
description = str(tool_obj.description or "").strip() or "No description provided."
lines.append(f"- `{tool_obj.name}`: {description} Parameters: {parameter_summary}.")
return "\n".join(lines)
def _format_filesystem_capabilities(
*,
filesystem_enabled: bool,
workspace_enabled: bool,
mounted_paths: Sequence[str],
) -> str:
if not filesystem_enabled:
return "Filesystem access is unavailable because no workspace root or file mounts are configured."
lines = ["Filesystem access is enabled."]
lines.append("Read files from `/input`.")
lines.append("Write generated artifacts to `/output`; returned files will be attached to the tool result.")
if workspace_enabled:
lines.append("The configured workspace root is available under `/input/`.")
if mounted_paths:
lines.append("Additional mounted paths:")
lines.extend(f"- `{mounted_path}`" for mounted_path in mounted_paths)
elif not workspace_enabled:
lines.append("No workspace root or explicit file mounts are currently configured.")
return "\n".join(lines)
def _format_network_capabilities(
*,
allowed_domains: Sequence[AllowedDomain],
) -> str:
if not allowed_domains:
return "Outbound network access is unavailable because no allow-listed targets are configured."
lines = ["Outbound network access is allowed only for these configured targets:"]
for allowed_domain in allowed_domains:
methods_text = (
", ".join(allowed_domain.methods) if allowed_domain.methods else "all methods allowed by the backend"
)
lines.append(f"- `{allowed_domain.target}`: {methods_text}.")
return "\n".join(lines)
def build_codeact_instructions(
*,
tools: Sequence[FunctionTool],
tools_visible_to_model: bool,
filesystem_enabled: bool = False,
) -> str:
"""Build dynamic CodeAct instructions for the effective sandbox state."""
usage_note = (
"Some tools may also appear directly, but prefer `execute_code` whenever you need to combine Python "
"control flow with sandbox tool calls."
if tools_visible_to_model
else "Provider-owned sandbox tools are not exposed separately; use `execute_code` when you need them."
)
output_note = (
"To surface results from `execute_code`, end the code with `print(...)`; the sandbox does not "
"return the value of the last expression."
)
if filesystem_enabled:
output_note += (
" For larger artifacts, write them to `/output/<filename>` instead — returned files will be "
"attached to the tool result."
)
return f"""You have one primary tool: execute_code.
Prefer one execute_code call per request when possible.
Its tool description contains the current `call_tool(...)` guidance, sandbox
tool registry, and capability limits.
{output_note}
{usage_note}
"""
def build_execute_code_description(
*,
tools: Sequence[FunctionTool],
filesystem_enabled: bool,
workspace_enabled: bool,
mounted_paths: Sequence[str],
allowed_domains: Sequence[AllowedDomain],
) -> str:
"""Build the dynamic execute_code tool description for standalone usage."""
filesystem_text = _format_filesystem_capabilities(
filesystem_enabled=filesystem_enabled,
workspace_enabled=workspace_enabled,
mounted_paths=mounted_paths,
)
network_text = _format_network_capabilities(
allowed_domains=allowed_domains,
)
return f"""Execute Python in an isolated Hyperlight sandbox.
Inside the sandbox, `call_tool(name, **kwargs)` is available as a built-in for
registered host callbacks. Use the tool name as the first argument and keyword
arguments only. Do not pass a dict or any other positional arguments after the
tool name.
Registered sandbox tools:
{_format_tool_summaries(tools)}
Filesystem capabilities:
{filesystem_text}
Network capabilities:
{network_text}
Prefer `execute_code` when you need to combine one or more `call_tool(...)`
calls with Python control flow, loops, or post-processing.
"""
@@ -0,0 +1,111 @@
# Copyright (c) Microsoft. All rights reserved.
from __future__ import annotations
from collections.abc import Callable, Sequence
from pathlib import Path
from typing import Any
from agent_framework import AgentSession, ContextProvider, FunctionTool, SessionContext
from agent_framework._tools import ApprovalMode
from ._execute_code_tool import HyperlightExecuteCodeTool, SandboxRuntime
from ._types import AllowedDomain, AllowedDomainInput, FileMount, FileMountInput
class HyperlightCodeActProvider(ContextProvider):
"""Inject a Hyperlight-backed CodeAct surface using provider-owned tools."""
DEFAULT_SOURCE_ID = "hyperlight_codeact"
def __init__(
self,
source_id: str = DEFAULT_SOURCE_ID,
*,
tools: FunctionTool | Callable[..., Any] | Sequence[FunctionTool | Callable[..., Any]] | None = None,
approval_mode: ApprovalMode | None = None,
workspace_root: str | Path | None = None,
file_mounts: FileMountInput | Sequence[FileMountInput] | None = None,
allowed_domains: AllowedDomainInput | Sequence[AllowedDomainInput] | None = None,
backend: str = "wasm",
module: str | None = "python_guest.path",
module_path: str | None = None,
_registry: SandboxRuntime | None = None,
) -> None:
super().__init__(source_id)
self._execute_code_tool = HyperlightExecuteCodeTool(
tools=tools,
approval_mode=approval_mode,
workspace_root=workspace_root,
file_mounts=file_mounts,
allowed_domains=allowed_domains,
backend=backend,
module=module,
module_path=module_path,
_registry=_registry,
)
def add_tools(
self,
tools: FunctionTool | Callable[..., Any] | Sequence[FunctionTool | Callable[..., Any]],
) -> None:
"""Add provider-owned sandbox tools."""
self._execute_code_tool.add_tools(tools)
def get_tools(self) -> list[FunctionTool]:
"""Return the provider-owned sandbox tools."""
return self._execute_code_tool.get_tools()
def remove_tool(self, name: str) -> None:
"""Remove one provider-owned sandbox tool by name."""
self._execute_code_tool.remove_tool(name)
def clear_tools(self) -> None:
"""Remove all provider-owned sandbox tools."""
self._execute_code_tool.clear_tools()
def add_file_mounts(self, file_mounts: FileMountInput | Sequence[FileMountInput]) -> None:
"""Add provider-managed file mounts."""
self._execute_code_tool.add_file_mounts(file_mounts)
def get_file_mounts(self) -> list[FileMount]:
"""Return the provider-managed file mounts."""
return self._execute_code_tool.get_file_mounts()
def remove_file_mount(self, mount_path: str) -> None:
"""Remove one provider-managed file mount."""
self._execute_code_tool.remove_file_mount(mount_path)
def clear_file_mounts(self) -> None:
"""Remove all provider-managed file mounts."""
self._execute_code_tool.clear_file_mounts()
def add_allowed_domains(self, domains: AllowedDomainInput | Sequence[AllowedDomainInput]) -> None:
"""Add provider-managed outbound allow-list entries."""
self._execute_code_tool.add_allowed_domains(domains)
def get_allowed_domains(self) -> list[AllowedDomain]:
"""Return the provider-managed outbound allow-list entries."""
return self._execute_code_tool.get_allowed_domains()
def remove_allowed_domain(self, domain: str) -> None:
"""Remove one provider-managed outbound allow-list entry."""
self._execute_code_tool.remove_allowed_domain(domain)
def clear_allowed_domains(self) -> None:
"""Remove all provider-managed outbound allow-list entries."""
self._execute_code_tool.clear_allowed_domains()
async def before_run(
self,
*,
agent: Any,
session: AgentSession | None,
context: SessionContext,
state: dict[str, Any],
) -> None:
"""Inject CodeAct instructions and a run-scoped execute_code tool before each run."""
run_tool = self._execute_code_tool.create_run_tool()
state[self.source_id] = run_tool.build_serializable_state()
context.extend_instructions(self.source_id, run_tool.build_instructions(tools_visible_to_model=False))
context.extend_tools(self.source_id, [run_tool])
@@ -0,0 +1,28 @@
# Copyright (c) Microsoft. All rights reserved.
from __future__ import annotations
from collections.abc import Sequence
from pathlib import Path
from typing import NamedTuple, TypeAlias
class FileMount(NamedTuple):
"""Map a host file or directory into the sandbox input tree."""
host_path: str | Path
mount_path: str
FileMountHostPath: TypeAlias = str | Path
FileMountInput: TypeAlias = str | tuple[FileMountHostPath, str] | FileMount
class AllowedDomain(NamedTuple):
"""Allow outbound requests to one target, optionally restricted to specific HTTP methods."""
target: str
methods: tuple[str, ...] | None = None
AllowedDomainInput: TypeAlias = str | tuple[str, str | Sequence[str]] | AllowedDomain
+100
View File
@@ -0,0 +1,100 @@
[project]
name = "agent-framework-hyperlight"
description = "Hyperlight CodeAct integrations for Microsoft Agent Framework."
authors = [{ name = "Microsoft", email = "af-support@microsoft.com"}]
readme = "README.md"
requires-python = ">=3.10"
version = "1.0.0b260709"
license-files = ["LICENSE"]
urls.homepage = "https://aka.ms/agent-framework"
urls.source = "https://github.com/microsoft/agent-framework/tree/main/python"
urls.release_notes = "https://github.com/microsoft/agent-framework/releases?q=tag%3Apython-1&expanded=true"
urls.issues = "https://github.com/microsoft/agent-framework/issues"
classifiers = [
"License :: OSI Approved :: MIT License",
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Typing :: Typed",
]
dependencies = [
"agent-framework-core>=1.11.0,<2",
"hyperlight-sandbox>=0.4.0,<0.5",
"hyperlight-sandbox-backend-wasm>=0.4.0,<0.5 ; ((sys_platform == 'linux' and platform_machine == 'x86_64') or (sys_platform == 'win32' and platform_machine == 'AMD64')) and python_version < '3.14'",
"hyperlight-sandbox-python-guest>=0.4.0,<0.6",
]
[tool.uv]
prerelease = "if-necessary-or-explicit"
environments = [
"sys_platform == 'linux'",
"sys_platform == 'win32'"
]
[tool.uv-dynamic-versioning]
fallback-version = "0.0.0"
[tool.pytest.ini_options]
testpaths = 'tests'
addopts = "-ra -q -r fEX"
asyncio_mode = "auto"
asyncio_default_fixture_loop_scope = "function"
filterwarnings = []
timeout = 120
markers = [
"integration: marks tests as integration tests that require external services",
]
[tool.ruff]
extend = "../../pyproject.toml"
[tool.ruff.lint.per-file-ignores]
"tests/**" = ["D", "INP", "TD", "ERA001", "RUF", "S"]
[tool.coverage.run]
omit = [
"**/__init__.py"
]
[tool.pyright]
extends = "../../pyproject.toml"
include = ["agent_framework_hyperlight"]
exclude = ['tests']
[tool.mypy]
plugins = ['pydantic.mypy']
strict = true
python_version = "3.10"
ignore_missing_imports = true
disallow_untyped_defs = true
no_implicit_optional = true
check_untyped_defs = true
warn_return_any = true
show_error_codes = true
warn_unused_ignores = false
disallow_incomplete_defs = true
disallow_untyped_decorators = true
[tool.bandit]
targets = ["agent_framework_hyperlight"]
exclude_dirs = ["tests"]
[tool.poe]
executor.type = "uv"
include = "../../shared_tasks.toml"
[tool.poe.tasks.mypy]
help = "Run MyPy for this package."
cmd = "mypy --config-file $POE_ROOT/pyproject.toml agent_framework_hyperlight"
[tool.poe.tasks.test]
help = "Run the default unit test suite for this package."
cmd = 'pytest -m "not integration" --cov=agent_framework_hyperlight --cov-report=term-missing:skip-covered tests'
[build-system]
requires = ["flit-core >= 3.11,<4.0"]
build-backend = "flit_core.buildapi"
File diff suppressed because it is too large Load Diff