Skip to content

Add AWF token steering frontmatter opt-out - #50122

Merged
pelikhan merged 3 commits into
mainfrom
copilot/fix-api-proxy-token-steering
Aug 4, 2026
Merged

Add AWF token steering frontmatter opt-out#50122
pelikhan merged 3 commits into
mainfrom
copilot/fix-api-proxy-token-steering

Conversation

Copilot AI commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Token steering could override an explicitly configured provider/model with an alias-selected, unconfigured provider. Workflow authors had no supported per-workflow control to disable it.

  • Sandbox configuration

    • Add sandbox.agent.token-steering boolean frontmatter.
    • Preserve existing default behavior when omitted.
  • AWF configuration

    • Emit apiProxy.enableTokenSteering: false when explicitly disabled.
    • Retain version gating and existing negative max-ai-credits behavior.
  • Discoverability

    • Update schema, editor autocomplete, reference documentation, and AWF config-source mapping.
sandbox:
  agent:
    token-steering: false

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix API-proxy token steering functionality Add AWF token steering frontmatter opt-out Aug 4, 2026
Copilot AI requested a review from pelikhan August 4, 2026 00:45
@pelikhan
pelikhan marked this pull request as ready for review August 4, 2026 00:52
Copilot AI review requested due to automatic review settings August 4, 2026 00:52
@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Design Decision Gate 🏗️ completed the design decision gate check.

No ADR enforcement needed: PR does not have the 'implementation' label and has ≤100 new lines of code in business logic directories (67 additions detected).

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

PR Code Quality Reviewer completed the code quality review.

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Test Quality Sentinel completed test quality analysis.

Test Quality Sentinel analysis complete for PR #50122: Score 90/100 (Excellent). 3 tests analyzed: 100 0esign-focused, 0 0mplementation. All behavioral contracts verified (token steering override, parser extraction, nil-state handling). No violations detected. Build tags present, no mock libraries used, descriptive assertions. Inflation noted but justified. Ready for merge.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a per-workflow opt-out for AWF API proxy token steering while preserving default behavior.

Changes:

  • Adds sandbox.agent.token-steering.
  • Emits explicit AWF token-steering configuration with version gating.
  • Updates tests, schema, autocomplete, and reference documentation.
Show a summary per file
File Description
specs/awf-config-sources-spec.md Maps the new frontmatter source.
pkg/workflow/sandbox.go Defines the sandbox option.
pkg/workflow/frontmatter_extraction_security.go Extracts the boolean setting.
pkg/workflow/frontmatter_extraction_security_test.go Tests extraction and omission.
pkg/workflow/awf_config.go Emits the AWF proxy setting.
pkg/workflow/awf_config_test.go Tests explicit disabling.
pkg/parser/schemas/main_workflow_schema.json Adds schema validation.
docs/src/content/docs/reference/sandbox.md Documents the opt-out.
docs/src/content/docs/reference/frontmatter-full.md Adds the full-reference entry.
docs/public/editor/autocomplete-data.json Adds editor autocomplete.
.github/aw/syntax-agentic.md Adds syntax guidance.

Review details

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 11/11 changed files
  • Comments generated: 1
  • Review effort level: Balanced

Comment on lines +556 to +558
if config.WorkflowData != nil && config.WorkflowData.SandboxConfig != nil && config.WorkflowData.SandboxConfig.Agent != nil && config.WorkflowData.SandboxConfig.Agent.TokenSteering != nil {
enableTokenSteering = *config.WorkflowData.SandboxConfig.Agent.TokenSteering
}
@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

PR Triage

  • Category: feature
  • Risk: medium
  • Score: 78/100 (impact 40, urgency 20, quality 18)
  • Recommended action: fast_track

Rationale: Adds a supported per-workflow opt-out (sandbox.agent.token-steering) for a real bug where token steering silently overrides an explicit provider/model config. Non-draft, mergeable, touches schema/docs/compiler with matching tests, linked to issue #50113. CI checks are still running (build/lint/tests in progress) at triage time — re-check before merge.

Automated PR triage.

Generated by 🔧 PR Triage Agent · auto · 30.2 AIC · ⌖ 3.69 AIC · ⊞ 8K ·

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: Add AWF token steering frontmatter opt-out

The feature is well-structured — schema, extraction, config emission, tests, and docs all updated together. Two issues found:

Blocking

  1. Wrong example value in frontmatter-full.md (line 2116): token-steering: true should be token-steering: false. The only reason to set this field explicitly is to disable the default behavior. See inline comment.

Non-blocking
2. Silent ignore when AWF version predates token-steering support: If a user explicitly sets token-steering: false on an old pinned AWF version, the opt-out is silently dropped with no log warning. See inline comment on awf_config.go:579.

🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · sonnet46 · 35.7 AIC · ⌖ 10.5 AIC · ⊞ 5.4K

# Enable or disable API proxy token steering. Set to false to preserve the
# explicitly configured provider and model.
# (optional)
token-steering: true

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The example value should be false, not true. The entire purpose of this field is to opt out of token steering — true is already the default and does not need to be set explicitly. Showing true here will mislead readers.

