Problem
Reusable workflow_call agentic workflows can parameterize some tool-related values today, such as tools.timeout and tools.startup-timeout, but the actual tools and tool allowlists remain compile-time-only.
This makes reusable workflows hard to compose when callers need to choose between otherwise-similar tool policies. For example, callers may want to select a Bash command allowlist, GitHub MCP toolsets, or whether an editing tool is enabled without maintaining separate workflow files for each tool configuration.
Representative examples that are not currently supported:
on:
workflow_call:
inputs:
bash-tools:
type: string
github-toolsets:
type: string
---
tools:
bash: ${{ inputs.bash-tools }}
github:
toolsets: ${{ inputs.github-toolsets }}
Related context: #23724 confirmed appetite for parameterizing frontmatter fields other than engine.id. Follow-up work covered timeout-minutes, engine.version, and tool timeout fields, but not tool availability or tool allowlists.
Desired Behavior
Reusable workflows should be able to expose selected tool policy inputs while preserving least privilege and fail-closed behavior.
Possible authoring pattern:
on:
workflow_call:
inputs:
bash-allowlist:
type: string
description: JSON array or newline/comma-separated command allowlist
github-toolsets:
type: string
description: JSON array or newline/comma-separated GitHub MCP toolsets
---
tools:
bash: ${{ inputs.bash-allowlist }}
github:
toolsets: ${{ inputs.github-toolsets }}
Literal static config must remain valid:
tools:
bash: ["bash", "git", "gh"]
edit:
github:
toolsets: [repos, issues]
Security Model
Because tools directly affect what an agent can do, expression support should not silently widen privileges.
A conservative implementation would be acceptable, for example:
- Require workflow authors to declare a compile-time maximum/superset of allowed tools.
- Let runtime inputs select a subset of that declared superset.
- Validate runtime-resolved values before enabling tools.
- Fail closed when an expression resolves to an invalid command/tool/toolset.
- Avoid expression support for fields that would require adding broader GitHub permissions at runtime unless the compiled workflow already includes the needed least-privilege permissions safely.
Proposed Scope
Start with fields that are high-value for reusable workflows and can be validated against known allowlists:
tools.bash command allowlist
tools.edit enable/disable if this can be expressed without changing job permissions unsafely
tools.github.toolsets
tools.github.allowed / tools.github.blocked if those are the current precise allowlist controls
- Any shared parsing helpers for string-list tool config
This issue intentionally excludes engine.id, which is a separate architectural question already called out in #23724.
Implementation Plan
Please implement this as an agentic-plan contribution rather than a direct community PR.
-
Audit tool config shape
- Inspect
pkg/parser/schemas/main_workflow_schema.json tool definitions and Go parsing under pkg/workflow.
- Identify which tool fields influence generated jobs, generated permissions, MCP server config, or runtime handler config.
- Classify fields as safe for expression support, safe only with compile-time superset validation, or not appropriate for runtime parameterization.
-
Choose runtime list format
- Reuse an existing convention where possible, such as JSON array, comma-separated string, newline-separated string, or the flexible list parser used by GitHub guard-policy fields.
- Document the chosen format for
workflow_call inputs.
-
Schema updates
- Allow selected fields to accept either their current literal types or a GitHub Actions expression string.
- Keep item-level validation for literal arrays.
- Keep non-expression strings invalid unless a field already intentionally accepts scalar strings.
-
Parser/config updates
- Preserve expression strings distinctly from literal arrays or booleans.
- Add or reuse templatable string-list helpers for tool allowlists.
- For fields with a compile-time superset model, validate that literal supersets are present and that runtime selections cannot exceed them.
-
Compilation/runtime validation
- Ensure expression values are emitted so GitHub Actions can evaluate them at runtime.
- Validate runtime-resolved values before starting tool servers or handing capabilities to the agent.
- Fail closed on malformed values or values outside the allowed superset.
- Avoid direct shell interpolation of expression-resolved values.
-
Tests
- Add schema/parser tests for literal values, expression values, invalid literal values, and invalid expression-resolved values.
- Add compiler tests proving expressions are preserved in generated lock YAML in runtime-evaluable locations.
- Add runtime tests for fail-closed validation of command/toolset selections.
-
Documentation
- Update the tools reference with reusable
workflow_call examples.
- Clearly document any compile-time superset requirement and runtime input format.
- Explain which tool fields support expressions and which remain compile-time by design.
Acceptance Criteria
Problem
Reusable
workflow_callagentic workflows can parameterize some tool-related values today, such astools.timeoutandtools.startup-timeout, but the actual tools and tool allowlists remain compile-time-only.This makes reusable workflows hard to compose when callers need to choose between otherwise-similar tool policies. For example, callers may want to select a Bash command allowlist, GitHub MCP toolsets, or whether an editing tool is enabled without maintaining separate workflow files for each tool configuration.
Representative examples that are not currently supported:
Related context: #23724 confirmed appetite for parameterizing frontmatter fields other than
engine.id. Follow-up work coveredtimeout-minutes,engine.version, and tool timeout fields, but not tool availability or tool allowlists.Desired Behavior
Reusable workflows should be able to expose selected tool policy inputs while preserving least privilege and fail-closed behavior.
Possible authoring pattern:
Literal static config must remain valid:
Security Model
Because tools directly affect what an agent can do, expression support should not silently widen privileges.
A conservative implementation would be acceptable, for example:
Proposed Scope
Start with fields that are high-value for reusable workflows and can be validated against known allowlists:
tools.bashcommand allowlisttools.editenable/disable if this can be expressed without changing job permissions unsafelytools.github.toolsetstools.github.allowed/tools.github.blockedif those are the current precise allowlist controlsThis issue intentionally excludes
engine.id, which is a separate architectural question already called out in #23724.Implementation Plan
Please implement this as an agentic-plan contribution rather than a direct community PR.
Audit tool config shape
pkg/parser/schemas/main_workflow_schema.jsontool definitions and Go parsing underpkg/workflow.Choose runtime list format
workflow_callinputs.Schema updates
Parser/config updates
Compilation/runtime validation
Tests
Documentation
workflow_callexamples.Acceptance Criteria
toolsfields accept GitHub Actions expression strings in reusable workflows.