Skip to content

feat: Migrate compiler to use AWF JSON config file instead of CLI flags #29220

@lpcox

Description

@lpcox

Problem

The gh-aw compiler currently generates AWF invocations using command-line flags:

awf --allow-domains github.com api.github.com \
    --enable-api-proxy \
    --dns-servers 8.8.8.8,8.8.4.4 \
    --image-tag v0.25.29 \
    --agent-timeout 300 \
    ...
    -- "claude ..."

As AWF gains more configuration surface (model policies, rate limits, api-proxy targets, container settings), this approach has scaling problems:

  1. Shell escaping — Complex values (JSON objects, multi-line strings) are fragile in shell argv
  2. Readability — Long flag lists in lock files are hard to audit
  3. Composability — No clean way to layer org-level defaults with workflow-level overrides
  4. Validation — Flags are validated only at runtime; config files can be schema-validated at compile time

Proposed Solution

AWF already supports --config <path|-> which loads a JSON/YAML config file (gh-aw-firewall src/config-file.ts). The compiler should generate a config file and invoke AWF with it:

awf --config .awf-config.json -- "claude ..."

Where .awf-config.json contains the structured configuration:

{
  "$schema": "https://github.com/github/gh-aw-firewall/schemas/awf-config.v1.json",
  "network": {
    "allowDomains": ["github.com", "api.github.com", "*.actions.githubusercontent.com"],
    "dnsServers": ["8.8.8.8", "8.8.4.4"]
  },
  "apiProxy": {
    "enabled": true,
    "targets": {
      "openai": { "host": "api.openai.com" },
      "anthropic": { "host": "api.anthropic.com" },
      "copilot": { "host": "api.githubcopilot.com" }
    }
  },
  "container": {
    "imageTag": "v0.25.29",
    "agentTimeout": 300,
    "buildLocal": false
  },
  "modelPolicy": {
    "model": { "id": "claude-sonnet-4-20250514", "provider": "anthropic" },
    "fallback": [{ "strategy": "auto" }],
    "onUnavailable": "fail"
  }
}

Benefits

Aspect CLI flags (current) Config file (proposed)
Complex values Shell escaping issues Native JSON types
Auditability Long one-liner Structured, diffable
Schema validation Runtime only Compile-time + IDE support
Composability Flag precedence only File merging + overlays
New features New flag per feature Add to schema, no argv changes
Model policy Not expressible First-class object (#2309)

Implementation Plan

Phase 1: Compiler generates config file

  1. Compiler emits .awf-config.json alongside the lock file (or inline via --config - on stdin)
  2. Lock file run: step changes from flag soup to awf --config .awf-config.json -- "..."
  3. Backwards compatible: AWF already supports --config; CLI flags still override for user ad-hoc runs

Phase 2: Schema validation at compile time

  1. Publish JSON Schema in gh-aw-firewall (schemas/awf-config.v1.json)
  2. gh aw compile --validate validates the generated config against the schema
  3. IDE support via $schema field for autocomplete in editors

Phase 3: Composable config layers

  1. Org-level defaults (.github/awf-config.json)
  2. Workflow-level overrides (frontmatter → config)
  3. CLI flags as final override layer
  4. Merge semantics: deep merge with arrays replaced (not appended)

AWF Config File Support (already implemented)

The firewall already supports config files via --config <path|->:

  • Parses JSON or YAML
  • Validates against known schema sections: network, apiProxy, container
  • Maps config keys to CLI option equivalents
  • CLI flags take precedence over file values

Key source files:

Related

  • gh-aw-firewall#2309 — Model-selection policy schema (new config section)
  • gh-aw#29191 — Model fallback feature request
  • AWF --config docs: awf --help--config <path|-> Load configuration from JSON/YAML file (use - for stdin)

Metadata

Metadata

Assignees

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