Running GitHub Copilot SDK Inside GitHub Actions

If you’ve been using GitHub Copilot, you already know how powerful it can be. Lets look at running the GitHub Copilot SDK inside GitHub Actions.

Dropping it into a GitHub Actions workflow means it can work right inside your CI/CD pipeline. I will show how-to with a working example: a Pull Request Review Assistant that runs in GitHub Actions, uses the Copilot SDK, and applies a predefined skill so its output is consistent.

What Is the GitHub Copilot SDK?

The GitHub Copilot SDK is a programmable interface to the Copilot agent runtime used by the Copilot CLI. It lets you embed Copilot’s agent behavior directly into:

  • Applications
  • Automation workflows
  • Internal tools
  • CI/CD pipelines
  • Developer portals

Under the hood:

  • The SDK talks to the Copilot CLI in server mode over JSON-RPC.
  • The CLI handles authentication and communication with Copilot services.
  • The SDK manages the CLI process lifecycle for you.

So instead of calling a single model endpoint, you are using the same agent runtime that Copilot itself uses, now from your own code

The repository is here:
https://github.com/github/copilot-sdk

It supports multiple languages (Python, TypeScript, Go, .NET) and is currently in Technical Preview.

Why use GitHub Copilot SDK in GitHub Actions?

You could call an LLM API directly from a workflow, but the SDK changes the shape of the problem.

You reuse the Copilot agent runtime.

You do not have to build your own:

  • Orchestration loop
  • Tool invocation wiring
  • Context management

The SDK and CLI already implement this behaviour for development workflows.

You standardise AI in the pipeline

Running Copilot via the SDK inside Actions means you can fix:

  • The model
  • The prompt structure
  • The skill definitions
  • The output format
  • The enforcement rules on every PR

In a short summary: Direct LLM API calls mean reinventing agent loops, context handling, and tool wiring. The SDK reuses Copilot’s battle-tested runtime, letting you standardise prompts, models (e.g., claude-sonnet-4.5), skills, and output formats across every PR.

GitHub Actions example – What we’re building

The example in this blog post is a Pull Request Review Assistant that:

  • Triggers on pull requests
  • Fetches the PR metadata and diff
  • Sends that context to a Copilot SDK session
  • Asks for:
    • A complexity score
    • A risk assessment
    • Automated review comments
    • Recommendations
  • Posts a structured comment back to the PR

The goal is not to replicate Copilot Code Review, but to show that calling the Copilot SDK programmatically from Actions is straightforward and reusable.

Screenshot of GitHub Action example with Copilot SDK

Architecture at a glance

At runtime, the pieces line up like this:

  1. GitHub Actions runner
    • Triggers on a PR event
    • Installs Node.js
    • Installs the Copilot CLI
    • Installs Python dependencies
  2. Python script
    • Fetches PR metadata and diffs via the GitHub API
    • Starts a Copilot SDK client
    • Creates a session (with skills)
    • Sends a structured prompt and waits for a response
  3. Copilot SDK
    • Launches or connects to the Copilot CLI in server mode
    • Manages the request and session lifecycle
  4. Copilot CLI
    • Authenticates using a token
    • Communicates with Copilot services
  5. Copilot services
    • Process the prompt and context
    • Return a structured response

The key dependency is the CLI. If there is no Copilot CLI runtime, the SDK cannot create a session.

Architecture of GitHub Action using GitHub Copilot SDK & PR summary with Python

Prerequisites

You will need:

  • A GitHub repository with Actions enabled.
  • An active GitHub Copilot subscription with API access.
  • A fine-grained GitHub personal access token with Copilot read permissions.
  • Python 3.13+ available on the runner.

Step 1: Create the Copilot token

  1. In GitHub, go to Settings → Developer settings → Personal access tokens → Fine-grained tokens.
  2. Create a new token with:
    • Copilot: Read permission
  3. Copy and store the token value; you will use it as a repo secret.

Step 2: Add repository secrets

In your repository:

  1. Open Settings → Secrets and variables → Actions.
  2. Add the following secrets:
    • COPILOT_GITHUB_TOKEN: your fine-grained Copilot token.

Create the workflow

Create .github/workflows/copilot-review.yml:

name: PR Review Assistant

on:
  pull_request:
    types: [opened, synchronize, reopened]

jobs:
  review:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      pull-requests: write
      
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          fetch-depth: 0  # Full history for better analysis
          
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '22'
          
      - name: Install GitHub Copilot CLI
        run: npm i -g @github/copilot
          
      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.13'
          
      - name: Install dependencies
        run: |
          pip install github-copilot-sdk PyGithub
          
      - name: Run PR Review
        env:
          COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          PR_NUMBER: ${{ github.event.pull_request.number }}
          REPOSITORY: ${{ github.repository }}
        run: |
          python pr_reviewer.py

Why Install Both CLI and SDK?

  • The SDK is the Python library your script imports, for example from copilot import CopilotClient.
  • The CLI is the local runtime the SDK connects to over JSON-RPC.

During a run:

  • The SDK starts or attaches to the CLI process.
  • The CLI authenticates using the token and talks to Copilot services.
  • The SDK manages sessions and responses.

Because of this, the workflow must:

  • Install Node.js
  • Install @github/copilot
  • Expose COPILOT_GITHUB_TOKEN (or another supported token) to the job

If the CLI is missing, session creation will fail.

The PR assistant (Python)

The implementation below:

  • Fetches PR metadata and diffs
  • Starts a Copilot SDK client
  • Creates a session (with an optional skill)
  • Requests a structured analysis
  • Posts feedback back to the PR

copilot_review.py

import asyncio
import os
from github import Github
from copilot import CopilotClient


async def main():
    copilot_token = os.getenv("COPILOT_GITHUB_TOKEN")
    github_token = os.getenv("GITHUB_TOKEN")
    pr_number = int(os.getenv("PR_NUMBER"))
    repository = os.getenv("REPOSITORY")

    if not all([copilot_token, github_token, pr_number, repository]):
        raise SystemExit("Missing environment variables")

    # Fetch PR diff with PyGithub
    gh = Github(github_token)
    repo = gh.get_repo(repository)
    pr = repo.get_pull(pr_number)

    diff_parts = [f"# PR #{pr.number}: {pr.title}"]
    for f in pr.get_files():
        if f.patch:
            diff_parts.append(
                f"\n## File: {f.filename}\n```diff\n{f.patch}\n```"
            )
    diff_content = "\n".join(diff_parts)

    client = CopilotClient({})
    await client.start()

    try:
        session = await client.create_session({
            "model": "claude-sonnet-4.5",
            "streaming": False,
        })

        prompt = f"""Review this PR and provide:
- Complexity score (1-10)
- Bugs or risks
- Testing recommendations

PR content:
{diff_content}
"""

        response = await session.send_and_wait({"prompt": prompt})
        analysis = response.data.content if response and response.data else ""

    finally:
        await client.stop()

    # Post a comment to the PR
    comment = f"""## Copilot SDK Review

{analysis}
"""
    pr.create_issue_comment(comment)


if __name__ == "__main__":
    asyncio.run(main())

This script shows the minimal pattern:

  • Pull context from GitHub (here, the PR diff).
  • Call the Copilot SDK with that context.
  • Write results back into GitHub (as a comment).

Do note, I’ve also made use of skills_directory

session = await client.create_session({
    "model": "claude-sonnet-4.5",
    "streaming": True,
    "skill_directories": ["./.copilot_skills/pr-reviewer"]
})

By loading skill_directories, you’re:

  • Injecting predefined behaviour
  • Enforcing output structure
  • Turning Copilot into a scoped agent

Instead of prompting loosely, you are giving the agent a defined role.

Example of output from the above

Screenshot of example showing automated PR review assistant

Using Skills to Define Agent Behaviour

To make the assistant more consistent, you can load one or more skills when you create the session:

You can define:

  • Required markdown sections
  • Severity rating format
  • Risk classification logic
  • Mandatory scoring scale
  • Output constraints
session = await client.create_session({
    "model": "claude-sonnet-4.5",
    "streaming": True,
    "skill_directories": ["./.copilot_skills/pr-reviewer"]
})

By loading skill_directories, you are:

  • Injecting predefined behavior
  • Enforcing output structure
  • Turning Copilot into a scoped agent, instead of a loosely prompted model

A skill defines, for example:

  • The agent’s role (for example, “PR reviewer for backend services”)
  • How to assign a complexity score from 1–10
  • How to classify risks and recommendations
  • The required sections and markdown layout

You might organise like this:

.copilot_skills/
  pr-reviewer/
    SKILL.md

The SKILL.md file describes what the agent does and how it should respond. Skills let you change behavior and shape output without editing your Python prompts, and the same mechanism can drive other agents (security reviewer, documentation checker, release-notes writer) by changing which directory you pass in skill_directories

Wrapping Up

You now have a pattern for running GitHub Copilot SDK as an agent inside GitHub Actions: the workflow provides event triggers and repository context, the CLI provides the local runtime, and your Python script plus skills define what the agent does and how it responds.

With that in place, you can treat Actions as a Copilot socket in your CI/CD, swapping skills and prompts to reuse the same plumbing for a PR reviewer, security assistant, documentation enforcer, or release-notes generator

Check out this GitHub repo that contains the code from this blog post

1 thought on “Running GitHub Copilot SDK Inside GitHub Actions”

Leave a Reply

Discover more from Thomas Thornton Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading

Discover more from Thomas Thornton Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading