Problem
Reusable workflow_call agentic workflows often need callers to choose whether safe-output threat detection should run for a particular invocation. Today safe-outputs.threat-detection is effectively compile-time: literal booleans and object config are accepted, but a GitHub Actions expression such as ${{ inputs.enable-threat-detection }} is not accepted as the top-level value or as threat-detection.enabled.
This means a reusable workflow cannot expose a simple input that lets callers select stricter or lighter-weight safe-output handling at runtime. Authors have to maintain separate workflow files for configurations that differ only in threat-detection behavior.
Related context: #23724 established appetite for parameterizing frontmatter fields other than engine.id. The earlier follow-ups covered timeout-minutes, engine.version, and some tool timeout fields, but not threat-detection toggles.
Desired Behavior
Both literal and expression forms should work:
on:
workflow_call:
inputs:
enable-threat-detection:
type: boolean
required: false
default: true
---
safe-outputs:
threat-detection: ${{ inputs.enable-threat-detection }}
And, if the object form is preferred for implementation clarity:
safe-outputs:
threat-detection:
enabled: ${{ inputs.enable-threat-detection }}
continue-on-error: ${{ inputs.detection-continue-on-error }}
Literal forms should remain backward compatible:
safe-outputs:
threat-detection: false
safe-outputs:
threat-detection:
enabled: true
continue-on-error: false
Implementation Plan
Please implement this as an agentic plan rather than a direct community PR.
-
Schema updates
- Update
pkg/parser/schemas/main_workflow_schema.json so safe-outputs.threat-detection accepts a GitHub Actions expression string in addition to the current boolean/object forms.
- Update the object form so
enabled and continue-on-error accept templatable booleans.
- Reuse the existing expression pattern and boolean-templating conventions already used elsewhere in safe-output config.
-
Parsing and config model
- Update
ThreatDetectionConfig and parseThreatDetectionConfig so boolean literals and expression strings are preserved distinctly.
- Consider using the existing
preprocessBoolFieldAsString / buildTemplatableBoolEnvVar / AddTemplatableBool helpers if they fit this path.
- Preserve current default behavior: when
safe-outputs exists and threat-detection is omitted, detection remains enabled by default.
- Preserve current explicit-disable behavior for literal
false.
-
Compilation behavior
- If an expression controls whether detection is enabled, compile a runtime conditional instead of deciding only at compile time.
- Ensure generated
needs and downstream safe-output/conclusion jobs handle the detection job being skipped at runtime.
- Prefer an explicit job or step
if: using the caller expression over shell-time branching.
- Ensure
continue-on-error expression values are passed safely, without direct shell interpolation.
-
Tests
- Add schema and parser coverage for:
threat-detection: true
threat-detection: false
threat-detection: ${{ inputs.enable-threat-detection }}
- object-form
enabled and continue-on-error expression values
- invalid non-expression strings
- Add compiler tests proving the expression appears in the generated lock YAML in a runtime-evaluable location.
- Add tests for downstream jobs when detection is conditionally skipped.
-
Documentation
- Update the safe outputs and threat detection references to show reusable
workflow_call examples.
- Mention that runtime expression support may compile the detection path and skip it at runtime rather than removing it at compile time.
Acceptance Criteria
Problem
Reusable
workflow_callagentic workflows often need callers to choose whether safe-output threat detection should run for a particular invocation. Todaysafe-outputs.threat-detectionis effectively compile-time: literal booleans and object config are accepted, but a GitHub Actions expression such as${{ inputs.enable-threat-detection }}is not accepted as the top-level value or asthreat-detection.enabled.This means a reusable workflow cannot expose a simple input that lets callers select stricter or lighter-weight safe-output handling at runtime. Authors have to maintain separate workflow files for configurations that differ only in threat-detection behavior.
Related context: #23724 established appetite for parameterizing frontmatter fields other than
engine.id. The earlier follow-ups coveredtimeout-minutes,engine.version, and some tool timeout fields, but not threat-detection toggles.Desired Behavior
Both literal and expression forms should work:
And, if the object form is preferred for implementation clarity:
Literal forms should remain backward compatible:
Implementation Plan
Please implement this as an agentic plan rather than a direct community PR.
Schema updates
pkg/parser/schemas/main_workflow_schema.jsonsosafe-outputs.threat-detectionaccepts a GitHub Actions expression string in addition to the current boolean/object forms.enabledandcontinue-on-erroraccept templatable booleans.Parsing and config model
ThreatDetectionConfigandparseThreatDetectionConfigso boolean literals and expression strings are preserved distinctly.preprocessBoolFieldAsString/buildTemplatableBoolEnvVar/AddTemplatableBoolhelpers if they fit this path.safe-outputsexists andthreat-detectionis omitted, detection remains enabled by default.false.Compilation behavior
needsand downstream safe-output/conclusion jobs handle the detection job being skipped at runtime.if:using the caller expression over shell-time branching.continue-on-errorexpression values are passed safely, without direct shell interpolation.Tests
threat-detection: truethreat-detection: falsethreat-detection: ${{ inputs.enable-threat-detection }}enabledandcontinue-on-errorexpression valuesDocumentation
workflow_callexamples.Acceptance Criteria
safe-outputs.threat-detection: ${{ inputs.enable-threat-detection }}validates and compiles.safe-outputs.threat-detection.enabledandcontinue-on-erroraccept boolean expressions.