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
- 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.

Architecture at a glance
At runtime, the pieces line up like this:
- GitHub Actions runner
- Triggers on a PR event
- Installs Node.js
- Installs the Copilot CLI
- Installs Python dependencies
- 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
- Copilot SDK
- Launches or connects to the Copilot CLI in server mode
- Manages the request and session lifecycle
- Copilot CLI
- Authenticates using a token
- Communicates with Copilot services
- 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.

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
- In GitHub, go to Settings → Developer settings → Personal access tokens → Fine-grained tokens.
- Create a new token with:
- Copilot: Read permission
- Copy and store the token value; you will use it as a repo secret.
Step 2: Add repository secrets
In your repository:
- Open Settings → Secrets and variables → Actions.
- 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

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
- 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”