Skip to content

Engine configuration

The engine field specifies which engine to use for the agentic task. The string form is an engine identifier (currently only copilot is supported). The object form uses id for the engine identifier plus additional options like model selection and timeout.

# Simple string format (engine identifier, defaults to copilot)
engine: copilot
# Object format with additional options
engine:
id: copilot
model: claude-opus-4.7
timeout-minutes: 30
Field Type Default Description
id string copilot Engine identifier. Currently only copilot (GitHub Copilot CLI) is supported.
model string claude-opus-4.7 AI model to pass to the Copilot CLI --model flag. Any model ID supported by GitHub Copilot is accepted (e.g., claude-sonnet-4.5, claude-opus-4.7). The compiler does not validate the value — an unrecognised ID produces a runtime error from the CLI.
timeout-minutes integer (none) Maximum time in minutes the agent job is allowed to run. Sets timeoutInMinutes on the Agent job in the generated pipeline.
version string (none) Engine CLI version to install (e.g., "1.0.43", "latest"). Overrides the pinned COPILOT_CLI_VERSION. Set to "latest" to use the newest available version.
agent string (none) Custom agent file identifier (Copilot only). Adds --agent <name> to the CLI invocation, selecting a custom agent from .github/agents/.
api-target string (none) Custom API endpoint hostname for GHES/GHEC (e.g., "api.acme.ghe.com"). Adds --api-target <hostname> to the CLI invocation and adds the hostname to the AWF network allowlist.
args list [] Custom CLI arguments appended after compiler-generated args. Subject to shell-safety validation and blocked from overriding compiler-controlled flags (see args reference below).
env map (none) Engine-specific environment variables merged into the sandbox step’s env: block. Keys must be valid env var names; values must not contain ADO expressions ($(, ${{) or pipeline command injection (##vso[). Compiler-controlled keys are blocked (see env reference below).
command string (none) Custom engine executable path (skips the default engine binary installation). The path must be accessible inside the AWF container (e.g., /tmp/... or workspace-mounted paths).
github-app-token map (none) GitHub App-backed Copilot authentication. When set, the compiler mints a short-lived installation token at runtime and sources GITHUB_TOKEN from it instead of the operator-provided secret variable. See github-app-token below. Copilot engine only — rejected at compile time for any other engine.id.

The timeout-minutes field sets a wall-clock limit (in minutes) for the entire agent job. It maps to the Azure DevOps timeoutInMinutes job property on Agent. This is useful for:

  • Budget enforcement – hard-capping the total runtime of an agent to control compute costs.
  • Pipeline hygiene – preventing agents from occupying a runner indefinitely if they stall or enter long retry loops.
  • SLA compliance – ensuring scheduled agents complete within a known window.

When omitted, Azure DevOps uses its default job timeout (60 minutes). When set, the compiler emits timeoutInMinutes: <value> on the agentic job.

The args list appends raw CLI arguments to the Copilot invocation. This is an escape hatch for passing flags that ado-aw does not yet model in front matter — use it sparingly.

The compiler rejects any argument that starts with one of the following blocked prefixes, because those flags are owned and managed by the compiler:

Blocked prefix Reason
--prompt Compiler controls how the prompt is supplied
--additional-mcp-config Compiler owns MCP configuration
--allow-tool Compiler controls tool allow-listing
--allow-all-tools Compiler controls tool allow-listing
--allow-all-paths Compiler controls path permissions
--disable-builtin-mcps Compiler manages built-in MCP setup
--no-ask-user Compiler controls interactive-mode setting
--ask-user Compiler controls interactive-mode setting

Each argument is also checked against a shell-safety character allowlist to prevent injection.

Example — enabling a hypothetical experimental flag:

engine:
id: copilot
args:
- --experimental-feature
- --log-level=debug

The env map injects additional environment variables into the sandbox step’s env: block. This is useful for passing static configuration values or feature flags that the agent script needs.

The compiler also blocks keys that it controls:

Blocked key Reason
GITHUB_TOKEN Compiler-managed auth token
GITHUB_READ_ONLY Compiler-managed auth mode
COPILOT_OTEL_ENABLED Compiler-managed telemetry
COPILOT_OTEL_EXPORTER_TYPE Compiler-managed telemetry
COPILOT_OTEL_FILE_EXPORTER_PATH Compiler-managed telemetry
PATH System shell variable
HOME System shell variable
BASH_ENV System shell variable
ENV System shell variable
IFS System shell variable
LD_PRELOAD Dynamic linker — security-sensitive
LD_LIBRARY_PATH Dynamic linker — security-sensitive

Example — passing static configuration values:

engine:
id: copilot
env:
STATIC_CONFIG: "production"
FEATURE_FLAGS: "enable-new-parser,strict-mode"

By default the Copilot engine authenticates using the GITHUB_TOKEN pipeline variable you store with ado-aw secrets set GITHUB_TOKEN <pat>. For organization-managed Copilot access you can instead have the compiler mint a GitHub App installation token at pipeline runtime — mirroring gh-aw’s create-github-app-token model, adapted to Azure DevOps.

engine:
id: copilot
github-app-token:
app-id: 1234567 # literal App ID or client ID (required)
owner: octo-org # installation owner (org or user login; required)
repositories: [octo-repo] # optional — scopes the token to these repos only
# api-url: https://ghe.example.com/api/v3 # optional — GHES base URL
# skip-token-revocation: false # optional — revoke token after use (default)
# private-key: MY_SECRET_VAR # optional — override the default variable name

Store the App’s private key once before running the pipeline:

Terminal window
ado-aw secrets set GITHUB_APP_PRIVATE_KEY "$(cat app-private-key.pem)"

Fields:

Field Required Description
app-id Yes The GitHub App ID — a literal value: either a numeric App ID (e.g. 1234567, quoted or unquoted) or an alphanumeric client ID (e.g. Iv23liABC…). The App ID is not secret so it is written verbatim.
owner Yes GitHub installation owner — organization or user login.
repositories No Owner-relative repository names to scope the token to. Omit to span every repository the installation grants.
api-url No GitHub API base URL. Defaults to https://api.github.com. For GitHub Enterprise Server, set the /api/v3 base URL (e.g. https://ghe.example.com/api/v3). Must be an https:// URL.
skip-token-revocation No When true, do not revoke the minted token after the Copilot run. Defaults to false (token revoked after use).
private-key No Name of the ADO secret pipeline variable holding the private key (PEM). Defaults to GITHUB_APP_PRIVATE_KEY. Set this only to point at a differently-named variable.

What the compiler generates:

  • A token-mint step runs immediately before the Copilot invocation in both the Agent and Detection jobs. It builds a short-lived RS256 JWT, resolves the GitHub App installation for owner, exchanges it for a scoped installation token, and exposes it as a masked same-job variable (GITHUB_APP_TOKEN).
  • The Copilot engine’s GITHUB_TOKEN is sourced from $(GITHUB_APP_TOKEN) instead of the operator-provided static variable.
  • A token-revocation step runs after the Copilot invocation (unless skip-token-revocation: true), calling DELETE /installation/token. It is best-effort (always() + continueOnError) and never fails the build.
  • The minted token is never provided to SafeOutputs, user-authored steps:, Teardown, ManualReview, or Conclusion.

The mint and revocation steps run outside the AWF network sandbox — they reach the GitHub API over the build agent pool’s normal network, so no network.allowed entry is needed.

Copilot model provider (BYOK) configuration

Section titled “Copilot model provider (BYOK) configuration”

The Copilot engine can route requests to an external LLM provider — for example a private Azure Copilot Foundry instance — instead of GitHub’s default routing. This Bring Your Own Key (BYOK) mode is configured with the dedicated engine.provider block, which the compiler maps to the COPILOT_PROVIDER_* environment variables the Copilot CLI reads to reach the provider.

Prefer engine.provider over hand-writing COPILOT_PROVIDER_* keys in engine.env: it is typed and validated, and its token sub-block lets the compiler acquire the provider bearer token for you, minted in the same job as each engine run so it resolves correctly at runtime.

Field Required Maps to Description
base-url yes COPILOT_PROVIDER_BASE_URL Base URL of the external provider (e.g. https://RESOURCE.cognitiveservices.azure.com/openai/v1). A literal host is auto-added to the AWF network allowlist.
type optional COPILOT_PROVIDER_TYPE Provider format: openai (default), azure, or anthropic.
wire-api optional COPILOT_PROVIDER_WIRE_API Wire API variant: completions (default) or responses.
token optional COPILOT_PROVIDER_API_KEY Compiler-minted credential via Azure CLI (see below). Mutually exclusive with api-key.
api-key optional COPILOT_PROVIDER_API_KEY Static API key, typically a $(VAR) secret pipeline variable. Mutually exclusive with token.

The model itself is set via engine.model (or a COPILOT_MODEL env var).

Compiler-owned token acquisition (provider.token)

Section titled “Compiler-owned token acquisition (provider.token)”

Set provider.token to have the compiler mint the provider bearer token in-job via Azure CLI + an ARM service connection:

token field Required Description
service-connection yes ARM service connection used to authenticate az before minting the token.
resource optional Azure resource (audience) for az account get-access-token --resource. Defaults to https://cognitiveservices.azure.com.

The compiler emits an AzureCLI@2 step immediately before the Copilot invocation in both the Agent and Detection jobs. That step runs az account get-access-token and publishes the result as a same-job secret pipeline variable (AW_PROVIDER_BEARER_TOKEN), which is wired into COPILOT_PROVIDER_API_KEY — the credential env var the AWF api-proxy sidecar reads and forwards as Authorization: Bearer <value>. Because the token is minted in the same job as the engine run, it resolves via a plain $(...) macro — no cross-job output plumbing, no dependsOn.

The minted token is a short-lived AAD access token (typically valid ~1 hour). The mint step is emitted as the last step before the engine invocation to keep it fresh; a pool that queues or idles for the full token lifetime between the mint step and the run could observe an expired token.

When a provider credential is configured (base-url + token/api-key), the compiler automatically enables the AWF api-proxy sidecar (--enable-api-proxy) and pre-pulls its container image. The real credential is held inside the proxy container; the agent container receives only a placeholder and a proxy URL, and the credential keys are passed as --exclude-env flags so the raw value is never copied into the agent via --env-all. This applies to both the Agent and Detection (threat-analysis) jobs.

When base-url is a literal URL, the compiler automatically adds its hostname to the AWF network allowlist. If a literal value cannot be resolved to a DNS-safe host, the compiler emits a non-fatal warning telling you to add the provider hostname manually via network.allowed.

Example — Azure Copilot Foundry with a compiler-minted bearer token

Section titled “Example — Azure Copilot Foundry with a compiler-minted bearer token”
engine:
id: copilot
model: gpt-4o
provider:
base-url: https://my-foundry.cognitiveservices.azure.com/openai/v1
type: azure
token:
service-connection: my-arm-connection
# resource: https://cognitiveservices.azure.com # optional; this is the default

The compiler mints the token in-job (Agent + Detection) and adds my-foundry.cognitiveservices.azure.com to the AWF allowlist automatically. No setup: step or COPILOT_PROVIDER_* env keys are needed.

To use a static key instead, drop token and set api-key to a secret variable:

engine:
id: copilot
provider:
base-url: https://api.openai.com/v1
type: openai
api-key: $(OPENAI_API_KEY)

Raw engine.env COPILOT_PROVIDER_* (legacy, discouraged)

Section titled “Raw engine.env COPILOT_PROVIDER_* (legacy, discouraged)”

For back-compat you may still set COPILOT_PROVIDER_* keys directly in engine.env. engine.provider and raw COPILOT_PROVIDER_* keys are mutually exclusive — setting both is a compile error. A cross-job macro such as $(Setup.FOUNDRY_TOKEN) (a value set with isOutput=true in a separate setup: job) does not resolve inside a step env: block and yields an empty token at runtime — use provider.token (or a same-job / pipeline / variable-group $(VAR) secret) instead.