Skip to content

feat: support bounded queries in workflow frontmatter and AWF configuration - #49149

Merged
lpcox merged 5 commits into
mainfrom
copilot/support-bounded-queries
Jul 30, 2026
Merged

feat: support bounded queries in workflow frontmatter and AWF configuration#49149
lpcox merged 5 commits into
mainfrom
copilot/support-bounded-queries

Conversation

Copilot AI commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

AWF supports bounded queries for finite, pre-approved cross-repository private data access, but gh-aw had no way to configure this declaratively. Workflows needing private-repo data had to fall back to checkout, cross-repo tokens, or manual AWF config.

Changes

Frontmatter schema (sandbox.go)

  • Adds BoundedQueriesConfig and BoundedQueryPrivateRepo types on AgentSandboxConfig.BoundedQueries
  • All optional fields (runtime, timeout, memory-limit, interpreter, max-invocations) are omitted from the generated config when unset — AWF remains source of truth for defaults
sandbox:
  agent:
    id: awf
    bounded-queries:
      private-repos:
        - repo: my-org/internal-service
          sensitivity: internal      # public | internal | confidential | sealed
        - repo: my-org/confidential-data
          sensitivity: confidential
      runtime: docker      # optional
      timeout: 30          # optional, seconds
      memory-limit: 512m   # optional
      interpreter: python3 # optional
      max-invocations: 32  # optional

AWF config generation (awf_config.go)

  • Adds AWFBoundedQueriesConfig / AWFBoundedQueryPrivateRepo structs mapping to AWF's boundedQueries JSON schema
  • extractBoundedQueriesConfig helper populates AWFConfigFile.BoundedQueries; always sets enabled: true
  • Gated behind AWFBoundedQueriesMinVersion (v0.28.0) — silently skipped for pinned older versions

Validation (sandbox_validation.go)

Compilation rejects:

  • Empty or nil private-repos
  • Duplicate owner/repo slugs
  • GitHub Actions expressions in repo slugs or sensitivity values
  • Invalid sensitivity (only public, internal, confidential, sealed)
  • Unsupported runtime (only docker) or interpreter (only python3)
  • Negative timeout or max-invocations
  • Invalid memory-limit format (must match \d+[kmgKMG])
  • bounded-queries on a non-AWF sandbox

Schema (schemas/awf-config.schema.json)

  • Adds boundedQueries top-level property with full property definitions and constraints

Constants (version_constants.go, awf_helpers.go)

  • AWFBoundedQueriesMinVersion = "v0.28.0" with corresponding awfSupportsBoundedQueries() helper

Tests (bounded_queries_test.go, spec_test.go)

  • TestBuildAWFConfigJSON_BoundedQueries: end-to-end JSON output including version-gate behavior
  • TestExtractBoundedQueriesConfig: extraction helper edge cases
  • TestValidateBoundedQueriesConfig: all valid and invalid inputs including all four sensitivity levels
  • TestValidateRepoSlug: slug format and expression rejection
  • TestAWFBoundedQueriesJSONRoundtrip: JSON serialization fidelity
  • TestSpec_VersionConstraints_MinVersionValues: AWFBoundedQueriesMinVersion pinned value

Documentation (.github/aw/syntax-agentic.md)

  • Documents sandbox.agent.bounded-queries with full example, sensitivity level descriptions, and guidance on when bounded queries are appropriate vs. unsuitable (source-code extraction, unbounded answers)

Warning

threat detection engine error
The threat detection engine encountered an error and could not complete analysis. This is a tooling failure, not a security finding.

Details

The threat detection engine failed to produce results.

Review the workflow run logs for details.

Generated by 👨‍🍳 PR Sous Chef · gpt54 · 10.3 AIC · ⊞ 6.3K ·
Comment /souschef to run again


Warning

threat detection engine error
The threat detection engine encountered an error and could not complete analysis. This is a tooling failure, not a security finding.

Details

The threat detection engine failed to produce results.

Review the workflow run logs for details.

