Runtimes configuration
Runtimes Configuration
Section titled “Runtimes Configuration”The runtimes field configures language environments that are installed before the agent runs. Unlike tools (which are agent capabilities like edit, bash, memory), runtimes are execution environments that the compiler auto-installs via pipeline steps.
Aligned with gh-aw’s runtimes: front matter field.
Lean 4 (lean:)
Section titled “Lean 4 (lean:)”Lean 4 theorem prover runtime. Auto-installs the Lean toolchain via elan, extends the bash command allow-list, adds Lean-specific domains to the network allowlist, and appends a prompt supplement informing the agent that Lean is available.
# Simple enablement (installs latest stable toolchain)runtimes: lean: true
# With options (pin specific toolchain version)runtimes: lean: toolchain: "leanprover/lean4:v4.29.1"When enabled, the compiler:
- Injects an elan installation step into
{{ prepare_steps }}(runs before AWF network isolation) - Defaults to the
stabletoolchain; if alean-toolchainfile exists in the repo, elan overrides to that version automatically - Auto-adds
lean,lake, andelanto the bash command allow-list - Adds Lean-specific domains to the network allowlist:
elan.lean-lang.org,leanprover.github.io,lean-lang.org - Mounts
$HOME/.elaninto the AWF container via--mountflag so the elan toolchain is accessible inside the chroot (AWF replaces$HOMEwith an empty overlay for security) - Appends a prompt supplement informing the agent about Lean 4 availability and basic commands
- Emits a compile-time warning if
tools.bashis empty (Lean requires bash access)
Note: In the 1ES target, the bash command allow-list is updated but elan installation must be done manually via steps: front matter. The 1ES target handles network isolation separately.
Python (python:)
Section titled “Python (python:)”Python runtime. Auto-installs Python via UsePythonVersion@0, emits PipAuthenticate@1 for internal feed access, adds Python ecosystem domains to the AWF network allowlist, extends the bash command allow-list, and optionally injects feed URL env vars for pip and uv.
# Simple enablement (installs default Python 3.x)runtimes: python: true
# With options (pin version, configure feed)runtimes: python: version: "3.12" feed-url: "https://pkgs.dev.azure.com/myorg/_packaging/myfeed/pypi/simple/"Fields:
| Field | Type | Description |
|---|---|---|
version | string | Python version to install (e.g., "3.12", "3.11"). Passed to UsePythonVersion@0 versionSpec. Defaults to latest 3.x. |
feed-url | string | Internal PyPI feed URL. Injects PIP_INDEX_URL and UV_DEFAULT_INDEX env vars into the agent environment. |
config | string | Path to a pip/uv config file. Accepted with a warning — the file will not be available inside the AWF agent environment until proxy-auth support lands. |
When enabled, the compiler:
- Injects
UsePythonVersion@0into{{ prepare_steps }}(runs before AWF) - If
feed-urlis set, also injectsPipAuthenticate@1to authenticate the ADO build service identity for internal feeds - Auto-adds
python,python3,pip,pip3,uvto the bash command allow-list - Adds Python ecosystem domains to the network allowlist (pypi.org, pythonhosted.org, etc.)
- If
feed-urlis set, injectsPIP_INDEX_URLandUV_DEFAULT_INDEXenv vars into the agent environment - Appends a prompt supplement informing the agent about Python availability
- No AWF mounts or PATH prepends needed —
UsePythonVersion@0installs to/opt/hostedtoolcache(auto-mounted by AWF) and publishes PATH entries that AWF merges via$GITHUB_PATH
Note: PipAuthenticate@1 is currently emitted with an empty artifactFeeds input, which configures credentials for all feeds accessible to the build service identity. If your internal feed requires scoped authentication to a specific Azure Artifacts feed, this may need future refinement.
Node.js (node:)
Section titled “Node.js (node:)”Node.js runtime. Auto-installs Node.js via NodeTool@0, emits npmAuthenticate@0 for internal feed access, adds Node ecosystem domains to the AWF network allowlist, extends the bash command allow-list, and optionally injects feed URL env vars for npm.
# Simple enablement (installs default Node LTS)runtimes: node: true
# With options (pin version, configure feed)runtimes: node: version: "22.x" feed-url: "https://pkgs.dev.azure.com/ORG/PROJECT/_packaging/FEED/npm/registry/"Fields:
| Field | Type | Description |
|---|---|---|
version | string | Node.js version to install (e.g., "22.x", "20.x"). Passed to NodeTool@0 versionSpec. Defaults to "22.x". |
feed-url | string | Internal npm registry URL. Injects NPM_CONFIG_REGISTRY env var into the agent environment. |
config | string | Path to an .npmrc config file. Accepted with a warning — the file will not be available inside the AWF agent environment until proxy-auth support lands. |
When enabled, the compiler:
- Injects
NodeTool@0into{{ prepare_steps }}(runs before AWF) - If
feed-urlorconfigis set, also injectsnpmAuthenticate@0(and an ensure-.npmrcstep) to authenticate the ADO build service identity for internal feeds - Auto-adds
node,npm,npxto the bash command allow-list - Adds Node ecosystem domains to the network allowlist (npmjs.org, nodejs.org, etc.)
- If
feed-urlis set, injectsNPM_CONFIG_REGISTRYenv var into the agent environment - Appends a prompt supplement informing the agent about Node.js availability
- No AWF mounts or PATH prepends needed —
NodeTool@0installs to/opt/hostedtoolcache(auto-mounted by AWF) and publishes PATH entries that AWF merges via$GITHUB_PATH - Note: AWF overlays
~/.npmrcwith/dev/nullfor credential security — theNPM_CONFIG_REGISTRYenv var approach avoids conflicting with this overlay
.NET (dotnet:)
Section titled “.NET (dotnet:)”.NET runtime. Auto-installs the .NET SDK via UseDotNet@2, emits NuGetAuthenticate@1 for internal feed access, adds .NET ecosystem domains to the AWF network allowlist, and extends the bash command allow-list with dotnet.
# Simple enablement (installs default .NET SDK, currently 8.0.x)runtimes: dotnet: true
# With options (pin version, configure internal feed)runtimes: dotnet: version: "8.0.x" feed-url: "https://pkgs.dev.azure.com/myorg/_packaging/myfeed/nuget/v3/index.json"
# Or point at a checked-in nuget.configruntimes: dotnet: version: "8.0.x" config: "nuget.config"
# Pin SDK from the repo's global.json (UseDotNet@2 useGlobalJson mode)runtimes: dotnet: version: "global.json"Fields:
| Field | Type | Description |
|---|---|---|
version | string | .NET SDK version to install (e.g., "8.0.x", "9.0.x"). Passed to UseDotNet@2 version with packageType: 'sdk'. Defaults to "8.0.x". The special value "global.json" (case-insensitive) emits useGlobalJson: true instead, which discovers and installs every SDK referenced by global.json files in the workspace. |
feed-url | string | Internal NuGet feed URL (typically the v3 index.json of an Azure Artifacts feed). When set, the compiler creates a minimal nuget.config if none exists and runs NuGetAuthenticate@1. |
config | string | Path to a checked-in nuget.config in the repo. When set, the compiler runs NuGetAuthenticate@1 (which auto-discovers nuget.config files in the workspace). Mutually exclusive with feed-url. |
global.json precedence. A global.json file in the repo is the canonical
way to pin the .NET SDK. The compiler enforces a single source of truth:
- If a
global.jsonexists at the agent’s compile directory and the front matter sets a concreteversion, compilation errors out. Either remove the front-matter version or set it to the literal string"global.json"to opt intoUseDotNet@2’suseGlobalJson: truemode. - If
version: "global.json"is set, the compiler emitsuseGlobalJson: true(no explicitversion:input) so the install task walks the workspace forglobal.jsonfiles itself. - If no
versionis set and aglobal.jsonexists, the compiler does not auto-promote — the default"8.0.x"is used. Opt in explicitly with the sentinel.
When enabled, the compiler:
- Injects
UseDotNet@2into{{ prepare_steps }}(runs before AWF) - If
feed-urlis set, injects an ensure-nuget.configstep (writes a minimalnuget.configreferencing the feed only when one doesn’t already exist) andNuGetAuthenticate@1 - If
configis set (andfeed-urlis not), injectsNuGetAuthenticate@1only — the user-checked-innuget.configis assumed to be present in the workspace - Auto-adds
dotnetto the bash command allow-list - Adds .NET ecosystem domains to the network allowlist (nuget.org, dotnet.microsoft.com, pkgs.dev.azure.com, etc.)
- Appends a prompt supplement informing the agent about .NET availability
- No AWF mounts or PATH prepends needed —
UseDotNet@2installs to/opt/hostedtoolcache(auto-mounted by AWF) and publishes PATH entries that AWF merges via$GITHUB_PATH
Differences from the Python and Node runtimes (called out for clarity, since this runtime intentionally diverges):
- No agent env var is injected for
feed-url. Unlikepip(PIP_INDEX_URL) andnpm(NPM_CONFIG_REGISTRY), NuGet has no first-class environment-variable equivalent for selecting a package source. Feed configuration always goes through anuget.configfile. config:is functional, not a deferred warning. AWF only overlays files in$HOME(e.g.,~/.npmrc->/dev/null); workspace files such asnuget.configare preserved inside the agent sandbox, so a checked-innuget.configworks today.NuGetAuthenticate@1requires noworkingFile:input. It auto-discoversnuget.configfiles anywhere in the workspace, unlikenpmAuthenticate@0which needs an explicit path.
Combining Runtimes
Section titled “Combining Runtimes”Multiple runtimes can be enabled simultaneously:
runtimes: python: version: "3.12" node: version: "22.x" dotnet: version: "8.0.x" lean: trueAll runtime extensions are sorted into ExtensionPhase::Runtime and execute before tool extensions (ExtensionPhase::Tool), ensuring language toolchains are available before any tools that depend on them.