# Should be:
token-steering: false

@copilot please address this.

awfConfigLog.Printf("Skipping apiProxy.enableTokenSteering: max-ai-credits is negative (disabled)")
awfConfigLog.Print("Disabling apiProxy.enableTokenSteering")
} else if !awfSupportsTokenSteering(firewallConfig) {
awfConfigLog.Printf("Skipping apiProxy.enableTokenSteering: AWF version %q requires at least %s", getAWFImageTag(firewallConfig), constants.AWFTokenSteeringMinVersion)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When awfSupportsTokenSteering returns false but the user explicitly set sandbox.agent.token-steering: false, the explicit opt-out is silently dropped — the log only fires for the version-gating path when enableTokenSteering is true. A user who pins an old AWF version and sets token-steering: false will get no indication that their setting was ignored.

Consider emitting a warning when the user set the field explicitly but the version does not support it:

} else if !awfSupportsTokenSteering(firewallConfig) {
    if config.WorkflowData != nil && ... tokenSteering != nil {
        awfConfigLog.Printf("Warning: sandbox.agent.token-steering is set but AWF version %q requires at least %s; setting ignored",
            getAWFImageTag(firewallConfig), constants.AWFTokenSteeringMinVersion)
    } else {
        awfConfigLog.Printf("Skipping apiProxy.enableTokenSteering: ...")
    }
}

@copilot please address this.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · sonnet46 · 52.2 AIC · ⌖ 8.31 AIC · ⊞ 7.1K
Comment /matt to run again

maxAICredits = 0
}
var tokenSteeringEnabled *bool
if awfSupportsTokenSteering(firewallConfig) && (enableTokenSteering || (config.WorkflowData != nil && config.WorkflowData.SandboxConfig != nil && config.WorkflowData.SandboxConfig.Agent != nil && config.WorkflowData.SandboxConfig.Agent.TokenSteering != nil)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/codebase-design] The nil-guard chain on line 564 is a verbatim copy of the one on line 556, making the emit logic hard to follow. A shared local variable would eliminate the duplication and clarify intent.

💡 Suggested refactor

After line 557, capture the explicit-override flag once:

agent := func() *AgentSandboxConfig {
    if config.WorkflowData != nil && config.WorkflowData.SandboxConfig != nil {
        return config.WorkflowData.SandboxConfig.Agent
    }
    return nil
}()
explicitlySet := agent != nil && agent.TokenSteering != nil

Then lines 556–564 simplify to:

if explicitlySet {
    enableTokenSteering = *agent.TokenSteering
}
var tokenSteeringEnabled *bool
if awfSupportsTokenSteering(firewallConfig) && (enableTokenSteering || explicitlySet) {
    tokenSteeringEnabled = &enableTokenSteering
}

@copilot please address this.

EnableTokenSteering: tokenSteeringEnabled,
}

if !enableTokenSteering {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/diagnosing-bugs] The log message on line 577 says "Disabling" but that condition also fires when the sandbox override explicitly sets token-steering: false — the old message was more informative (it stated the reason: negative max-ai-credits). With the new opt-out path, the same branch covers two distinct causes without distinguishing them.

💡 Suggestion

Differentiate the two disablement paths in the log:

if !enableTokenSteering {
    if explicitlySet {
        awfConfigLog.Print("Disabling apiProxy.enableTokenSteering: sandbox.agent.token-steering=false")
    } else {
        awfConfigLog.Print("Disabling apiProxy.enableTokenSteering: max-ai-credits is negative")
    }
}

This keeps operational diagnostics actionable when users report unexpected behaviour.

@copilot please address this.

}

jsonStr, err := BuildAWFConfigJSON(config)
require.NoError(t, err)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/tdd] The new test verifies the happy path (sandbox disables steering), but misses the interaction case: when sandbox.agent.token-steering: false is set alongside a positive max-ai-credits, the feature should still be disabled. Without this test, a future refactor of the priority logic could silently regress the override behaviour.

💡 Suggested additional test case
t.Run("token steering sandbox override wins over positive max-ai-credits", func(t *testing.T) {
    disabled := false
    config := AWFCommandConfig{
        EngineName:     "copilot",
        AllowedDomains: "github.com",
        WorkflowData: &WorkflowData{
            EngineConfig: &EngineConfig{ID: "copilot", MaxAICredits: 500},
            NetworkPermissions: &NetworkPermissions{
                Firewall: &FirewallConfig{Enabled: true},
            },
            SandboxConfig: &SandboxConfig{
                Agent: &AgentSandboxConfig{TokenSteering: &disabled},
            },
        },
    }
    jsonStr, err := BuildAWFConfigJSON(config)
    require.NoError(t, err)
    assert.Contains(t, jsonStr, `"enableTokenSteering":false`)
})

@copilot please address this.

"type": "boolean",
"description": "Enable or disable API proxy token steering. Set to false to preserve the explicitly configured provider and model.",
"examples": [false]
},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/grill-with-docs] token-steering uses "type": "boolean" while its sibling model-fallback uses "$ref": "#/$defs/templatable_boolean" which also accepts GitHub Actions expressions. If a user tries token-steering: "${{ inputs.disable-steering }}" it will fail schema validation, which is an inconsistency they'll hit when parameterising workflows.

Consider using the same templatable_boolean ref — or if that's intentional (expressions not supported at runtime), add a comment in the schema noting why.

@copilot please address this.

# Enable or disable API proxy token steering. Set to false to preserve the
# explicitly configured provider and model.
# (optional)
token-steering: true

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/grill-with-docs] The reference doc shows the default as token-steering: true, but the feature is a pure opt-out — the only user-facing value is false. Showing true as the canonical example may confuse authors who are looking for the opt-out pattern.

Suggest showing the opt-out value in the example, matching the usage example in sandbox.md and syntax-agentic.md:

token-steering: false

@copilot please address this.

@github-actions github-actions Bot mentioned this pull request Aug 4, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔎 Code quality review by PR Code Quality Reviewer · auto · 54.2 AIC · ⌖ 4.56 AIC · ⊞ 7.9K
Comment /review to run again

// value (-1) omits that budget from the AWF config and disables token steering.
// When maxAICredits is 0 (runtime default), token steering stays enabled here.
enableTokenSteering := maxAICredits >= 0
if config.WorkflowData != nil && config.WorkflowData.SandboxConfig != nil && config.WorkflowData.SandboxConfig.Agent != nil && config.WorkflowData.SandboxConfig.Agent.TokenSteering != nil {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Explicit token-steering:true silently re-enables steering even when max-ai-credits is negative (intentionally disabled), while maxAiCredits is still omitted from the config — an untested, inconsistent combination.

💡 Details

Before this PR, enableTokenSteering := maxAICredits >= 0 was the sole source of truth, and maxAICredits < 0 reliably meant "no budget, no steering". Now an explicit sandbox.agent.token-steering: true override runs after that computation but before maxAICredits is reset to 0 for omission, so:

enableTokenSteering := maxAICredits >= 0
if ...SandboxConfig.Agent.TokenSteering != nil {
    enableTokenSteering = *config.WorkflowData.SandboxConfig.Agent.TokenSteering
}
if maxAICredits < 0 {
    maxAICredits = 0 // omitted from config
}

If a workflow sets max-ai-credits: -1 (explicitly disabling the budget) AND sandbox.agent.token-steering: true, the emitted config has enableTokenSteering:true with no maxAiCredits field. It is unclear whether AWF's token steering can function meaningfully without a budget to steer against, and no test exercises this combination (only max-ai-credits-negative alone and token-steering:false alone are covered).

Suggested fix: either ignore/reject the override when maxAICredits < 0 with a clear log message, or add a test that documents the intended behavior for this combination.

maxAICredits = 0
}
var tokenSteeringEnabled *bool
if awfSupportsTokenSteering(firewallConfig) && (enableTokenSteering || (config.WorkflowData != nil && config.WorkflowData.SandboxConfig != nil && config.WorkflowData.SandboxConfig.Agent != nil && config.WorkflowData.SandboxConfig.Agent.TokenSteering != nil)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 4-level nil-check chain for SandboxConfig.Agent.TokenSteering is duplicated three times in ~15 lines — extract a helper to avoid drift.

💡 Details
if config.WorkflowData != nil && config.WorkflowData.SandboxConfig != nil && config.WorkflowData.SandboxConfig.Agent != nil && config.WorkflowData.SandboxConfig.Agent.TokenSteering != nil {

This exact expression (or a near-duplicate) appears at line 556 and twice more within the if at line 564. Any future refactor of SandboxConfig/AgentSandboxConfig risks updating some occurrences but not others, silently breaking the override logic. Extract a small helper, e.g.:

func tokenSteeringOverride(wd *WorkflowData) *bool {
    if wd == nil || wd.SandboxConfig == nil || wd.SandboxConfig.Agent == nil {
        return nil
    }
    return wd.SandboxConfig.Agent.TokenSteering
}

and reuse tokenSteeringOverride(config.WorkflowData) != nil / the dereferenced value at each call site. This also matches the existing pattern of small extractXxx helpers already used elsewhere in this file (e.g. extractModelFallback).

@pelikhan

pelikhan commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

@copilot run pr-finisher skill

@pelikhan
pelikhan merged commit 30bc231 into main Aug 4, 2026
5 checks passed
@pelikhan
pelikhan deleted the copilot/fix-api-proxy-token-steering branch August 4, 2026 01:21
@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

🎉 Great work on this fix, @Copilot! This PR resolves a real and well-documented pain point — token steering was silently routing requests to unconfigured providers while overriding explicit provider/model choices.

What stands out:

This looks ready for review and merge. The implementation is clean, focused, and addresses exactly what the issue identified.

Generated by ✅ Contribution Check · auto · 40.5 AIC · ⌖ 4.24 AIC · ⊞ 8.8K ·

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

🎉 This pull request is included in a new release.

Release: v0.84.4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

3 participants