run: https://github.com/github/gh-aw/actions/runs/30563574734

Generated by 👨‍🍳 PR Sous Chef · gpt54 · 9.6 AIC · ⊞ 8.7K ·
Comment /souschef to run again

@pelikhan

Copy link
Copy Markdown
Collaborator

@lpcox can we chat about this? tools.github might be a better home for this frontmatter.

Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
Copilot AI changed the title [WIP] Add support for bounded queries in workflow frontmatter feat: support bounded queries in workflow frontmatter and AWF configuration Jul 30, 2026
Copilot finished work on behalf of lpcox July 30, 2026 14:32
Copilot AI requested a review from lpcox July 30, 2026 14:32
@lpcox
lpcox marked this pull request as ready for review July 30, 2026 15:13
Copilot AI review requested due to automatic review settings July 30, 2026 15:13
@lpcox

lpcox commented Jul 30, 2026

Copy link
Copy Markdown
Collaborator

That makes sense. Bounded queries are implemented by AWF, but their user-facing configuration is specifically about GitHub repository access. I’ll move the frontmatter to tools.github.bounded-queries while continuing to compile it into AWF’s boundedQueries configuration for enforcement.

@lpcox

lpcox commented Jul 30, 2026

Copy link
Copy Markdown
Collaborator

@copilot move bounded-queries config from sandbox.agent to tools.github in the front matter

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 declarative bounded-query configuration for AWF private-repository access.

Changes:

  • Adds frontmatter and AWF configuration types.
  • Adds validation, version gating, schemas, and tests.
  • Documents bounded-query usage and sensitivity levels.
Show a summary per file
File Description
.github/aw/syntax-agentic.md Documents bounded queries.
pkg/constants/spec_test.go Tests the minimum version constant.
pkg/constants/version_constants.go Defines the AWF version gate.
pkg/workflow/awf_config.go Generates bounded-query AWF JSON.
pkg/workflow/awf_helpers.go Adds version-support detection.
pkg/workflow/bounded_queries_test.go Tests generation and validation.
pkg/workflow/sandbox.go Defines frontmatter configuration types.
pkg/workflow/sandbox_validation.go Validates bounded-query settings.
pkg/workflow/schemas/awf-config.schema.json Extends the generated AWF schema.

Review details

Tip

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

Comments suppressed due to low confidence (5)

pkg/workflow/schemas/awf-config.schema.json:810

  • AWF caps bounded-query timeouts at 540 seconds to reserve cleanup time before the final timing bucket. This schema has no upper bound, and validateBoundedQueriesConfig likewise accepts values above 540, so gh-aw accepts a workflow that AWF later rejects at startup. Add the 540 maximum throughout frontmatter and domain validation.
          "minimum": 1

pkg/workflow/schemas/awf-config.schema.json:815

  • This pattern diverges from AWF's accepted Docker-memory format: it permits zero-valued limits such as 0m, which AWF rejects, and rejects valid byte limits such as 512b. Align the schema and Go validator with AWF's positive [bkmg] format so compilation cannot defer failure to AWF preflight.
          "pattern": "^\\d+[kmgKMG]$"

pkg/workflow/schemas/awf-config.schema.json:825

  • AWF's schema limits maxInvocations to 1–10000. Without the upper bound here—and with the Go validator only checking negatives—gh-aw can emit a config that AWF rejects. Add the 10000 maximum consistently to schema and validation.
          "minimum": 1

.github/aw/syntax-agentic.md:336

  • The linked issue requires authentication instructions and a basic query example, but this section only states that the credential remains host-side. Document that AWF staging resolves GH_TOKEN/GITHUB_TOKEN, explain how the workflow supplies it without exposing it to the agent, and include a minimal bounded-query --repo ... --schema ... invocation.
    Sensitivity levels: `public` (no restrictions), `internal` (internal-only audiences), `confidential` (restricted within org), `sealed` (highest restriction). The staging credential used to access private repositories must remain host-side and is never written to the lock file or exposed to the agent. Use bounded queries when the question has a finite, bounded answer; prefer this over granting a cross-repository token or checking out the private repository into the primary workspace.

