Files
Evan Mattson e56e6dad4d Python: Remove bespoke Foundry toolbox helpers; standardize on MCP for toolbox consumption (#5671)
* Remove Foundry toolbox helpers; standardize on MCP for toolbox consumption

- Remove RawFoundryChatClient.get_toolbox() and its fetch_toolbox import
- Remove fetch_toolbox, select_toolbox_tools, get_toolbox_tool_name,
  get_toolbox_tool_type, FoundryHostedToolType, ToolboxToolSelectionInput
  from agent_framework_foundry._tools
- Remove ExperimentalFeature.TOOLBOXES from _feature_stage.py (no consumers)
- Drop toolbox re-exports from agent_framework_foundry/__init__.py and
  agent_framework.foundry namespace
- Update _sanitize_foundry_response_tool docstring to remove toolbox framing;
  sanitization logic itself is unchanged
- Update _agent.py docstring: 'toolbox-fetched MCP' → 'hosted MCP'
- Delete tests/test_toolbox.py (all tests covered removed helpers)
- Update test_foundry_chat_client.py: rename/redoc tests that mentioned
  toolbox but test sanitization that remains
- Delete foundry_chat_client_with_toolbox.py (bespoke toolbox API sample)
- Delete foundry_toolbox_context_provider.py (relied on select_toolbox_tools)
- Rename foundry_chat_client_with_toolbox_mcp.py →
  foundry_chat_client_with_toolbox.py (canonical MCP pattern)
- Rewrite 04_foundry_toolbox/main.py to use MCPStreamableHTTPTool
- Update provider/README, context_providers/README, 04_foundry_toolbox/README

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(samples): update 06_files sample to consume toolbox via MCP (#5670)

Replace removed get_toolbox/select_toolbox_tools APIs with
MCPStreamableHTTPTool, using allowed_tools=["code_interpreter"] to
select only the code interpreter from the toolbox endpoint.

Update .env.example and README to use FOUNDRY_TOOLBOX_ENDPOINT
instead of TOOLBOX_NAME.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(foundry): remove non-existent toolbox helper APIs from README (#5670)

Remove the 'fetch, optionally filter, and pass tools directly' pattern
from the FoundryChatClient toolbox documentation, as select_toolbox_tools
and get_toolbox were removed. Only the MCP endpoint pattern is documented.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(foundry): remove residual toolbox docstring references and reproduction report

Remove REPRODUCTION_REPORT.md (workflow artifact that should not be committed),
and update two remaining docstring references that still said 'toolbox reads'
/'toolbox definition' after the toolbox helpers were removed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Python: Remove bespoke Foundry toolbox helpers; standardize on MCP for toolbox consumption

Fixes #5670

* fix(#5670): resolve toolbox endpoint from TOOLBOX_NAME fallback; add namespace regression tests

- Add _resolve_toolbox_endpoint() helper in 04_foundry_toolbox/main.py and
  06_files/main.py that prefers FOUNDRY_TOOLBOX_ENDPOINT but falls back to
  deriving the MCP URL from FOUNDRY_PROJECT_ENDPOINT + TOOLBOX_NAME — fixing
  the startup KeyError when agents are deployed via azd provision (which injects
  TOOLBOX_NAME, not FOUNDRY_TOOLBOX_ENDPOINT).
- Update 04_foundry_toolbox/.env.example to use FOUNDRY_TOOLBOX_ENDPOINT
  (consistent with 06_files).
- Add TOOLBOX_NAME env var to 06_files/agent.yaml so deployed agents have it
  available for the fallback derivation.
- Update both READMEs to document the two ways to supply the toolbox endpoint.
- Add test_foundry_namespace_no_longer_exposes_toolbox_helpers() with negative
  assertions for FoundryHostedToolType, get_toolbox_tool_name,
  get_toolbox_tool_type, and select_toolbox_tools — guarding against accidental
  re-introduction of removed symbols.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(samples): fail fast on empty FOUNDRY_TOOLBOX_ENDPOINT; add unit tests

Addresses review feedback for #5670:

- In _resolve_toolbox_endpoint() (04_foundry_toolbox/main.py and
  06_files/main.py) change the walrus-operator check from a truthy
  test to an explicit 'is not None' guard.  An explicitly set empty
  string now raises ValueError immediately with a clear message
  instead of silently falling through to the fallback URL
  construction.

- Add tests/samples/hosting/test_toolbox_endpoint.py covering both
  sample modules:
    (a) FOUNDRY_TOOLBOX_ENDPOINT set → returned as-is
    (b) FOUNDRY_TOOLBOX_ENDPOINT set to empty string → ValueError
    (c) fallback constructs URL from FOUNDRY_PROJECT_ENDPOINT + TOOLBOX_NAME,
        stripping trailing slashes
    (d) neither variable group set → KeyError

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Address review feedback: remove extraneous test and docstring content

- Remove test_foundry_namespace_no_longer_exposes_toolbox_helpers (no longer warranted)
- Remove docstring from _agent.py _prepare_tools_for_openai (extraneous)
- Trim _chat_client.py _prepare_tools_for_openai docstring to one-liner (toolbox references no longer relevant)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: remove remaining extraneous docstring from RawFoundryChatClient._prepare_tools_for_openai

Address review comment on PR #5671: reviewer noted the description
isn't warranted now that toolbox helpers have been removed. Matches
the pattern in RawFoundryAgentChatClient which has no docstring.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
e56e6dad4d · 2026-05-06 23:56:16 +00:00
History
..

What this sample demonstrates

An Agent Framework agent that runs Python in a Hyperlight WebAssembly sandbox via the CodeAct pattern, hosted using the Responses protocol. The model is only given a single execute_code tool. Local Python tools (compute, fetch_data) are registered on HyperlightCodeActProvider and are reachable from inside the sandbox via call_tool(...), never as direct LLM tools. All of this can be run as a container, however not under all circumstances.

⚠️ Foundry hosted-agent runtime support is in progress. Hyperlight requires a hypervisor (/dev/kvm on Linux, MSHV on Windows). The default Foundry hosted-agent runtime does not currently expose a hypervisor to the workload container, so deploying this sample as a Foundry hosted agent will fail at runtime with Failed to create sandbox: ... No Hypervisor was found for Sandbox. The sample container itself works end-to-end when run locally with docker run --device=/dev/kvm ... (see Hypervisor requirement below). We are working with the platform team to enable a hypervisor-capable hosting target.

How It Works

Model integration

The agent uses FoundryChatClient to talk to a Foundry-hosted model deployment. A HyperlightCodeActProvider is attached as a context provider, which on every run injects the execute_code tool plus the CodeAct instructions that teach the model how to author Python that calls call_tool(...) for sandbox-only tools.

See main.py for the full implementation.

Agent hosting

The agent is hosted with ResponsesHostServer from agent-framework-foundry-hosting, which exposes a REST endpoint compatible with the OpenAI Responses protocol.

The Hyperlight Wasm backend is currently published only for linux/x86_64 and win32/AMD64 with Python <3.14. The hosted container runs python:3.12-slim on linux/x86_64, which is supported.

Hypervisor requirement

Hyperlight executes guest WebAssembly inside a micro-VM and requires a hypervisor on the host:

  • Linux: /dev/kvm must be present and the container must have access to it (docker run --device=/dev/kvm ...).
  • Windows: the Microsoft Hypervisor Platform (MSHV) must be enabled.

Without a hypervisor, sandbox creation fails with:

Failed to create sandbox: failed to build ProtoWasmSandbox: No Hypervisor was found for Sandbox

This affects hosted environments that don't expose /dev/kvm to the workload container (most managed PaaS, including the default Foundry hosted-agent runtime). To run this sample as a hosted agent you need a hosting target with nested virtualization and /dev/kvm device passthrough — for example an Azure VM, AKS nodes with KVM enabled, or Azure Container Instances configured for nested virt.

Running the Agent Host

Follow the instructions in the Running the Agent Host Locally section of the README in the Foundry Hosted Agent directory.

Interacting with the agent

Send a POST request to the server with a JSON body containing an "input" field. The model should respond by calling execute_code with Python that uses call_tool(...) to reach the sandbox-only tools:

curl -X POST http://localhost:8088/responses \
  -H "Content-Type: application/json" \
  -d '{"input": "Fetch all users, find the admins, multiply 7 by 6, and print the users, admins and multiplication result. Use execute_code with call_tool(...)."}'

Deploying the Agent to Foundry

Deploying this container to Foundry will not work yet, as soon as it does, we will update this sample.