Tools, Imports, and Permissions
June 27, 2026 · View on GitHub
Cache Configuration
The cache: field supports the same syntax as the GitHub Actions actions/cache action:
Single Cache:
cache:
key: node-modules-${{ hashFiles('package-lock.json') }}
path: node_modules
restore-keys: |
node-modules-
Multiple Caches:
cache:
- key: node-modules-${{ hashFiles('package-lock.json') }}
path: node_modules
restore-keys: |
node-modules-
- key: build-cache-${{ github.sha }}
path:
- dist
- .cache
restore-keys:
- build-cache-
fail-on-cache-miss: false
Supported Cache Parameters:
key:- Cache key (required)path:- Files/directories to cache (required, string or array)restore-keys:- Fallback keys (string or array)upload-chunk-size:- Chunk size for large files (integer)fail-on-cache-miss:- Fail if cache not found (boolean)lookup-only:- Only check cache existence (boolean)
Cache steps are auto-added to the workflow job; cache config is removed from the final .lock.yml.
Memory configuration: For
cache-memory:,repo-memory:, andcomment-memory:, see memory.md.
Tool Configuration
The tools: field configures which tools the coding agent may use.
GitHub Tools (tools.github)
-
allowed:- Array of allowed GitHub API functions. Each entry is either a string tool name (e.g.,issue_read) or an object{ name: <tool>, max-calls: <n> }to cap how many times that tool may be called per run. Colon shorthand ("issue_read:1") is not a call-limit form.tools: github: allowed: - { name: issue_read, max-calls: 1 } - list_labels - pull_request_read -
mode:- GitHub access mode. Prefer"gh-proxy"— it is faster (no MCP server startup) and lets the agent useghshell commands directly for all GitHub reads (issues, PRs, discussions, commits, etc.):"gh-proxy"(preferred) — pre-authenticatedghCLI available in bash; no GitHub MCP server is registered. Useghcommands for all GitHub reads."local"(default) — Docker-based GitHub MCP Server; use GitHub MCP tools for reads,ghis not authenticated.- do NOT use
"remote"— it does not work with the GitHub Actions token; use"gh-proxy"instead.
-
version:- MCP server version (local mode only) -
args:- Additional command-line arguments (local mode only) -
read-only:- The GitHub MCP server always operates in read-only mode; this field is accepted but has no effect -
github-token:- Custom GitHub token -
lockdown:- Enable lockdown mode to limit content surfaced from public repositories to items authored by users with push access (boolean, default: false) -
github-app:- GitHub App configuration for token minting; when set, mints an installation access token at workflow start that overridesgithub-tokenclient-id:- GitHub App client ID (required, e.g.,${{ vars.APP_ID }}). Useapp-id:for legacy compatibility.private-key:- GitHub App private key (required, e.g.,${{ secrets.APP_PRIVATE_KEY }})owner:- Optional installation owner (defaults to current repository owner)repositories:- Optional list of repositories to grant access to (array)permissions:- Optional extra permissions to include in the minted token for org-level API access (object)- Example:
permissions: { members: read, organization-administration: read }— required when calling org-level APIs (e.g.,orgs,userstoolsets) since the default GITHUB_TOKEN does not have org-scoped permissions
- Example:
-
min-integrity:- Minimum integrity level for MCP Gateway guard policy; controls which content the agent may act on based on author trust (none,unapproved,approved,merged) -
blocked-users:- Usernames whose content is unconditionally blocked (array or GitHub Actions expression); these users receive integrity belownoneand are always denied -
approval-labels:- Label names that elevate a content item's integrity toapprovedwhen present (array or GitHub Actions expression); does not overrideblocked-users -
trusted-users:- Usernames elevated toapprovedintegrity regardless ofauthor_association(array or GitHub Actions expression); takes precedence overmin-integritybut not overblocked-users; requiresmin-integrityto be set -
toolsets:- Enable specific GitHub toolset groups (array only)- Default toolsets (when unspecified):
context,repos,issues,pull_requests(excludesusersas GitHub Actions tokens don't support user operations) - Group aliases:
default(recommended action-friendly set),action-friendly(action-safe toolsets, excludesusers),all(everything) - Individual toolsets:
context,repos,issues,pull_requests,actions,code_security,dependabot,discussions,experiments,gists,labels,notifications,orgs,projects,secret_protection,security_advisories,stargazers,users,search - Examples:
toolsets: [default],toolsets: [default, discussions],toolsets: [repos, issues] - Recommended: Prefer
toolsets:overallowed:for better organization and reduced configuration verbosity
- Default toolsets (when unspecified):
Other Built-in Tools
-
agentic-workflows:- GitHub Agentic Workflows MCP server for workflow introspection. Providesstatus,compile,logs,audit, andcheckstools so agents can analyze run traces and improve workflows. Enable withagentic-workflows: true. -
edit:- File editing tools (required to write to files in the repository) -
web-fetch:- Web content fetching tools -
web-search:- Web search tools -
bash:- Shell command tools- Bash allowlist decision rule:
- PR-triggered workflows processing untrusted input (issue/PR body, comment text, user-provided filenames): use a narrow allowlist (e.g.
[find, cat, grep, wc, jq]). This limits blast radius if shell injection is embedded in untrusted content. scheduleorworkflow_dispatchworkflows with no untrusted input (only trusted API data or internal state):["*"]is acceptable.- Rule of thumb: If the workflow reads issue/PR bodies, comment text, or other user-provided strings, use a narrow list. Otherwise
["*"]is acceptable.
- PR-triggered workflows processing untrusted input (issue/PR body, comment text, user-provided filenames): use a narrow allowlist (e.g.
# PR-triggered workflow reading untrusted user text on: pull_request: tools: bash: [find, cat, grep, wc, jq] # Internal scheduled workflow reading only trusted/internal data on: schedule: - cron: "0 * * * *" tools: bash: ["*"] - Bash allowlist decision rule:
-
playwright:- Browser automation for visual regression, accessibility, and end-to-end testing. Usemode: cli(recommended) — no Docker, runsplaywright-cli <command>in bash,localhostreaches local servers directly.mode: mcpis deprecated (Docker-based). Pin a version withversion:and restrict network tolocal+playwright.tools: playwright: mode: cli # recommended: token-efficient CLI mode version: "0.1.11" # optional: @playwright/cli npm package version -
timeout:- Per-operation timeout in seconds for all tool and MCP calls (integer or expression). Defaults vary by engine (Claude: 60 s, Codex: 120 s). -
startup-timeout:- Timeout in seconds for MCP server initialization (integer or expression, default: 120). -
cli-proxy:- Mount each user-facing MCP server as a standalone CLI tool onPATH(boolean, default:false). When enabled, the agent can call MCP servers via shell (e.g.github issue_read --method get ...).
Custom MCP Tools
Stdio MCP servers must be Docker-based (use container: + entrypoint:). For Node/Python servers already installed on the runner, use HTTP transport instead:
# Stdio (Docker-based)
mcp-servers:
my-custom-tool:
container: "ghcr.io/my-org/my-tool:latest"
entrypoint: "my-tool"
allowed:
- custom_function_1
- custom_function_2
# HTTP (for Node/Python servers running on the runner)
mcp-servers:
my-node-tool:
type: http
url: "http://localhost:8765/mcp"
HTTP MCP servers are also supported with optional upstream authentication:
mcp-servers:
my-server:
type: http
url: "https://myserver.example.com/mcp"
headers:
Authorization: "Bearer ${{ secrets.API_KEY }}" # Optional: custom headers
my-oidc-server:
type: http
url: "https://myserver.example.com/mcp"
auth:
type: github-oidc # GitHub Actions OIDC token authentication
audience: "https://myserver.example.com" # Optional: custom OIDC audience
auth.type: github-oidc uses GitHub Actions OIDC tokens for secure server-to-server authentication without static credentials. The audience field defaults to the server URL when omitted.
Engine Network Permissions
Control network access via the top-level network: field (defaults to network: defaults — basic infrastructure only). For workflows that build, test, or install packages, always add the language ecosystem alongside defaults:
network:
allowed:
- defaults # Basic infrastructure (CAs, Ubuntu verification, JSON schema)
- node # Node.js / npm ecosystem
- "api.custom.com" # Custom domain
blocked:
- "*.ads.com" # Block domain patterns
Full reference: valid ecosystem identifiers, invalid shorthands, wildcard/protocol rules, and per-language inference live in network.md. Do not restate the ecosystem table here.
Imports Field
Import shared components using the imports: field in frontmatter:
---
on: issues
engine: copilot
imports:
- copilot-setup-steps.yml # Import setup steps from copilot-setup-steps.yml
- shared/security-notice.md
- shared/tool-setup.md
- shared/mcp/tavily.md
---
Object form with inputs — Use path:/uses: + with:/inputs: to pass values to shared workflows that define an import-schema::
imports:
- path: shared/tool-setup.md
with:
environment: staging
max-issues: 3
- uses: shared/security-notice.md # 'uses' is an alias for 'path'
path/uses and with/inputs are the only valid keys on an import entry. To supply environment variables or a checkout ref, set top-level env:/checkout: frontmatter inside the imported file itself — those are merged into the importing workflow (see the merge list below), not configured per import entry.
Conditional imports: entries are not supported. For experiment-specific prompt variants, keep the import unconditional and gate a {{#runtime-import? ...}} block (optional form) in the workflow body instead. The optional form is not promoted to unconditional lock-file macros, so the content is only injected when the condition is true at runtime.
Inside the imported workflow, access values via ${{ github.aw.import-inputs.<name> }}.
Import File Structure
Import files are in .github/workflows/shared/ and can contain:
- Tool configurations
- Safe-outputs configurations
- Text content
- Mixed frontmatter + content
The following frontmatter fields in imported files are merged into the importing workflow:
tools:- Merged with the importing workflow's toolssafe-outputs:- Merged with safe-output configurationenv:- Environment variables merged; conflicts between two imports defining the same key are compilation errors (remove the duplicate or move it to the main workflow to override)checkout:- Checkout configurations appended (main workflow's checkouts take precedence)github-app:- Top-level GitHub App credentials (first-wins across imports)on.github-app:- Activation GitHub App credentials (first-wins across imports)steps:- Steps appended in import orderpre-agent-steps:- Steps appended in import orderpost-steps:- Steps appended in import orderjobs.<job-id>.setup-stepsandjobs.<job-id>.pre-steps- Merged per job with imported steps first, then main workflow steps. Execution order issetup-stepsbeforepre-steps.runtimes:,network:,permissions:,services:,cache:,features:,mcp-servers:
Example import file:
---
tools:
github:
allowed: [get_repository, list_commits]
safe-outputs:
create-issue:
labels: [automation]
env:
MY_VAR: "shared-value"
checkout:
fetch-depth: 0
---
Additional instructions for the coding agent.
Special Import: copilot-setup-steps.yml
The copilot-setup-steps.yml file receives special handling when imported. Instead of importing the entire job structure, only the steps from the copilot-setup-steps job are extracted and inserted at the start of your workflow's agent job.
Key behaviors:
- Only the steps array is imported (job metadata like
runs-on,permissionsis ignored) - Imported steps are placed at the start of the agent job (before all other steps)
- Other imported steps are placed after copilot-setup-steps but before main frontmatter steps
- Main frontmatter steps come last
- Final order: copilot-setup-steps → other imported steps → main frontmatter steps
- Supports both
.ymland.yamlextensions - Enables clean reuse of common setup configurations across workflows
Example:
---
on: issue_comment
engine: copilot
imports:
- copilot-setup-steps.yml
- shared/common-tools.md
steps:
- name: Custom environment setup
run: echo "Main frontmatter step runs last"
---
In the compiled workflow, the order is: copilot-setup-steps → imported steps from shared/common-tools.md → main frontmatter steps.
Permission Patterns
IMPORTANT: Agentic workflows MUST NOT include write permissions (issues: write, pull-requests: write, contents: write). Safe-outputs provide these via separate secured jobs. Granting writes to the main AI job causes a compilation error.
Read-Only Pattern
permissions:
contents: read
metadata: read
Output Processing Pattern (Recommended)
permissions:
contents: read # Main job minimal permissions
actions: read
safe-outputs:
create-issue: # Automatic issue creation
add-comment: # Automatic comment creation
create-pull-request: # Automatic PR creation
Key Benefits of Safe-Outputs:
- Main job runs with minimal permissions
- Write operations handled by dedicated jobs
- Safe-outputs jobs auto-receive required permissions
- Clear audit trail between AI processing and GitHub API