Skip to content

Bug: dispatch-workflow safe-output causes CAPIError: 400 Bad Request in strict mode #26270

@corygehr

Description

@corygehr

Bug: dispatch-workflow safe-output causes CAPIError: 400 Bad Request in strict mode

Summary

Adding a dispatch-workflow safe-output to an agentic workflow causes the Copilot CLI agent to fail immediately with CAPIError: 400 Bad Request on the first inference attempt. Removing the dispatch-workflow safe-output (with no other changes) resolves the issue.

Environment

  • gh-aw version: v0.68.1 (latest)
  • Agent engine: Copilot CLI (agent_id: copilot)
  • Strict mode: true (default)
  • AWF image: 0.25.18

Context

We use a label-command router pattern: a lightweight workflow watches for issues: [labeled] events and dispatches the appropriate agentic workflow via workflow_dispatch. One agent workflow (the "analyzer") evaluates items and, if they pass, needs to dispatch a second agent workflow (the "executor") to act on them. We added dispatch-workflow to the analyzer so it can chain to the executor after completing its work.

Minimal Reproduction

Working configuration (no dispatch-workflow):

---
on:
  workflow_dispatch:
permissions:
  contents: read
  issues: read
tools:
  cache-memory: true
  bash: ["python3", "cat", "echo", "gh"]
  github:
    toolsets: [issues]
safe-outputs:
  update-issue:
    target: "*"
    max: 10
  add-labels:
    allowed: [some-label]
    max: 10
  remove-labels:
    allowed: [another-label]
    max: 10
  add-comment:
    target: "*"
    max: 10
  close-issue:
    target: "*"
    max: 10
---

# Analyzer Workflow

Evaluate issues and take action.

Broken configuration (only change: add dispatch-workflow):

safe-outputs:
  # ... same as above, plus:
  dispatch-workflow:
    workflows: [executor-workflow.agent]
    max: 3

Where executor-workflow.agent.md exists in the same repo and declares workflow_dispatch in its on: triggers.

Observed Behavior

  1. gh aw compile succeeds without errors.

  2. The compiled lock file contains a dynamic_tools entry with the dispatch tool definition.

  3. The workflow runs. The activation job succeeds. The agent job starts.

  4. During the "Execute GitHub Copilot CLI" step, the following warning appears:

    [entrypoint][WARN] Failed to transfer /host/home/runner/work/_temp/gh-aw/safeoutputs ownership to chroot user
    
  5. The Copilot CLI immediately fails on the first inference attempt:

    Execution failed: CAPIError: 400 400 Bad Request
    
  6. The copilot-driver retries with --resume, but subsequent attempts fail with:

    Error: No authentication information found.
    
  7. After all retries are exhausted, the job fails.

Expected Behavior

The workflow should start successfully and the dispatch-workflow tool should be available to the agent, same as any other safe-output tool.

Key Observations

  • The warning is the smoking gun: Failed to transfer /host/home/runner/work/_temp/gh-aw/safeoutputs ownership to chroot user does NOT appear in working runs (without dispatch-workflow). It consistently appears in all failing runs.
  • The 400 is from the Copilot Inference API, not GitHub Actions. The tool definitions (including the dynamic_tools for dispatch) are sent as MCP tools in the initial request. If the safe-outputs MCP server can't read the tool definition file due to the chroot ownership failure, the tool schema sent to the inference API may be malformed/incomplete, causing the 400.
  • Removing dispatch-workflow is the only change needed to fix it. All other safe-outputs (add-labels, remove-labels, update-issue, add-comment, close-issue) work correctly.
  • The issue is 100% reproducible. Tested 3 consecutive runs with dispatch-workflow (all failed identically), then 1 run without it (succeeded), then re-added it (failed again).

Compiled Lock File Diff

The only meaningful differences when dispatch-workflow is added:

  1. A dispatch_workflow entry in the safe-outputs config JSON
  2. A dynamic_tools array entry with the dispatch tool schema
  3. actions: write added to conclusion and safe_outputs job permissions
-              "dynamic_tools": []
+              "dynamic_tools": [
+                {
+                  "_workflow_name": "executor-workflow.agent",
+                  "description": "Dispatch the 'executor-workflow.agent' workflow...",
+                  "inputSchema": {
+                    "additionalProperties": false,
+                    "properties": {
+                      "aw_context": {
+                        "default": "",
+                        "description": "Agent caller context...",
+                        "type": "string"
+                      }
+                    },
+                    "type": "object"
+                  },
+                  "name": "executor_workflow.agent"
+                }
+              ]

Hypothesis

The dispatch-workflow safe-output adds a dynamic tool definition file to the safe-outputs directory. When the AWF sandbox (strict mode, chroot) tries to transfer ownership of the safe-outputs directory to the chroot user, this new file (or the directory structure change) fails the ownership transfer. The safe-outputs MCP server then starts with either a missing or unreadable tool definition, causing the Copilot Inference API to receive a malformed tool schema and return 400.

Workaround

Remove dispatch-workflow from safe-outputs. Use alternative chaining:

  • A label-command router workflow that polls for command labels on a cron schedule and dispatches the appropriate workflow
  • Or use call-workflow (compile-time fan-out) if the target workflow supports workflow_call

Metadata

Metadata

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions