Extending ado-aw
Extending ado-aw
Section titled “Extending ado-aw”This guide shows the usual workflow for adding a new capability to the compiler.
Use it when you want to add a feature such as:
- a new CLI command
- a new compile target
- a new front-matter field
- a new template marker
- a new safe-output tool
- a new first-class tool
- a new runtime
Add a new CLI command
Section titled “Add a new CLI command”Start in src/main.rs.
- Add a new variant to the
Commandsenum. - Define the arguments with
clapderive attributes. - Handle the new command in the main dispatch logic.
- Add tests for parsing and behavior.
Use this when you want a new top-level command such as ado-aw my-command.
Add a new compile target
Section titled “Add a new compile target”Compile targets live under src/compile/.
A typical workflow is:
- create a new target module such as
src/compile/my_target.rs - implement the compiler behavior for that target
- register the target so the front matter can select it
- add tests that compile representative inputs and verify generated output
Use this when the project needs a different kind of generated Azure DevOps template.
Add a new front-matter field
Section titled “Add a new front-matter field”Front-matter types live in src/compile/types.rs.
To add a field:
- add the new field to the relevant Rust type
- update parsing and validation
- thread the value into compilation where needed
- add tests for valid and invalid input
If the change is breaking, also add a codemod under src/compile/codemods/.
Use a codemod for changes such as:
- renaming a field
- removing a field
- changing a field’s shape
- adding a new required field
Add a new template marker
Section titled “Add a new template marker”Template markers are placeholders in the pipeline templates under src/data/.
To add one:
- add the marker to the relevant template file
- update the target compiler that replaces markers
- ensure the replacement is correct for every target that needs it
- add tests that assert the generated YAML contains the expected expansion
This is the right approach when a feature needs new generated YAML in the final pipeline.
Add a new safe-output tool
Section titled “Add a new safe-output tool”Safe-output tools live in src/safeoutputs/.
Typical workflow:
- add a new file in
src/safeoutputs/ - define the tool’s input and validation rules
- implement Stage 3 execution behavior
- register the tool in the safe-output module wiring
- expose it through the MCP server and execution path
- add compile-time and execution tests
Use a safe output when the agent should propose an action that is validated and executed later, instead of performing the action directly.
Add a new first-class tool
Section titled “Add a new first-class tool”First-class tools live under src/tools/<name>/.
A common pattern is:
- create
src/tools/<name>/mod.rs - create
src/tools/<name>/extension.rs - add
execute.rsif the tool also needs Stage 3 runtime behavior - extend the front-matter config types in
src/compile/types.rs - register the tool in extension collection
- add tests
Use a first-class tool when the feature is user-configured under tools: and needs compiler-managed setup.
Add a new runtime
Section titled “Add a new runtime”Runtimes live under src/runtimes/<name>/.
To add one:
- create
src/runtimes/<name>/mod.rsfor config types and helpers - create
src/runtimes/<name>/extension.rsfor compiler integration - extend
RuntimesConfiginsrc/compile/types.rs - register the runtime in extension collection
- add tests for pipeline generation, validation, and runtime-specific behavior
Use a runtime when the feature installs or configures a language or execution environment before the agent runs.
Use the CompilerExtension trait
Section titled “Use the CompilerExtension trait”The key abstraction for tools and runtimes is CompilerExtension in src/compile/extensions/mod.rs.
Implement this trait when your feature needs to contribute things like:
- required network hosts
- required bash commands
- prompt supplements
- prepare or setup steps
- MCP gateway server entries
- allowed Copilot tools
- compile-time validation
- pipeline environment mappings
- AWF mounts or PATH updates
In practice, the workflow is:
- implement
CompilerExtensionfor your runtime or tool - return the pieces your feature needs
- let the compiler collect and merge those requirements
This keeps new features composable instead of scattering special-case logic across the compiler.
Recommended extension workflow
Section titled “Recommended extension workflow”When adding a new feature:
- decide whether it belongs under
safe-outputs,tools,runtimes, or target compilation - add or update front-matter types in
src/compile/types.rs - implement the behavior in the colocated module
- register the feature in the compiler’s collection and dispatch points
- add tests for parsing, validation, and generated YAML
- run
cargo testandcargo clippy
Example decision guide
Section titled “Example decision guide”Choose the extension point that matches the job:
- CLI command: new end-user command
- compile target: new output shape for generated pipelines
- front-matter field: new author-facing configuration
- template marker: new generated YAML insertion point
- safe output: validated deferred write action
- first-class tool: agent capability configured under
tools: - runtime: installed language or execution environment
If you place the feature in the right extension point from the start, the rest of the implementation tends to stay much simpler.