Skip to content

Python: fix LocalShellTool on self-hosted Foundry agents - #8858

Closed
alkaiserItron wants to merge 2 commits into
microsoft:mainfrom
alkaiserItron:LocalShell_FoundryFix
Closed

alkaiserItron wants to merge 2 commits into
microsoft:mainfrom
alkaiserItron:LocalShell_FoundryFix

Conversation

@alkaiserItron

@alkaiserItron alkaiserItron commented Sep 29, 2026 •

Copy link
Copy Markdown

Motivation & Context

Since agent-framework-openai 1.14.4 (PR #8294), a shell_call is only routed to local execution when the response item carries environment.type == "local". Self-hosted Foundry responses omit that marker, so a registered LocalShellTool is misclassified as a hosted shell call, never executes, and the next turn fails with 400 - No tool output found for shell call .... This restores local shell execution against a Foundry sandbox for self-hosted Foundry agents, while ensuring a shell call the provider already executed is never re-run locally.

Description & Review Guide

  • What are the major changes?

    • Extract the shell-call local-environment check in RawOpenAIChatClient into an overridable _shell_call_targets_local_executor hook (default behavior unchanged: only environment.type == "local" is local).
    • Override it in RawFoundryChatClient to also treat a missing environment as local, since Foundry omits the marker. Explicit hosted container environments still stay informational.
    • Add a provider-output guard in the shared base client: when a shell_call already has a matching shell_call_output (same call_id) in the same response, it stays a hosted shell_tool_call and is never routed to the local executor. This prevents unapproved local re-execution and duplicate outputs for one call_id on stateless replay. Applied on the non-streaming path (the full item list isn't available mid-stream, and a delegated call never streams its own output).
    • Add Foundry tests covering the env-less shell call (streaming and non-streaming), the container-environment-stays-hosted guard, an end-to-end run that executes the tool and replays its output, and regression tests for the mixed call/output case (classification + end-to-end no re-execution).
  • What is the impact of these changes?

    • OpenAI and Azure OpenAI behavior is unchanged; only the Foundry client relaxes the classification, and the provider-output guard is a strict safety net that never fires in existing flows. No public API changes (the hook and guard are private). Not a breaking change.
  • What do you want reviewers to focus on?

    • Whether the Foundry override is the right seam versus loosening the base client, that the container-environment case correctly remains hosted, and that the provider-output guard correctly keeps already-executed shell calls hosted.

Related Issue

Fixes #8663

Contribution Checklist

  • The code builds clean without any errors or warnings
  • All unit tests pass, and I have added new tests where possible
  • The PR follows the Contribution Guidelines
  • This PR is linked to an issue and there is no other open PR for this issue (see Related Issue above).
  • This is not a breaking change.

Foundry omits the shell_call local-environment marker, so a registered local
shell executor was misclassified as hosted and never ran (400 'No tool output
found for shell call'). Override shell-call classification in Foundry to treat
a missing environment as local.

Fixes #8663
Copilot AI balanced review requested due to automatic review settings September 29, 2026 18:22
@agent-framework-automation agent-framework-automation Bot added the python Usage: [Issues, PRs], Target: Python label Sep 29, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

Unmarked hosted calls may cross the local execution boundary, requiring a fix and validation against real Foundry responses.

Review effort: Balanced
Findings: 1 High severity

Open (1)
What changed in this PR

This PR aims to restore local shell execution for self-hosted Foundry agents whose responses omit the local environment marker.

Changes:

  • Extracts OpenAI’s shell-call classification into an overridable hook and lets Foundry treat unmarked calls as local.
  • Adds Foundry tests for unmarked calls, explicitly hosted calls, streaming, and output replay.
File Description
python/​packages/​openai/​agent_framework_openai/​_chat_client.py Adds the classification hook without changing the OpenAI default.
python/​packages/​foundry/​tests/​foundry/​test_foundry_chat_client.py Tests Foundry shell-call routing and replay.
python/​packages/​foundry/​agent_framework_foundry/​_chat_client.py Routes unmarked shell calls to a registered local executor.

💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

Comment thread python/packages/foundry/agent_framework_foundry/_chat_client.py
…utput so they stay hosted instead of being re-run by a registered local executor. Preserves the #8663 fix (env-less calls with no output still execute locally) while preventing duplicate outputs / unapproved local execution. Adds Foundry mixed call/output regression tests.
@eavanvalkenburg

Copy link
Copy Markdown
Member

alkaiserItron Thanks for the contribution. This materially overlaps with the older open #8720 for the same issue, so I’m closing this PR and continuing the work there.

This branch was previously deployed

1 inactive deployment
github-app-auth — 472bfb24 Deployed Sep 29, 2026 by alkaiserItron via add_label #24048
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

python Usage: [Issues, PRs], Target: Python

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Python: [Bug]: LocalShellTool never executes on a self-hosted Foundry agent since openai 1.14.4 - "No tool output found for shell call"

3 participants