.github/aw/syntax-agentic.md:336

  • These sensitivity descriptions are materially inaccurate. public is unmetered but still subject to finite-schema and operational limits; AWF budgets internal at 64 bits/run, confidential at 8 bits/run, and sealed at 0 bits/run, so sealed repositories cannot answer any query. Documenting only audience labels can cause authors to select a level that cannot support the intended workload.
    Sensitivity levels: `public` (no restrictions), `internal` (internal-only audiences), `confidential` (restricted within org), `sealed` (highest restriction). The staging credential used to access private repositories must remain host-side and is never written to the lock file or exposed to the agent. Use bounded queries when the question has a finite, bounded answer; prefer this over granting a cross-repository token or checking out the private repository into the primary workspace.
  • Files reviewed: 9/9 changed files
  • Comments generated: 4
  • Review effort level: Medium

Comment thread pkg/workflow/sandbox_validation.go Outdated
}

// Validate no duplicates.
key := r.Repo

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in the latest commit. Changed key := r.Repo to key := strings.ToLower(r.Repo) so that slugs like octo/private and Octo/Private are treated as duplicates, matching AWF's case-insensitive handling. A new test "rejects duplicate repo slugs case-insensitively" covers this case.

"runtime": {
"type": "string",
"description": "Container runtime used to execute bounded-query scripts. When omitted AWF uses its default.",
"enum": ["docker"]

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in the latest commit. gvisor is now included consistently across:

  • validBoundedQueryRuntimes in sandbox_validation.go (added "gvisor": {})
  • Error message updated to "must be \"docker\" or \"gvisor\""
  • awf-config.schema.json enum changed to ["docker", "gvisor"]
  • main_workflow_schema.json bounded-queries runtime enum also set to ["docker", "gvisor"]
  • syntax-agentic.md example comment updated to # optional; docker | gvisor
  • New test "accepts gvisor runtime" added

Comment thread pkg/workflow/sandbox.go Outdated
Memory string `yaml:"memory,omitempty"` // Memory limit for the AWF container (e.g., "4g", "8g")
ModelFallback *TemplatableBool `yaml:"model-fallback,omitempty"` // AWF API proxy model fallback enable/disable flag (optional)
Targets map[string]*AgentAPIProxyTargetConfig `yaml:"targets,omitempty"` // Per-provider API proxy target overrides keyed by provider name (e.g. "openai", "anthropic")
BoundedQueries *BoundedQueriesConfig `yaml:"bounded-queries,omitempty"` // Bounded-query configuration for cross-repository private data access

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This thread is outdated: the bounded-queries config was moved from sandbox.agent to tools.github in 6ed6e07. The pipeline wiring was completed for that location: tools_parser.go has parseBoundedQueriesConfig() called from parseGitHubTool(), and main_workflow_schema.json now declares bounded-queries as a property of the tools.github object schema (added in the latest commit), so the YAML is no longer rejected by additionalProperties: false.

Comment thread .github/aw/syntax-agentic.md Outdated

- **`sandbox.agent.sudo`** (boolean) controls whether AWF runs in root mode. Default is `false`: AWF runs rootless in network-isolation egress mode (`--network-isolation`), with MCP sidecars attached as bridge containers on the internal `awf-net` network. Set `sudo: true` for the legacy root mode; in strict mode explicit `sudo: true` is an error (warning otherwise).
- **`sandbox.agent.runtime`** (string) selects an extra-isolation container runtime for the agent: `gvisor` (runs under gVisor's `runsc` for kernel-level isolation) or `docker-sbx` (Docker sbx microVM with KVM hypervisor-level isolation; needs `DOCKER_PAT`/`DOCKER_USERNAME` secrets and a KVM-capable runner). Both require `sudo: true` and are incompatible with `runner.topology: arc-dind`.
- **`sandbox.agent.bounded-queries`** (object, AWF v0.28.0+) configures the AWF bounded-query subsystem for cross-repository private data access. When present, the agent may answer finite, pre-approved questions about the listed repositories using the generated `bounded-query` skill — without receiving raw source code. This is the preferred pattern for cross-repository workflows. All optional fields use AWF defaults when omitted.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This thread is outdated (bounded-queries moved to tools.github in 6ed6e07), but the authoring-guidance concern was valid. Fixed in the latest commit:

  • create-agentic-workflow.md: The "Multi-Repository Requests" section now first asks whether the question is finite/bounded. If yes → use tools.github.bounded-queries (preferred). If no or unbounded → use cross-repo token/checkout.
  • designer.md: Added "finite question about private repo" row to the Tool Mapping table pointing to tools.github.bounded-queries, and a corresponding row in the Data Strategy Mapping table.

Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>

Copilot AI commented Jul 30, 2026

Copy link
Copy Markdown
Contributor Author

@copilot move bounded-queries config from sandbox.agent to tools.github in the front matter

Done in 6ed6e07. Moved bounded-queries from sandbox.agent to tools.github:

tools:
  github:
    bounded-queries:
      private-repos:
        - repo: my-org/internal-service
          sensitivity: internal
sandbox:
  agent:
    id: awf

Changes across:

  • tools_types.goBoundedQueriesConfig types and BoundedQueries field added to GitHubToolConfig
  • tools_parser.goparseBoundedQueriesConfig helper added; parseGitHubTool now populates it
  • sandbox.go — field and types removed from AgentSandboxConfig
  • sandbox_validation.go / compiler_validators.go — validation updated to *WorkflowData and field paths updated to tools.github.bounded-queries.*
  • awf_config.goextractBoundedQueriesConfig reads from ParsedTools.GitHub.BoundedQueries
  • bounded_queries_test.go — all tests updated
  • syntax-agentic.md — docs moved under tools:

Copilot finished work on behalf of lpcox July 30, 2026 15:40
@gh-aw-bot

Copy link
Copy Markdown
Collaborator

Warning

threat detection engine error
The threat detection engine encountered an error and could not complete analysis. This is a tooling failure, not a security finding.

Details

The threat detection engine failed to produce results.

Review the workflow run logs for details.

@copilot please run the pr-finisher skill, address any unresolved review feedback, and rerun checks once the branch is up to date.

Generated by PR Sous Chef run: https://github.com/github/gh-aw/actions/runs/30557283067

Generated by 👨‍🍳 PR Sous Chef · gpt54 · 10.3 AIC · ⊞ 6.3K ·
Comment /souschef to run again

@lpcox lpcox left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The move to tools.github.bounded-queries is internally consistent, but I found four issues to address before merge:

  1. Malformed frontmatter is silently discarded (pkg/workflow/tools_parser.go). If bounded-queries has the wrong type, or private-repos mixes valid objects with malformed entries, the parser ignores the invalid input instead of rejecting it. Please preserve malformed input long enough to produce a validation error rather than silently generating a reduced or absent policy.

  2. Validation limits diverge from AWF (pkg/workflow/sandbox_validation.go and pkg/workflow/schemas/awf-config.schema.json). Enforce timeout from 1 through 540, max-invocations from 1 through 10000, and memory limits matching ^[1-9][0-9]*[bkmgBKMG]$. The current rules accept values AWF rejects at startup and reject valid byte limits. Explicit zero values should also be rejected rather than treated as omitted.

  3. Unsupported AWF versions silently omit bounded queries (pkg/workflow/awf_config.go). When the workflow requests bounded queries but pins an AWF version below the minimum, compilation should fail with an actionable version error. Silently generating a workflow without the requested capability is surprising and may cause the agent to follow an invalid access model.

  4. Sensitivity documentation is inaccurate (.github/aw/syntax-agentic.md). Please document the actual disclosure budgets: public is unmetered but still schema- and operationally bounded, internal is 64 bits/run, confidential is 8 bits/run, and sealed is 0 bits/run and cannot fund a query.

@lpcox

lpcox commented Jul 30, 2026

Copy link
Copy Markdown
Collaborator

@copilot address feedback #49149 (review)

Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
Issue 1: Surface malformed frontmatter parse errors
- Add ParseError field to BoundedQueriesConfig
- In parseGitHubTool: create sentinel config when bounded-queries has wrong type
- In parseBoundedQueriesConfig: set ParseError for wrong-type private-repos,
  non-map items, and wrong-type timeout/max-invocations
- In validateBoundedQueriesConfig: reject configs with non-empty ParseError

Issue 2: Fix validation limits to match AWF contract
- Change Timeout and MaxInvocations from int to *int to distinguish
  unset (nil) from explicitly-set-to-zero (which is now rejected)
- Timeout: enforce range 1-540 (AWF contract); rejects 0 and > 540
- MaxInvocations: enforce range 1-10000 (AWF contract); rejects 0 and > 10000
- memory-limit pattern: ^[1-9][0-9]*[bkmgBKMG]$ (reject leading zeros,
  reject 0m/0k, allow b/B unit, match AWF's accepted format)
- Update both awf-config.schema.json and main_workflow_schema.json

Issue 3: Unsupported AWF versions now fail compilation
- validateBoundedQueriesConfig checks awfSupportsBoundedQueries() and
  returns a hard validation error with actionable version guidance
  instead of silently omitting the bounded-queries section

Issue 4: Accurate sensitivity documentation
- Document actual disclosure budgets: public=unmetered, internal=64 bits/run,
  confidential=8 bits/run, sealed=0 bits/run (cannot fund a query)

Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>

Copilot AI commented Jul 30, 2026

Copy link
Copy Markdown
Contributor Author

@copilot address feedback #49149 (review)

Done in the latest commit. All four issues addressed:

  1. Malformed frontmatter surfaces errors: BoundedQueriesConfig now has a ParseError string field. The parser sets it when bounded-queries is not a mapping, private-repos is not an array, a repo entry is not a map, or timeout/max-invocations have the wrong type. validateBoundedQueriesConfig rejects any config with a non-empty ParseError.

  2. Validation limits match AWF: Timeout and MaxInvocations changed from int to *int so that explicit zero (invalid) is distinguishable from unset (nil, skipped). Enforced ranges are timeout: 1–540, max-invocations: 1–10000. Memory-limit pattern updated to ^[1-9][0-9]*[bkmgBKMG]$ (rejects leading zeros and bare-zero values, adds b/B unit). Both schema files updated to match.

  3. Unsupported AWF version is a compile error: validateBoundedQueriesConfig now calls awfSupportsBoundedQueries() and returns a ValidationError with actionable guidance when bounded queries are requested but the effective version (including the default v0.27.42) is below v0.28.0. Workflows must explicitly pin firewall.version or sandbox.agent.version to v0.28.0+.

  4. Sensitivity documentation corrected: Documents the actual disclosure budgets — public (unmetered), internal (64 bits/run), confidential (8 bits/run), sealed (0 bits/run; cannot fund a query).

Copilot AI requested a review from lpcox July 30, 2026 16:31
Copilot finished work on behalf of lpcox July 30, 2026 16:31
@gh-aw-bot

Copy link
Copy Markdown
Collaborator

Warning

threat detection engine error
The threat detection engine encountered an error and could not complete analysis. This is a tooling failure, not a security finding.

Details

The threat detection engine failed to produce results.

Review the workflow run logs for details.

@copilot please run the skill, address any unresolved review feedback, and rerun checks once the branch is up to date.

Generated by 👨‍🍳 PR Sous Chef · gpt54 · 9.6 AIC · ⊞ 8.7K ·
Comment /souschef to run again

@github-actions

Copy link
Copy Markdown
Contributor

🎉 This pull request is included in a new release.

Release: v0.84.1

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support bounded queries in workflow frontmatter and generated AWF configuration

5 participants