Ground your GitHub Copilot agent in a local clone instead of letting it guess

A long debugging session lost to GitHub Agentic Workflows. Not because the tool was broken, but because the agent kept inventing how it worked. The model was not being unreasonable. It was being asked an impossible question.

Ground your GitHub Copilot agent in a local clone instead of letting it guess
Photo by Jaredd Craig / Unsplash

A long debugging session lost to GitHub Agentic Workflows. Not because the tool was broken, but because the agent kept inventing how it worked. The model was not being unreasonable. It was being asked an impossible question.

github/gh-aw renamed a core safe output from create-agent-task to create-agent-session in version 0.4.0. There are perhaps a few dozen real-world examples of the tool in public. A significant portion of what exists online describes the previous shape. An LLM asked about a topic with thin, contradictory, recently changed training data will not say "I don't know" — it will interpolate, and it will do so fluently.

The remedy is straightforward: stop asking it to recall, and give it something to read.


The technique

cd ~/src
git clone https://github.com/github/gh-aw.git

Then in VS Code: File → Add Folder to Workspace… → pick the clone.

Then, in your Copilot session:

I've added the github/gh-aw repo to this workspace at ~/src/gh-aw. That's the actual implementation and documentation for GitHub Agentic Workflows. When you're unsure how something works, read the source there instead of assuming.

That is the entire technique. The agent now has grep access to ground truth.

I use this regularly — for debugging VS Code extensions, for comparing a framework's actual behaviour against its documented behaviour, and for any dependency that moves faster than model training cycles. It consumes a considerable number of tokens, and it is highly effective.


Why this is preferable to the alternatives

Source Strength Limitation
Model memory Fast and free Often stale on fast-moving projects, and can be confidently wrong
Generic web search Reasonably current Finds blog posts, old documentation and partial examples; usually not the actual implementation
GitHub MCP code search Searches the source repository directly, so it is much better grounded than generic web search Slower than local grep and may consume more tokens
Local clone Exact code you depend on; greppable, cite-able and testable Requires setup and can be token-intensive if the agent reads broadly

Documentation describes intent. Source code describes behaviour. When the two disagree — and in a fast-moving repository they will — you want your agent reading the artefact that actually runs. GitHub MCP code search is a useful alternative when you do not have a local clone: it searches the repository directly, so it is better grounded than generic web search, but it is slower than local grep and may consume more tokens.


A worked example

While researching the agent-session problem, I compared gh-aw's documentation against its code. Two discrepancies emerged immediately.

Discrepancy one — cross-repository support.

The safe-outputs specification says:

Type: create_agent_session — Cross-Repository Support: No (same repository only)

The reference doc, and the actual Go source, say otherwise:

// pkg/workflow/create_agent_session.go
type CreateAgentSessionConfig struct {
    BaseSafeOutputConfig `yaml:",inline"`
    Base                 string   `yaml:"base,omitempty"`
    TargetRepoSlug       string   `yaml:"target-repo,omitempty"`   // ← cross-repo
    AllowedRepos         []string `yaml:"allowed-repos,omitempty"` // ← cross-repo
}

An agent relying on the specification document would have reported that cross-repository use was impossible. The struct definition settles the question immediately.

Discrepancy two — the API version header.

GitHub's public docs show:

-H "X-GitHub-Api-Version: 2022-11-28"

gh-aw's implementation sends:

// actions/setup/js/create_agent_session.cjs
const response = await githubClient.request("POST /agents/repos/{owner}/{repo}/tasks", {
  owner: repoParts.owner,
  repo: repoParts.repo,
  prompt: taskDescription,
  base_ref: baseBranch,
  headers: { "X-GitHub-Api-Version": "2026-03-10" },
});

If you were debugging a raw curl request against a preview API, that difference is decisive — and no amount of careful prompting would have surfaced it.

The discrepancy that mattered most. The token resolution chain is not documented in prose anywhere, but the source comment sets it out in full:

/**
 * Token precedence:
 *   1. config["github-token"] — per-handler PAT configured in the workflow frontmatter
 *   2. GH_AW_AGENT_SESSION_TOKEN — agent token injected by the compiler
 *      (evaluates to: GH_AW_AGENT_TOKEN || GH_AW_GITHUB_TOKEN || GITHUB_TOKEN)
 *   3. global github — step-level token (fallback)
 */

That is the answer: the silent fallback to GITHUB_TOKEN, and the precise reason a correctly written workflow returns 404 with no useful error message. A targeted grep resolved what a long prompting session could not.


Bake it into your instructions

The clone only helps if the agent actually reaches for it. Make that automatic:

<!-- .github/copilot-instructions.md -->

## Grounding sources

The `github/gh-aw` repository is available in this workspace at `../gh-aw`.
It contains the implementation and documentation for GitHub Agentic Workflows.

