Skip to content

.NET: Python: [Bug]: persistent PowerShell shell session reports a stale exit code for cmdlet-only commands #8205

Description

Description

On Windows, LocalShellTool(mode="persistent") reports the exit code of an earlier command for any later command that only runs cmdlets.

ShellSession._build_script derives the return code from $LASTEXITCODE:

"   Invoke-Expression $__af_cmd;"
"   if ($LASTEXITCODE -ne $null) { $__af_rc = $LASTEXITCODE }"
"   elseif (-not $?) { $__af_rc = 1 }"

$LASTEXITCODE is a session-wide automatic variable that PowerShell only updates when a native (external) executable exits. Cmdlets leave it untouched. Since the session is long-lived, once any command in it has run an external process, $LASTEXITCODE stays set, and every subsequent cmdlet-only command takes the if branch and reports that stale value instead of 0.

The blast radius is that the tool tells the agent a command failed when it succeeded, for the whole rest of the session, until another external command happens to reset the variable.

Stateless mode is unaffected — each command is a fresh process and the rc comes from the process exit code.

Code Sample

import asyncio
from agent_framework_tools.shell._resolve import resolve_shell
from agent_framework_tools.shell._session import ShellSession

async def main():
    async with ShellSession(resolve_shell(None, interactive=True)) as s:
        for cmd in [
            "Write-Output 'cmdlet only'",
            "cmd /c exit 3",
            "Write-Output 'cmdlet only, after a failing native command'",
            "Write-Output 'cmdlet only again'",
        ]:
            r = await s.run(cmd, timeout=20)
            print(f"exit_code={r.exit_code:<4} cmd={cmd}")

asyncio.run(main())

Output I get on Windows 11 with Windows PowerShell 5.1:

exit_code=0    cmd=Write-Output 'cmdlet only'
exit_code=3    cmd=cmd /c exit 3
exit_code=3    cmd=Write-Output 'cmdlet only, after a failing native command'
exit_code=3    cmd=Write-Output 'cmdlet only again'

The last two commands succeeded and printed their output, but are reported as exit code 3.

Expected: 0, 3, 0, 0.

Error Messages / Stack Traces

No exception — the wrong value is returned silently in ShellResult.exit_code.

Package Versions

agent-framework-tools: 1.0.0b260730 (from a source checkout of main at 992d445)

Python Version

Python 3.12.9

Additional Context

This is Windows-only, and the CI matrix (.github/workflows/python-*.yml) is ubuntu-latest everywhere, so the existing PowerShell tests in python/packages/tools/tests/test_local_shell_tool.py — the ones guarded by @pytest.mark.skipif(sys.platform != "win32", ...) — never actually execute anywhere.

The .NET port has the same lines in dotnet/src/Microsoft.Agents.AI.Tools.Shell/ShellSession.cs (around line 592), so it very likely has the same behaviour. I have not built or run the .NET side, so I am reporting that as an observation rather than a verified claim.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

.NETUsage: [Issues, PRs], Target: .NetpythonUsage: [Issues, PRs], Target: PythonreproducedUsage: [Issues], Target: all issues that can be reproduced by the triage workflowskillsUsage: [Issues, PRs], Target: skills related features

Type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions