Skip to content

Bug: engine.agent propagates to threat detection job, causing "No such agent" failure #17943

@benvillalobos

Description

@benvillalobos

🤖 AI Assisted Bug Report

Summary

When engine.agent is set in a workflow's frontmatter along with an explicit model, the --agent flag is propagated to the threat detection job's Copilot CLI invocation. The detection job does not check out the repository, so the agent file is unavailable, causing an immediate failure: No such agent: <name>, available: (empty list).

Reproduction

  1. Create a workflow .md with engine.agent and an explicit model:
engine:
  id: copilot
  agent: my-agent
  model: claude-opus-4.6
  1. Place a matching agent file at .github/agents/my-agent.agent.md
  2. Configure safe-outputs (which enables threat detection)
  3. Compile with gh aw compile and run via workflow_dispatch

Expected: All jobs succeed — the agent job uses --agent my-agent, the detection job runs threat analysis without the --agent flag.

Actual: The agent job succeeds, but the detection job fails with:

No such agent: my-agent, available:
Process completed with exit code 1

Safe outputs are skipped because detection failed.

Root Cause

In pkg/workflow/threat_detection.go buildEngineSteps(), the detectionEngineConfig is set differently depending on whether a model is explicitly configured:

When model IS configured (modelExplicitlyConfigured == true):

detectionEngineConfig = engineConfig  // Full reference — includes Agent field

This passes the entire EngineConfig (including Agent: "my-agent") to the threat detection WorkflowData, which causes GetExecutionSteps() in copilot_engine_execution.go to emit --agent my-agent.

When model is NOT configured, the code creates a manual copy that happens to omit Agent:

detectionEngineConfig = &EngineConfig{
    ID:          detectionEngineConfig.ID,
    Model:       "",
    Version:     detectionEngineConfig.Version,
    MaxTurns:    detectionEngineConfig.MaxTurns,
    Concurrency: detectionEngineConfig.Concurrency,
    UserAgent:   detectionEngineConfig.UserAgent,
    Env:         detectionEngineConfig.Env,
    Config:      detectionEngineConfig.Config,
    Args:        detectionEngineConfig.Args,
    Firewall:    detectionEngineConfig.Firewall,
    // Agent is NOT copied — accidentally correct for detection
}

The detection job also doesn't check out the repository (no actions/checkout step) and doesn't add $GITHUB_WORKSPACE to --add-dir, so even if --agent is passed, the agent file can't be found.

Suggested Fix

Always strip the Agent field from the detection engine config, similar to how Model is already handled. The threat detection job has its own purpose (analyzing agent output for threats) and should never run as a custom agent.

In the modelExplicitlyConfigured branch, create a copy that excludes Agent:

if modelExplicitlyConfigured {
    detectionEngineConfig = &EngineConfig{
        ID:          engineConfig.ID,
        Model:       engineConfig.Model,
        Version:     engineConfig.Version,
        MaxTurns:    engineConfig.MaxTurns,
        Concurrency: engineConfig.Concurrency,
        UserAgent:   engineConfig.UserAgent,
        Env:         engineConfig.Env,
        Config:      engineConfig.Config,
        Args:        engineConfig.Args,
        Firewall:    engineConfig.Firewall,
        // Agent intentionally omitted — detection should not use custom agents
    }
}

Or alternatively, strip Agent after the config is determined:

// Threat detection should never run as a custom agent
if detectionEngineConfig != nil {
    detectionEngineConfig.Agent = ""
}

Environment

Workaround

Remove engine.agent from the workflow frontmatter and instead use {{#runtime-import}} to pull the agent file's content inline, avoiding the --agent flag entirely.

Metadata

Metadata

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions