Copilot Integration

Commit trailers, Workspace hooks, and the pragmatic limits of a closed client.

Why This Exists

GitHub Copilot is the AI agent with the largest deployed footprint and the most constrained integration surface. It does not expose an MCP client. It does not read a repo-level instruction file the way CLAUDE.md, .cursorrules, and GEMINI.md work. It produces edits and PRs through GitHub's infrastructure, not through a terminal the user controls.

Pretending otherwise would be dishonest. Aura's Copilot integration is the most pragmatic of the four — it meets Copilot where it actually is and accepts that some coordination primitives will land on the server side rather than in the client.

You cannot teach Copilot to call MCP tools. You can, however, intercept the PRs it produces, extract intent from its commits, and fold them into the Sentinel.

That is what this integration does.

How It Works

Copilot integration operates in two places:

  1. Commit-message trailers. Copilot-authored commits carry structured metadata in their trailers (the Key: value lines at the bottom of the message). Aura's server-side hook parses these trailers and reconstructs intent, file scope, and agent identity.
  2. GitHub Copilot Workspace webhooks. When Copilot Workspace opens or updates a PR, GitHub fires a webhook. Aura's cloud receiver processes the webhook, runs aura_pr_review against the diff, and posts the findings as a PR comment. If Sentinel detects zone or collision issues, those are surfaced on the PR.

The client-side story is thin because it has to be. The server-side story is where the integration earns its keep.

Commit trailer format

Copilot's default commit messages include structured metadata. Aura expects, at minimum:

Refactor authentication to support OAuth

Copilot-Agent: github-copilot
Copilot-Session: cw_7f3a2b
Copilot-Intent: Add OAuth 2.1 PKCE flow to authenticate()
Copilot-Files: src/auth/user_service.py, src/auth/oauth.py

The trailers Aura specifically looks for:

| Trailer | Purpose | | --- | --- | | Copilot-Agent | Identifies the authoring agent — always github-copilot for Copilot, but forward-compatible with other trailer-producing agents. | | Copilot-Session | Session id used for Sentinel correlation. | | Copilot-Intent | One-sentence intent, analogous to aura_log_intent content. | | Copilot-Files | Scope hint, used for zone intersection. | | Copilot-Branch | Optional, branch name at author time. |

If Copilot does not emit these trailers by default — and on some configurations it does not — Aura provides a GitHub Action that inserts them before the commit lands on the default branch:

# .github/workflows/aura-copilot-trailers.yml
name: Aura Copilot Trailers
on:
  pull_request:
    types: [opened, synchronize]
jobs:
  annotate:
    if: github.actor == 'github-copilot[bot]'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: aura-vcs/copilot-trailer-action@v1
        with:
          aura-api-key: ${{ secrets.AURA_API_KEY }}

The action reads the PR title and body, derives the required trailers, and amends the Copilot commits with a server-side git commit --amend on a bot branch.

Webhook flow

The Aura cloud receiver handles three Copilot-related events:

  1. pull_request.opened — fetches the diff, runs aura pr-review --base main, posts review comments.
  2. pull_request.synchronize — re-runs the review on the incremental diff.
  3. pull_request.review_requested (when the reviewer is the Aura bot) — full semantic review, posts a single summary comment.

The review comment uses the Sentinel event vocabulary you have already seen:

## Aura PR Review

**Intent parsed:** Add OAuth 2.1 PKCE flow to authenticate()
**Files touched:** 2 | **Logic nodes changed:** 6

### Findings
- [COLLISION] `UserService.authenticate` was modified by `cursor-def456`
  on branch `fix/timing-attack` 40 minutes ago. Consider coordinating
  before merge.
- [ZONE] `src/auth/oauth.py` overlaps an active BLOCKED zone held by
  `claude-7f3a2b`. Merge will be blocked by the server-side hook.
- [INTENT OK] AST diff matches stated intent.

### Suggested next steps
- Resolve collision via `aura_sentinel_send` from a Claude/Cursor session.
- Release or extend the active zone before merging.

The comment gives humans a specific remediation path without requiring Copilot itself to understand Sentinel.

Examples

A collision surfaced on a Copilot PR

Copilot opens a PR that touches UserService.authenticate. Claude is in the middle of refactoring the same function from a local Claude Code session.

[GitHub] pull_request.opened → Aura webhook
[Aura]   parses trailers, runs pr-review
[Aura]   detects collision against claude-7f3a2b's active session
[Aura]   posts PR comment with [COLLISION] finding
[Aura]   sends Sentinel event to claude-7f3a2b:
           kind="collision"
           peer={kind:"github-copilot", session:"cw_..."}
[Claude] sees event on next tool call, notifies user via assistant message

The human reviewing the Copilot PR sees the collision immediately. The Claude session knows about it without polling. The fix might be a conversation, a rebase, or a merge of the two changes — but all three parties have the context to make the call.

Merging a Copilot PR through the server-side hook

Aura's GitHub App installs a merge gate:

branch_protection:
  required_status_checks:
    - "aura/semantic-review"
    - "aura/zone-check"
    - "aura/intent-verification"

aura/zone-check fails if any file in the PR overlaps an active BLOCKED zone. This is the enforcement mechanism for Copilot — since we cannot teach Copilot to respect zones at edit time, we teach GitHub to respect them at merge time.

Opting a PR out of Aura review

For experimental branches or non-semantic changes (docs, workflow configs), skip review with a trailer or label:

Aura-Skip-Review: docs-only

Or add the aura:skip label to the PR. The webhook receiver short-circuits and posts a single-line comment noting the skip.

