Summary
Allow engine.model (and ideally the rest of the engine block) to be sourced from an Azure DevOps pipeline variable / variable group, so the model can be switched at queue time without editing *.agent.md and recompiling the *.agent.lock.yml.
Motivation
We run several copilot-engine agents (implementer, pr-reviewer, pr-comment-fixer) as compiled ADO pipelines. Today engine.model must be a compiled literal, so rolling the whole fleet from one model to another (e.g. gpt-5.5 → gpt-5.6-terra) means editing every .agent.md, recompiling, and committing every .agent.lock.yml. We already keep a shared ADO variable group for exactly this kind of knob and would like the model to live there, so ops can retarget a model (A/B a new deployment, roll back a bad one, cut cost) via a variable-group edit + re-run, not a source change + PR.
What I found in the current code (0.50.0)
engine.model is validated against a character allow-list ([A-Za-z0-9._:-]) in src/engine.rs, which rejects $(VAR) and ${{ }} macro syntax.
- The
COPILOT_MODEL env-var and engine.args back-doors are also blocked as substitution paths.
- Only
engine.provider.base-url accepts a $(VAR) macro today (and then the host has to be added to network.allowed manually).
So there is currently no supported way to make the model itself variable-driven.
Proposed behavior
Any of these would solve it, in rough order of preference:
- Permit ADO macro syntax (
$(VAR) / variable-group reference) in engine.model, resolved at pipeline runtime rather than compile time. If validation is still desired, validate the literal case only and pass macros through untouched.
- A dedicated, explicitly-variable field (e.g.
engine.model-variable: MY_MODEL_VAR) that compiles to --model $(MY_MODEL_VAR).
- Re-enable
COPILOT_MODEL (or an equivalent env override) as a documented, supported override of the compiled default.
Alternatives considered
Keeping the literal and scripting the multi-file edit + recompile on every model change — works, but couples an operational retarget to a source PR across N files, which is what we'd like to avoid.
Environment
- ado-aw 0.50.0, copilot engine, Azure AI Foundry BYOK provider (
engine.provider.type: azure), standalone target.
Summary
Allow
engine.model(and ideally the rest of theengineblock) to be sourced from an Azure DevOps pipeline variable / variable group, so the model can be switched at queue time without editing*.agent.mdand recompiling the*.agent.lock.yml.Motivation
We run several copilot-engine agents (
implementer,pr-reviewer,pr-comment-fixer) as compiled ADO pipelines. Todayengine.modelmust be a compiled literal, so rolling the whole fleet from one model to another (e.g.gpt-5.5→gpt-5.6-terra) means editing every.agent.md, recompiling, and committing every.agent.lock.yml. We already keep a shared ADO variable group for exactly this kind of knob and would like the model to live there, so ops can retarget a model (A/B a new deployment, roll back a bad one, cut cost) via a variable-group edit + re-run, not a source change + PR.What I found in the current code (0.50.0)
engine.modelis validated against a character allow-list ([A-Za-z0-9._:-]) insrc/engine.rs, which rejects$(VAR)and${{ }}macro syntax.COPILOT_MODELenv-var andengine.argsback-doors are also blocked as substitution paths.engine.provider.base-urlaccepts a$(VAR)macro today (and then the host has to be added tonetwork.allowedmanually).So there is currently no supported way to make the model itself variable-driven.
Proposed behavior
Any of these would solve it, in rough order of preference:
$(VAR)/ variable-group reference) inengine.model, resolved at pipeline runtime rather than compile time. If validation is still desired, validate the literal case only and pass macros through untouched.engine.model-variable: MY_MODEL_VAR) that compiles to--model $(MY_MODEL_VAR).COPILOT_MODEL(or an equivalent env override) as a documented, supported override of the compiled default.Alternatives considered
Keeping the literal and scripting the multi-file edit + recompile on every model change — works, but couples an operational retarget to a source PR across N files, which is what we'd like to avoid.
Environment
engine.provider.type: azure), standalone target.