fix: local .github/agents imports now use snippet-style runtime-import path for Claude/Codex#19614
fix: local .github/agents imports now use snippet-style runtime-import path for Claude/Codex#19614
Conversation
…h for Claude/Codex Local agent file imports (same repo) no longer trigger the AGENT_CONTENT+PROMPT_TEXT shell variable path in Claude/Codex engines. They now use the runtime-import macro (snippet-style) which is robust and avoids the AWF variable inheritance bug. Also fix awk command in both engines: it was extracting frontmatter instead of the body. Extract shared AgentFileBodyExtractCmd helper to avoid duplication between engines. Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Updates local .github/agents/*.md imports to follow the same runtime-import (“snippet-style”) path as .github/snippets, avoiding the legacy AGENT_CONTENT/PROMPT_TEXT assembly and unnecessary remote .github merge steps for same-repo agent files.
Changes:
- Adjust import BFS logic so local agent imports populate
ImportPaths(runtime-import macros) rather thanAgentFile/AgentImportSpec, while preserving the “one agent per workflow” rule for both local and remote. - Add a shared
AgentFileBodyExtractCmdhelper (with corrected awk) and update Claude/Codex engines to use it whenAgentFileis set (remote-agent path). - Update tests and compiled lockfiles to reflect that local agent imports no longer set
AgentFile/AgentImportSpecand no longer emit the remote.githubmerge step.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
pkg/parser/import_bfs.go |
Treats local agent imports like snippet imports (runtime-import path) and introduces firstAgentPath for duplicate-agent enforcement. |
pkg/parser/import_field_extractor.go |
Documents that agentFile/agentImportSpec are remote-only and adds firstAgentPath tracking field. |
pkg/parser/agent_import_integration_test.go |
Updates expectations: local agent import leaves AgentFile/AgentImportSpec empty and uses ImportPaths. |
pkg/workflow/engine_helpers.go |
Adds AgentFileBodyExtractCmd helper and new awk program for stripping YAML frontmatter. |
pkg/workflow/claude_engine.go |
Uses AgentFileBodyExtractCmd for agent-body extraction when AgentFile is set. |
pkg/workflow/codex_engine.go |
Uses AgentFileBodyExtractCmd for agent-body extraction when AgentFile is set. |
pkg/workflow/engine_agent_import_test.go |
Clarifies in comments that AgentFile is remote-only; local agent imports use runtime-import macros. |
pkg/workflow/inline_imports_test.go |
Updates behavior: inlined-imports: true + local agent import now succeeds. |
.github/workflows/technical-doc-writer.lock.yml |
Removes remote .github merge step emitted previously for local agent import. |
.github/workflows/hourly-ci-cleaner.lock.yml |
Removes remote .github merge step emitted previously for local agent import. |
.github/workflows/glossary-maintainer.lock.yml |
Removes remote .github merge step emitted previously for local agent import. |
Comments suppressed due to low confidence (1)
pkg/parser/import_bfs.go:195
- The
.githubrelative-path extraction usesstrings.Index(item.fullPath, "/.github/"), which will not match Windows paths and can produce an absolute filesystem path inimportRelPath(breaking runtime-import macros and remote agent handling). Normalizeitem.fullPathwithfilepath.ToSlash(or useisCustomAgentFile+ a shared "relative-to-.github" helper) before slicing.
// Extract relative path from repository root (from .github/ onwards)
// This ensures the path works at runtime with $GITHUB_WORKSPACE
var importRelPath string
if idx := strings.Index(item.fullPath, "/.github/"); idx >= 0 {
importRelPath = item.fullPath[idx+1:] // +1 to skip the leading slash
} else {
importRelPath = item.fullPath
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
| // Check if this is a custom agent file (any markdown file under .github/agents) | ||
| isAgentFile := strings.Contains(item.fullPath, "/.github/agents/") && strings.HasSuffix(strings.ToLower(item.fullPath), ".md") | ||
| if isAgentFile { |
There was a problem hiding this comment.
item.fullPath is an OS-native path (uses \ on Windows). The agent-file detection strings.Contains(item.fullPath, "/.github/agents/") will fail on Windows and cause agent imports to be treated as regular imports. Consider reusing the existing isCustomAgentFile() helper (it normalizes via filepath.ToSlash) or normalize item.fullPath before this check.
This issue also appears on line 188 of the same file.
| // Build the agent command - prepend custom agent file content if specified (via imports) | ||
| // Note: AgentFile is only set for remote agent imports. Local agent imports use the | ||
| // runtime-import macro path (snippet-style) and do not set AgentFile. | ||
| // The AGENT_CONTENT approach reads the file at runtime from $GITHUB_WORKSPACE; it is only | ||
| // appropriate for remote imports where the file has been checked out separately. | ||
| var promptSetup string | ||
| var promptCommand string | ||
| if workflowData.AgentFile != "" { | ||
| agentPath := ResolveAgentFilePath(workflowData.AgentFile) | ||
| claudeLog.Printf("Using custom agent file: %s", workflowData.AgentFile) | ||
| // Extract markdown body from custom agent file and prepend to prompt | ||
| // Extract markdown body from custom agent file (skip YAML frontmatter) and prepend to prompt. | ||
| promptSetup = fmt.Sprintf(`# Extract markdown body from custom agent file (skip frontmatter) | ||
| AGENT_CONTENT="$(awk 'BEGIN{skip=1} /^---$/{if(skip){skip=0;next}else{skip=1;next}} !skip' %s)" | ||
| %s | ||
| # Combine agent content with prompt | ||
| PROMPT_TEXT="$(printf '%%s\n\n%%s' "$AGENT_CONTENT" "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)")"`, agentPath) | ||
| PROMPT_TEXT="$(printf '%%s\n\n%%s' "$AGENT_CONTENT" "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)")"`, | ||
| AgentFileBodyExtractCmd(agentPath)) | ||
| promptCommand = "\"$PROMPT_TEXT\"" |
There was a problem hiding this comment.
In AWF mode, promptSetup runs on the host before invoking awf ... -- <container command> (see BuildAWFCommand), but it currently sets AGENT_CONTENT/PROMPT_TEXT as unexported shell variables. Because AWF uses --env-all, only exported environment variables propagate into the container, so the Claude prompt argument "$PROMPT_TEXT" will be empty when AgentFile is set. Export these variables (or move the agent-body extraction + prompt assembly into the container command) so remote agent imports work under AWF.
See below for a potential fix:
export AGENT_CONTENT
# Combine agent content with prompt
PROMPT_TEXT="$(printf '%%s\n\n%%s' "$AGENT_CONTENT" "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)")"
export PROMPT_TEXT`,
|
@copilot merge main, recompile |
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Done — merged main and recompiled all 165 workflows (913e2d8). Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
|
@copilot compare copilot/claude/copilot behavior |
Here's how the three engines now compare when handling
Key change in this PR: Before, all agent imports (local and remote) used the The remaining known gap is remote agent imports under AWF for Claude/Codex (the reviewer's export comment). That's a separate issue from the one filed here. |
.github/agents/imports triggerAGENT_CONTENT+PROMPT_TEXTpath in Claude/Codex engines andmerge_remote_agent_github_foldersteppkg/parser/import_bfs.go: only setagentFile/agentImportSpecfor remote agent imports (not local); addedfirstAgentPathfor one-agent-per-workflow restrictionpkg/workflow/engine_helpers.go: extractedAgentFileBodyExtractCmdhelper with corrected awk that extracts markdown body (not frontmatter)pkg/workflow/claude_engine.goto useAgentFileBodyExtractCmdpkg/workflow/codex_engine.go(both AWF and non-AWF paths) to useAgentFileBodyExtractCmdpkg/parser/agent_import_integration_test.go: local imports should have emptyAgentFilepkg/workflow/inline_imports_test.go: local agent import +inlined-imports: trueshould succeed (test renamed)Original prompt
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.