2 Commits

  • 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>
  • Python: Fix hyperlight WasmSandbox cross-thread Drop and harden hosted-agent sample (#5603)
    * update hyperlight to beta and move samples, add hosted agent sample
    
    * Python: Fix hyperlight WasmSandbox cross-thread Drop and harden sample
    
    Root cause: when a worker-side closure raised, the exception's __traceback__
    retained frame locals that included the partially constructed PyO3 sandbox.
    Future.result() re-raised that exception on the caller thread, and when the
    caller's exception was eventually GC'd the frame locals were released
    off-thread, dec_ref'ing the unsendable sandbox from the wrong thread and
    tripping the PyO3 panic
    '_native_wasm::WasmSandbox is unsendable, but is being dropped on another thread'.
    
    Fix:
    * Add _SandboxWorker._run_on_worker which catches every exception on the
      worker, drops __traceback__ there, deletes the original exception, and
      re-raises a fresh instance on the caller thread. initialize and execute
      route through it; dispose keeps its bare-submit semantics.
    * Add an opt-in diagnostic module _drop_diagnostic (no-op unless
      HYPERLIGHT_TRACE_DROPS=1) that installs a sys.unraisablehook and dumps
      owner-thread + per-thread stacks on any future cross-thread unsendable
      Drop. Useful for triaging similar PyO3 regressions.
    * Tests: cross-thread invocation, traceback-leak isolation, _SandboxEntry
      attribute-shape check, and a stale-reference stress test driven through
      asyncio.to_thread.
    
    Sample (samples/04-hosting/foundry-hosted-agents/responses/06_hyperlight_codeact):
    * Dockerfile installs agent-framework-* from in-tree source with python/ as
      build context so unreleased fixes can be validated end-to-end.
    * call_server.py pins the Responses API version.
    * main.py enables include_detailed_errors=True so future tool failures
      surface the actual exception text instead of a bare 'Error: Function
      failed.' string.
    * README.md documents the in-tree-package build and the Hyperlight
      hypervisor requirement (/dev/kvm on Linux, MSHV on Windows). Hosted
      environments without hypervisor passthrough surface 'No Hypervisor was
      found for Sandbox'; this is a hosting constraint, not a hyperlight bug.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Python: remove _drop_diagnostic from hyperlight package
    
    The diagnostic module was useful while bisecting the cross-thread Drop bug,
    but it is no longer needed now that _SandboxWorker._run_on_worker prevents
    the panic at the source.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Python: address PR review feedback on hyperlight
    
    - Use lazy agent_framework.hyperlight import in sample main.py.
    - Env-driven endpoint (FOUNDRY_AGENT_ENDPOINT) in call_server.py; remove personal URLs.
    - Align agent.yaml model deployment with manifest (gpt-4.1-mini).
    - Tighten Dockerfile requirements guard; drop dangling deploy.ps1 reference.
    - Preserve exception args when sanitizing tracebacks in _run_on_worker.
    - Add public _SandboxWorker.is_alive(); update test to avoid private attr.
    - Add namespace coverage tests for agent_framework.hyperlight lazy loader.
    - Add prominent note: Foundry hosted-agent runtime does not yet support
      Hyperlight (no hypervisor exposed); container works locally with /dev/kvm.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Python: bump hyperlight-sandbox dependencies to 0.4.x
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Python: renumber hyperlight codeact sample to 08
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Coerce worker exception args to strings for cross-thread safety
    
    Stringify exc.args on the worker thread before propagating, so any
    PyO3 unsendable object captured in args (e.g. via a caller-supplied
    callback or underlying SDK) cannot be Dropped on the calling thread.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * moved sample
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>