- When you hit a snag, or are unsure how agentic workflows behave, **read the
  implementation** rather than making assumptions.
- Prefer, in order: `pkg/workflow/**` (Go compiler) →
  `actions/setup/js/**` (runtime handlers) → `docs/src/content/docs/**` →
  `CHANGELOG.md`.
- When docs and code disagree, **the code wins** — and say so in your answer.
- Cite file paths and line numbers for any claim about behaviour.
- Always run `gh aw compile` before committing workflow changes.

The citation requirement is more valuable than it first appears. It serves two purposes: it gives you a quick way to verify a claim, and it makes fabrication considerably harder for the model. An answer citing pkg/workflow/create_agent_session.go:12 is much easier to check. An answer without a citation cannot be checked directly.


The complementary half: GitHub MCP for what a clone cannot provide

A clone gives you code. It does not give you discussion. Issues, pull requests, discussions, and release notes — the layer that tells you whether something is a known problem — live on GitHub.

Enable the GitHub MCP server and your agent can query that too:

  • "Search gh-aw issues for create-agent-session 404"
  • "What changed in gh-aw between the version I have and main?"
  • "Are there open PRs touching the agent session token chain?"

This is where the undocumented reality surfaces: a maintainer explaining in an issue comment why something behaves as it does, a pull request that changed semantics recently, or a discussion thread describing the workaround most people use.

Choosing between a clone and MCP

Question Preferred source
"How does X actually work?" Clone — read the source. If unavailable, GitHub MCP code search
"What are the valid config fields?" Clone — read the struct/schema. If unavailable, GitHub MCP code search
"Why does this fail?" Clone first, then MCP for known issues
"Is this a known bug?" MCP — search issues
"What changed recently?" Clone CHANGELOG.md + git log, then MCP for PRs
"How do others use this?" MCP — code search across GitHub
"Is a fix coming?" MCP — open PRs and milestones

You can skip the clone and point custom instructions at the repository URL, letting the agent search the repository through GitHub MCP. This is still much better grounded than generic web search, because the agent is searching the actual source repository. It is slower than a local clone, requires more remote calls, and may consume more tokens. I clone by default and use MCP for the discussion layer and for repository code search when cloning is not practical.


Practical notes

Match the version you actually run. A clone of main describes the future. If you're on a release, check out the matching tag:

git -C ~/src/gh-aw fetch --tags
git -C ~/src/gh-aw checkout v0.4.0

Otherwise you risk implementing a feature that is not yet present in your version, which is a particularly frustrating class of bug.

Refresh it deliberately. Run git pull before a debugging session, and note the SHA you grounded against so that it remains clear later what "the code says" referred to.

Scope the search. Left unbounded, an agent will search across a repository of ten thousand files. Direct it:

Look only in pkg/workflow/ and actions/setup/js/ for how the token is resolved.

Budget for the cost. This is not inexpensive; you are paying tokens to read someone else's codebase. It remains considerably cheaper than a long debugging session based on an invented diagnosis.

Treat fetched content as untrusted input. Issue bodies, pull request descriptions, and README files can be influenced by third parties in public repositories. If your agent reads content that begins issuing it instructions, that is prompt injection rather than documentation. Worth being aware of even if you never encounter it.


When it's worth it

Grounding is worthwhile when:

  • The dependency changed recently
  • Public examples are scarce
  • Behaviour is subtle — auth chains, token precedence, compilation order
  • Docs and reality have visibly diverged
  • You're debugging something that "should work"

Skip it for stable, well-documented libraries with many public examples. There is no need to clone React to establish what useEffect does.

The heuristic I apply: if the model sounds confident but the result does not work, it is guessing. That is the point at which to clone.


Conclusion

A great deal of effort goes into prompt engineering — better phrasing, better structure, better framing. That effort is worthwhile, but a larger improvement is available before any of it: give the model the actual source of truth and instruct it to read.

Most agent failures I investigate are not reasoning failures. They are retrieval failures. The model reasoned correctly over information that was wrong.

You would not ask a new team member to implement against a library from memory. You would point them at the repository. Apply the same approach to your agent.

git clone <the-thing-you-depend-on>
# File → Add Folder to Workspace

Then instruct it to read.


Quick-start checklist

  • ✅ Clone the dependency repo locally
  • ✅ Check out the tag matching your installed version
  • ✅ Add it to your VS Code workspace
  • ✅ Add a "grounding sources" section to .github/copilot-instructions.md
  • ✅ Include "when in doubt, read the implementation" as an explicit instruction
  • ✅ Require file:line citations in answers
  • ✅ Enable the GitHub MCP server for issues, PRs, and discussions
  • ✅ Refresh the clone before serious debugging sessions