21 · Shell with Environment

How a real shell tool lets the model run commands, and an environment provider tells it which shell it is driving.

Part 25 of 91 Microsoft Agent Framework Go — Every Lesson

What this lesson demonstrates

The model gets one tool — run_shell — and actually executes commands on your machine. On top of that, an EnvironmentProvider probes the shell once (family, OS, working directory, installed CLIs) and injects a summary as instructions, so the model uses export NAME=value on POSIX but $env:NAME = 'value' on PowerShell.

The lesson also contrasts two shell modes: stateless spawns a fresh shell per call (a cd in one call does not affect the next), while persistent reuses one long-lived shell so cd and exported variables carry across calls. Both are built by the same constructor — only the mode argument changes.

This program runs real commands on your machine. It sets AcknowledgeUnsafe: true to disable the approval prompt so the demo runs unattended. In a real app, keep approval on (the default) or run the shell inside a container.

The core: shell tool plus environment provider

shell, err := shelltool.NewLocal(shelltool.LocalConfig{
    Mode:              mode,
    AcknowledgeUnsafe: true, // demo runs unattended; keep approval ON in real apps
})
// ...
envProvider := shelltool.NewEnvironmentProvider(shell, shelltool.EnvironmentProviderConfig{})
// ... then in agent.Config:
Tools:            []tool.Tool{shell},
ContextProviders: []agent.ContextProvider{envProvider},

The provider holds a reference to the same shell it probes, so after the run envProvider.CurrentSnapshot() replays exactly what it observed — which printSnapshot renders.

What to notice

How it maps to the SDK

shelltool gives a Foundry-backed agent genuine local execution, and its EnvironmentProvider plugs into the standard ContextProviders slot to make the model shell-aware. The pure snapshot formatters (valueOrUnknown, DefaultShellEnvironmentInstructions) are testable offline for both POSIX and PowerShell, so you validate the instruction text without probing a shell.

Run it

go run ./tutorial/02-agents/agents/step21_shell_with_environment

The offline test runs anywhere; the live path needs az login + FOUNDRY_PROJECT_ENDPOINT, runs real commands, and is gated behind AF_LIVE=1.


Next: step22 · Foundry Memory

Sources & References

The Go SDK this lesson exercises
Giving an agent a shell tool with an environment-aware context provider