Configuration

The Copilot-side config lives in .aura/config.toml like the others, but with fewer knobs:

[copilot]
webhook_enabled = true
require_trailers = true
auto_amend_trailers = true  # via GitHub Action
merge_gate = "block-on-zone"  # "warn" | "block-on-zone" | "block-any-finding"

[copilot.review]
run_on_open = true
run_on_synchronize = true
comment_style = "summary"   # "summary" | "per-finding"

merge_gate is the key setting. Teams starting out should use warn. Teams with established Sentinel hygiene should use block-on-zone — merge is only blocked when Copilot tries to cross an active zone. block-any-finding is strict and should only be used by teams with a very clear sense of their finding noise floor.

Feature Matrix

| Feature | Copilot Support | Notes | | --- | --- | --- | | Client-side MCP | No | Copilot does not expose MCP in PR mode | | Instruction file | No | No .copilotrules equivalent exists yet | | Pre-commit hook | Server-side only | Runs in GitHub Action / Aura webhook | | Intent logging | Via commit trailers | Auto-amended by Aura action | | Collision detection | Server-side | Posted as PR comment + Sentinel event | | Zone claims | Server-side | Enforced at merge gate | | Sentinel inbox | Read-only (humans can see Copilot attribution) | Copilot cannot reply | | Knowledge base | Not consulted | Copilot cannot read it | | Plan tools | No | Incompatible with Copilot's workflow |

The gaps are real. Copilot cannot query the knowledge base before writing, cannot reply to inbox messages, and cannot proactively claim zones. What Aura does instead is ensure that when Copilot's output reaches the repo, it gets audited, scoped, and cross-checked against everything other agents are doing.

Limitations

This section is plain about the things the integration does not do.

  • No pre-edit coordination. Copilot begins producing a diff before Aura sees it. All coordination happens after the PR opens.
  • No agent-to-agent conversation. Copilot cannot read or write Sentinel messages. Humans carry messages across the gap.
  • Intent is inferred, not declared. Copilot does not call aura_log_intent. Aura reconstructs intent from the PR title, body, and commit messages, then validates it against the AST diff. When Copilot writes thin PR descriptions, intent verification is weaker.
  • Zone claims are merge-time, not edit-time. A Copilot PR that crosses a zone will be flagged and blocked at merge, but the Copilot agent will not receive a warning during generation.

These are not bugs in Aura. They are properties of a closed client. The trade is worth it because most teams cannot simply stop using Copilot, and a partially-coordinated Copilot is still vastly better than an uncoordinated one.

Perfect is the enemy of shipping. The Copilot integration is deliberately pragmatic. The other integrations are what close the loop.

Forward Outlook

GitHub has been signaling more openness on Copilot Workspace's client surface. If and when a Copilot MCP client ships, the integration becomes symmetric with Claude, Cursor, and Gemini. Aura's server code is already shaped to accept client-side events when they arrive; only the webhook path exercises today.

Until then, commit trailers and PR webhooks are the seam we have. They are narrow, but they are enough.

Recommendations For Mixed Teams

Teams running Copilot alongside Claude, Cursor, or Gemini have converged on a few practical guidelines.

Use Copilot for well-scoped PRs. Copilot's strength is producing small, focused changes from a prompt or a Workspace spec. Feed it tasks with narrow blast radius and clear acceptance criteria. It struggles with wide refactors and should not be given them; those belong to Claude or Gemini.

Let the other agents hold the zones. Because Copilot cannot claim zones, the other agents in the fleet should be the ones doing claim-shaped work. Copilot operates in the interstitial space between claimed regions.

Treat Copilot PRs as the coordination surface. Unlike Claude or Cursor, where coordination happens pre-edit, Copilot coordination happens in the PR comments. Humans should treat Aura's PR comments as first-class — not as noise to be dismissed.

Escalate fast on blocked zones. A Copilot PR that crosses a blocked zone is going to happen eventually. When it does, the right response is usually to close the PR, wait for the zone to release, and re-run Copilot. Merging over a block — even when technically possible — trains the team to ignore zones.

Audit the trailer compliance. If the trailer action is not running or not emitting the right fields, the Sentinel side of Copilot integration degrades silently. aura doctor --copilot checks recent PRs for trailer compliance and flags misses.

Privacy And Enterprise Considerations

A Copilot integration touches your code through three party boundaries: GitHub (hosting the repo), Copilot (generating edits), and the Aura cloud (running server-side review). Teams on strict data residency policies should be aware of this chain.

Aura supports a self-hosted mode where the webhook receiver and the review engine run inside the customer's infrastructure. Copilot's side of the chain is controlled by GitHub's Copilot Enterprise settings, which is out of Aura's scope. The combination — self-hosted Aura, enterprise Copilot — is what most regulated customers end up deploying.

The commit trailers themselves contain no sensitive data beyond what already exists in the PR (intent text, file paths, session ids). They do not include code or diffs.

The Closed-Client Future

The broader trend in the space is toward more-open client surfaces. MCP has seen uptake across Anthropic, Google, and various independent clients; GitHub has been publishing more of Copilot's internals; the OpenAI platform is expanding its tool-use APIs. It is plausible that within a year, the Copilot integration will look more like the Claude one than it does today.

Aura is built to absorb that change. The server-side review pipeline is stable; adding a client-side MCP path when GitHub offers one is a small change. The Sentinel tool vocabulary is already agent-agnostic; it will not need to be reshaped for Copilot-as-MCP-client.

Until that day, commit trailers and PR webhooks are what we have, and they are enough to get most of the value.

See Also