Multi-agent demos have a habit of starting with a heroic architecture diagram and ending with three agents arguing over the same file. Let’s build something smaller and more useful: one agent that researches a codebase, one that can make tightly scoped changes, and a parent session that keeps both on a short leash.
This guide uses the stable GitHub Copilot SDK 1.0.9 release and Node.js. The first run is deliberately read-only. Once that works, you can add an implementer without handing every tool to every agent.
Verified scope: I checked this guide against GitHub’s official v1.0.9 release, SDK documentation and Node.js reference on 6 August 2026. I have not run this project or authenticated it against a live Copilot account. Treat the code as an evidence-backed starting point to review and test in a disposable repository, not as a claim of hands-on results.
What changed in GitHub Copilot SDK 1.0.9?
Version 1.0.9 was published on 6 August 2026. Its release notes include a Node.js Agent Factories authoring surface, an AgentStop session hook across languages, per-session GitHub MCP configuration, additional working directories, managed-approval information, session-store guidance, usage and billing documentation, a citations guide, and several tool-result and documentation fixes.
The exciting phrase there is “Agent Factories”, but there is an important asterisk. GitHub’s merged implementation describes that API as Node-only, marked experimental and gated behind both a runtime feature flag and a billing gate. This tutorial therefore uses the documented customAgents route that readers can use today. I would not build a production dependency around Agent Factories until GitHub removes those gates and publishes stable guidance.
| Requirement | What you need |
|---|---|
| Node.js | ^20.19.0 or >=22.12.0 according to the Node SDK README |
| Package | @github/copilot-sdk@1.0.9 |
| Copilot runtime | Bundled automatically with the Node.js SDK |
| Authentication | GitHub Copilot access, or a supported BYOK configuration |
| Safe test location | A disposable repository copy or clean Git branch with no production secrets |
| Agent Factories | Experimental and gated; not required for this guide |
Step 1: create the Node.js project
Check Node first. The package’s current engine requirement is more specific than a generic “Node 20 or later”, so an older Node 20 build can still fail.
node --version
npm --version
mkdir copilot-multi-agent
cd copilot-multi-agent
npm init -y --init-type module
npm install @github/copilot-sdk@1.0.9 tsx
npm list @github/copilot-sdkPinning 1.0.9 makes the guide reproducible. After you have a working baseline, move to a later patch deliberately and read its release notes instead of letting a fresh install quietly change the API underneath you.
Step 2: understand authentication before adding agents
The Node.js package includes the Copilot CLI runtime, so you do not need to install a second global CLI just to follow the default setup. You still need an identity and permission to use the service. GitHub documents standard Copilot authentication, BYOK, GitHub OAuth for user-facing apps, and short-lived installation tokens for server-to-server use.
For a local experiment, use your normal authorised account. Do not paste personal access tokens or model-provider keys into index.ts. If your organisation manages Copilot, its policy may restrict models, MCP tools or automatic approvals. That is a control to respect, not an error to work around.
Step 3: build a read-only two-agent session
Create index.ts with the following starting point. Both agents can inspect files, but neither gets an editing tool or shell. The distinction is in their job: the researcher maps the code, while the reviewer challenges assumptions and looks for risks.
import { CopilotClient } from "@github/copilot-sdk";
const client = new CopilotClient();
await client.start();
const session = await client.createSession({
model: "auto",
streaming: true,
sessionId: "copilot-multi-agent-demo",
availableTools: ["task", "grep", "glob", "view"],
customAgents: [
{
name: "researcher",
displayName: "Research Agent",
description: "Maps a codebase and answers architecture questions using read-only tools",
tools: ["grep", "glob", "view"],
prompt:
"Inspect and explain the codebase. Do not edit files, run shell commands, install packages, or access secrets.",
},
{
name: "reviewer",
displayName: "Review Agent",
description: "Reviews code and identifies correctness, security, and testing risks",
tools: ["grep", "glob", "view"],
prompt:
"Review evidence carefully. Report uncertainty and cite file paths. Do not modify anything.",
},
],
});
session.on((event) => {
if (event.type === "subagent.started") {
console.log("Sub-agent started:", event.data.agentDisplayName);
}
if (event.type === "subagent.completed") {
console.log("Sub-agent completed:", event.data.agentDisplayName);
}
if (event.type === "subagent.failed") {
console.error("Sub-agent failed:", event.data.error);
}
});
session.on("assistant.usage", (event) => {
const { model, inputTokens, outputTokens, cost } = event.data;
console.log(
"Usage:",
model,
"input=" + (inputTokens ?? 0),
"output=" + (outputTokens ?? 0),
"cost=" + (cost ?? 0),
);
});
const response = await session.sendAndWait({
prompt:
"Use the researcher to map this project, then ask the reviewer to list the three highest-risk assumptions. Read only. Cite file paths and do not change anything.",
});
console.log(response?.data.content);
await session.disconnect();
await client.stop();The session-wide availableTools allowlist matters. Restricting tools only inside customAgents would still leave the parent agent’s default toolset available. I have also intentionally left out an automatic permission handler. GitHub’s examples often show an “approve once” callback for compactness, but blindly approving every request is a poor default once an agent can execute commands or change files. Start with no write-capable tools and add a deliberate permission experience for your application before expanding access.
Step 4: run it in a disposable repository
Put the demo inside a throwaway project or point its working directory at a copy. Before the run, make sure Git can tell you if anything changes:
git status --short
npx tsx index.ts
git status --short
git diff --stat
git diffThe useful result is not merely a fluent answer. You want to see appropriate sub-agent events, usage events and an unchanged repository. The runtime may select one or both agents for this prompt; the exact delegation is not deterministic. If it repeatedly chooses the wrong specialist, make the descriptions more distinct or split the work into separate sessions with an agent pre-selected by name.
Step 5: add an implementer without making it automatic
Once the read-only path behaves, define a third agent. Do not simply add edit to the original session and hope the prompt is careful. Use a separate write-capable session, pre-select the implementer with agent: "implementer", and connect a permission handler that presents the exact request to a human.
const implementer = {
name: "implementer",
displayName: "Implementation Agent",
description: "Makes a requested, narrow code change after research is complete",
infer: false,
tools: ["view", "edit"],
prompt:
"Make only the explicitly requested change. Do not use a shell, install packages, touch secrets, commit, push, or broaden scope. Summarise every edited file.",
};
const writeSession = await client.createSession({
model: "auto",
sessionId: "copilot-implementation-demo",
availableTools: ["view", "edit"],
customAgents: [implementer],
agent: "implementer",
onPermissionRequest: reviewPermissionInYourUI,
});reviewPermissionInYourUI is intentionally an application-owned function, not a magic SDK helper: implement it so a human can inspect and approve or deny the exact request. Notice what is still missing: no unrestricted shell and no “all tools” shortcut. If the task genuinely requires a test command, add a narrowly designed custom tool. A useful multi-agent system is not the one with the most autonomy; it is the one whose mistakes are cheap to spot and reverse.
Resume the session later
Because the example supplies sessionId, the session can be resumed after a restart:
const client = new CopilotClient();
await client.start();
const session = await client.resumeSession("copilot-multi-agent-demo");
const response = await session.sendAndWait({
prompt: "Summarise the earlier findings and list the unresolved questions.",
});
console.log(response?.data.content);
await session.disconnect();
await client.stop();GitHub documents conversation history, tool results, planning state and session artifacts as persisted, but not provider API keys or in-memory tool state. BYOK credentials must be supplied again. Shared server deployments also need application-level access control and locking; two clients writing to one session at once is undefined.
Add MCP only after the base session works
Copilot SDK sessions can connect to local or remote MCP servers. Version 1.0.9 also exposes per-session configuration for GitHub’s built-in MCP tools. GitHub currently labels MCP as an evolving feature. It can be genuinely useful for issues, pull requests and repository context, but it also creates a wider permission boundary.
My sequence would be: make the plain session work, add one MCP server, allow only the tools the agent needs, use a short-lived token where possible, and test a read-only request before enabling writes. If you want a separate local example of the protocol, see this guide to set up MCP tools with llama.cpp. It is a different stack, not a Copilot SDK prerequisite.
Track usage before the bill becomes a mystery
The assistant.usage listener in the example reports the model, input tokens, output tokens and cost multiplier for each model call, including sub-agent calls. This matters because a request that looks like one turn can involve several model interactions.
GitHub also documents accumulated session metrics and account quota RPCs, but some of those generated RPC surfaces are explicitly marked experimental. Use the live event for a first dashboard, pin your SDK and runtime if you depend on experimental metrics, and reconcile your application logs with GitHub’s own account usage rather than treating one local number as a bill.
Troubleshooting
The install reports an unsupported Node engine
Check node --version. The Node SDK currently requires ^20.19.0 or >=22.12.0. Upgrade through the official Node installer or your trusted version manager, reopen the terminal, then reinstall dependencies.
Authentication fails or a model is unavailable
Confirm the account has Copilot access and that your organisation allows the SDK and requested model. Keep model: "auto" for the first test. For token-based authentication, follow GitHub’s documented environment-variable order; a classic ghp_ personal access token is not supported for this route. BYOK is a separate configuration path and does not mean every provider or model is automatically supported.
The runtime never selects a sub-agent
Make each agent’s description specific and non-overlapping. Mention the agent by name in the first test prompt. Check that infer is not false for agents you expect the runtime to select automatically.
A tool request is denied
That can be the correct result. Add a permission handler that exposes the exact request to the user and returns the narrowest decision your application supports. Do not fix the demo by silently approving every current and future tool. Managed organisation settings may require approval regardless of your code.
A resumed session has no history
Use the same explicit session ID, ensure the session-state location is writable and persistent, and do not call the permanent delete API. In containers, mount the session state to persistent storage. Provider keys and in-memory tool state are intentionally not restored.
An MCP server connects but its tools do not appear
Check the server transport, process path, environment variables, authentication and tool allowlist. GitHub’s MCP guide distinguishes local stdio servers from remote HTTP/SSE servers. Start with one explicitly allowed read-only tool instead of *.
Is Copilot SDK the right tool?
Use the SDK when you want to embed an agent loop, tools and session handling inside your own application. If you want a ready-made coding-agent stack instead of building an application, this guide to use DeepSeek V4 Flash with Codex on Windows takes a different, more direct route.
Frequently asked questions
Do I need a GitHub Copilot subscription?
Standard Copilot-authenticated use requires eligible Copilot access. GitHub also documents BYOK, which uses credentials and billing from a supported model provider instead of GitHub Copilot authentication.
Do I need to install Copilot CLI separately?
Not for the default Node.js setup. GitHub says the Node.js SDK bundles the CLI runtime. Advanced deployments can connect to an external runtime, but then you are responsible for compatibility and security.
Are custom agents the same as Agent Factories?
No. Custom agents are documented session definitions with their own prompts and tool scopes. Agent Factories are a new Node.js orchestration surface in 1.0.9, but GitHub’s implementation marks them experimental and places them behind runtime and billing gates.
Do custom agents run in parallel?
Custom agents support delegation and isolated sub-agent work. GitHub documents Fleet mode for work that should be split across independent agents in parallel. Start sequentially; parallel agents increase tool activity, context and usage, and they need clear ownership to avoid conflicting edits.
Is the SDK production-ready?
GitHub announced the core Copilot SDK as generally available on 2 June 2026. Individual surfaces can still be experimental, including Agent Factories and some usage RPCs. Evaluate stability feature by feature, pin versions and keep a human approval boundary around consequential tools.
Official sources
- GitHub Copilot SDK v1.0.9 release notes
- GitHub Copilot SDK 1.0.9 Node.js README
- Agent Factories implementation and experimental-status notes
- GitHub’s Copilot SDK general-availability announcement
- Build your first Copilot-powered app
- Custom agents and sub-agent orchestration
- Session resume and persistence
- Using MCP servers with the Copilot SDK
- Usage and billing metrics
- Copilot SDK authentication options
- Copilot SDK troubleshooting index