🤖 This issue has been filed by Claude Code.
Problem
The sandbox frontmatter field is currently only accepted in main workflow files (those with an on: trigger). Attempting to use it in a shared workflow partial causes the compiler to reject or silently ignore it:
field 'sandbox' cannot be used in shared workflows (only allowed in main workflows with 'on' trigger)
This means a shared partial that installs a binary into the runner environment cannot co-locate the mount declaration needed to make that binary accessible inside the agent sandbox. The mount must instead be duplicated in every main workflow that imports the shared partial — exactly the kind of repetition that shared partials exist to eliminate.
Motivating example
Suppose a shared partial sets up a CLI tool:
# shared/setup-my-cli.md
---
steps:
- name: Set up my-cli
uses: my-org/setup-my-cli@v2 # installs binary into ${MY_CLI_PATH}
---
`my-cli` is available. You can run `my-cli validate`, `my-cli fmt --check`, etc.
setup-my-cli unconditionally installs its binary into ${MY_CLI_PATH}, which by default is not on any path mounted into the agent container. Without a mount, the agent cannot invoke the binary even though it is present on the host.
The only way to expose it today is to add sandbox.agent.mounts to every main workflow that imports this partial:
# every-workflow-that-uses-my-cli.md (repeated in N files)
sandbox:
agent:
mounts:
- ${MY_CLI_PATH}/my-cli:${MY_CLI_PATH}/my-cli:ro
Proposed solution
Allow sandbox.agent.mounts (and potentially other sandbox.agent.* fields) in shared workflow partials. When compiling, the compiler should merge all mount lists from all imported shared partials with the main workflow's own sandbox.agent.mounts:
# shared/setup-my-cli.md
---
sandbox:
agent:
mounts:
- ${MY_CLI_PATH}/my-cli:${MY_CLI_PATH}/my-cli:ro
steps:
- name: Set up my-cli
uses: my-org/setup-my-cli@v2
---
`my-cli` is available. ...
With this, importing the shared partial is sufficient — the mount is declared alongside the step that installs the binary, and all consuming workflows get it automatically.
Merge semantics
When multiple shared partials (or a shared partial and the main workflow) each declare sandbox.agent.mounts, the compiler should union all mount lists into a single deduplicated list. Order within the list is not significant for correctness.
Example: if shared/setup-my-cli.md declares mount A and shared/setup-other-tool.md declares mount B, and a main workflow imports both and also declares mount C, the compiled awf invocation should include --mount A --mount B --mount C (deduplicated).
Alternatives considered
- Symlink into a well-known path: works for making the binary callable on the host PATH, but does not help the agent sandbox since the sandbox only sees explicitly mounted paths.
- Document the workaround: requires every workflow author to know they must add
sandbox.agent.mounts when importing a setup partial — fragile and easy to forget.
Impact
This would allow shared partials that install external tools to be truly self-contained, keeping the setup step and the corresponding sandbox declaration co-located in one file rather than scattered across every consuming workflow.
🤖 This issue has been filed by Claude Code.
Problem
The
sandboxfrontmatter field is currently only accepted in main workflow files (those with anon:trigger). Attempting to use it in a shared workflow partial causes the compiler to reject or silently ignore it:This means a shared partial that installs a binary into the runner environment cannot co-locate the mount declaration needed to make that binary accessible inside the agent sandbox. The mount must instead be duplicated in every main workflow that imports the shared partial — exactly the kind of repetition that shared partials exist to eliminate.
Motivating example
Suppose a shared partial sets up a CLI tool:
setup-my-cliunconditionally installs its binary into${MY_CLI_PATH}, which by default is not on any path mounted into the agent container. Without a mount, the agent cannot invoke the binary even though it is present on the host.The only way to expose it today is to add
sandbox.agent.mountsto every main workflow that imports this partial:Proposed solution
Allow
sandbox.agent.mounts(and potentially othersandbox.agent.*fields) in shared workflow partials. When compiling, the compiler should merge all mount lists from all imported shared partials with the main workflow's ownsandbox.agent.mounts:With this, importing the shared partial is sufficient — the mount is declared alongside the step that installs the binary, and all consuming workflows get it automatically.
Merge semantics
When multiple shared partials (or a shared partial and the main workflow) each declare
sandbox.agent.mounts, the compiler should union all mount lists into a single deduplicated list. Order within the list is not significant for correctness.Example: if
shared/setup-my-cli.mddeclares mount A andshared/setup-other-tool.mddeclares mount B, and a main workflow imports both and also declares mount C, the compiledawfinvocation should include--mount A --mount B --mount C(deduplicated).Alternatives considered
sandbox.agent.mountswhen importing a setup partial — fragile and easy to forget.Impact
This would allow shared partials that install external tools to be truly self-contained, keeping the setup step and the corresponding sandbox declaration co-located in one file rather than scattered across every consuming workflow.