How to Build Custom AI Agents Using the GitHub Copilot SDK: Complete Guide
Yes, the GitHub Copilot SDK provides a production-tested agent runtime that supports custom AI agents through JSON-RPC communication with the Copilot CLI, available in Node.js/TypeScript, Python, Go, .NET, Java, and Rust.
The github/copilot-sdk repository offers a production-ready framework for embedding AI agent capabilities into your applications. You can build custom AI agents using the GitHub Copilot SDK by defining lightweight configurations that include system prompts, tool permissions, and optional MCP servers, which the runtime then executes in isolated sub-agent contexts.
What Are Custom Agents?
A custom agent in the Copilot SDK is a named configuration object that ships with its own system prompt, a scoped set of allowed tools, and optional MCP (Model Context Protocol) servers. When user requests match the agent's description—or when an explicit agent name is supplied—the runtime automatically spawns a sub-agent that operates in an isolated context.
Key concepts include:
- Custom agent: The definition containing
name,prompt, optionaldescription, andtools - Sub-agent: The actual instance of a custom agent invoked during runtime
- Inference: Automatic selection based on prompt intent (controlled by the
inferparameter, which defaults totrue) - Session: The top-level interaction that may host multiple custom agents
- Tool scoping: Restriction of which first-party tools (e.g.,
grep,edit) an agent may invoke
According to the source code in docs/features/custom-agents.md, this architecture allows you to enforce least-privilege security by limiting tool access per agent while maintaining composable workflows.
Architecture and Internal Runtime Flow
The SDK abstracts JSON-RPC plumbing through the CopilotClient class that manages the CLI process automatically.
The internal execution flow works as follows:
- Session initialization: The SDK constructs a
SessionConfigcontaining thecustomAgentsarray and establishes a JSON-RPC handshake with the Copilot CLI running in server mode. - Intent evaluation: For each incoming prompt, the runtime evaluates custom agent
descriptionfields. If a match is detected andinferis not explicitly set tofalse, the runtime spawns a sub-agent. - Isolated execution: The sub-agent receives its dedicated system prompt and only the tools listed in its
toolsarray (or all available tools if the array is omitted). - Event streaming: Lifecycle events including
subagent.started,subagent.completed, andsubagent.failedstream back to the parent session, enabling real-time UI updates or logging. - Result integration: The sub-agent's final response merges into the parent session's answer and returns to the caller.
This process requires no manual process management from developers—you supply configuration objects and event handlers while the SDK handles the underlying JSON-RPC communication.
Multi-Language SDK Support
The GitHub Copilot SDK supports building custom agents across six languages through dedicated client libraries:
-
Node.js/TypeScript: Primary implementation with full feature parity
-
Python: Async/await support with the
copilotpackage -
Go: Native routines for concurrent agent management
-
.NET: C# implementation for enterprise applications
-
Java: Maven and Gradle compatible
-
Rust: Systems programming integration
Each implementation communicates with the same underlying Copilot CLI via JSON-RPC, ensuring consistent behavior across language ecosystems.
Creating a Custom Agent
To build custom AI agents, you instantiate a CopilotClient, create a session with a customAgents configuration array, and handle lifecycle events.
Node.js/TypeScript Example
The Node.js SDK exports CopilotClient from @github/copilot-sdk. Create agents by defining configurations with scoped tools and descriptions:
import { CopilotClient } from "@github/copilot-sdk";
const client = new CopilotClient();
await client.start();
const session = await client.createSession({
model: "gpt-4.1",
customAgents: [
{
name: "researcher",
displayName: "Research Agent",
description: "Explores codebases with read‑only tools",
tools: ["grep", "glob", "view"],
prompt:
"You are a research assistant. Analyze code and answer questions. Do not modify any files.",
},
{
name: "editor",
displayName: "Editor Agent",
description: "Makes targeted code changes",
tools: ["view", "edit", "bash"],
prompt:
"You are a code editor. Make minimal, surgical changes to files as requested.",
},
],
onPermissionRequest: async () => ({ kind: "approve-once" }),
});
// Listen for sub‑agent events
session.on((event) => {
if (event.type === "subagent.started") {
console.log(`▶ Sub‑agent ${event.data.agentDisplayName} started`);
}
});
const response = await session.sendAndWait({
prompt: "Explain the authentication flow in this repository",
});
console.log(response);
The runtime automatically delegates to the appropriate sub-agent based on the prompt content and agent descriptions. Full implementation details appear in nodejs/docs/agent-author.md.
Python Example
The Python SDK follows similar patterns using copilot.CopilotClient:
from copilot import CopilotClient, PermissionDecisionApproveOnce
client = CopilotClient()
await client.start()
session = await client.create_session(
model="gpt-4.1",
custom_agents=[
{
"name": "researcher",
"display_name": "Research Agent",
"description": "Read‑only exploration of the codebase",
"tools": ["grep", "glob", "view"],
"prompt": "You are a research assistant. Analyze code and answer questions. Do not modify any files.",
},
{
"name": "editor",
"display_name": "Editor Agent",
"description": "Makes targeted code changes",
"tools": ["view", "edit", "bash"],
"prompt": "You are a code editor. Make minimal, surgical changes to files as requested.",
},
],
on_permission_request=lambda req, inv: PermissionDecisionApproveOnce(),
)
def handle(event):
if event.type == "subagent.started":
print(f"▶ Sub‑agent {event.data.agent_display_name} started")
elif event.type == "subagent.completed":
print(f"✅ Sub‑agent {event.data.agent_display_name} completed")
unsubscribe = session.on(handle)
response = await session.send_and_wait("Summarize the CI configuration in this repo")
print(response)
Reference python/README.md for installation instructions and async patterns.
Security and Tool Scoping
Custom agents enforce least-privilege security through explicit tool scoping. By restricting the tools array, you limit what the underlying LLM can execute:
- Read-only agents: Limit to
["grep", "glob", "view"]for safe code exploration - Editor agents: Extend with
["edit", "bash"]for file modification capabilities - Domain-specific agents: Attach MCP servers to grant access to private data sources like database schemas or internal APIs
This separation of concerns prevents accidental modifications during research tasks while allowing surgical edits when explicitly requested.
Key Files and Documentation
The github/copilot-sdk repository contains definitive resources for building custom agents:
README.md: High-level architecture overview, installation instructions, and JSON-RPC communication diagramsdocs/features/custom-agents.md: Complete configuration schema, event types, and multi-language examplesnodejs/docs/agent-author.md: Node.js/TypeScript specific guidance for agent authoringpython/README.md: Python SDK quick-start and async patternsgo/README.md,dotnet/README.md,java/README.md,rust/README.md: Language-specific setup and usage guides
Summary
- Yes, you can build custom AI agents using the GitHub Copilot SDK's production-tested runtime across Node.js/TypeScript, Python, Go, .NET, Java, and Rust.
- Custom agents are configuration objects containing
name,description,prompt, and scopedtoolsthat run as isolated sub-agents. - Automatic delegation occurs when the runtime matches user prompts to agent descriptions (controlled by the
inferparameter). - Event streaming provides real-time visibility into sub-agent lifecycle states (
subagent.started,subagent.completed,subagent.failed). - Tool scoping enforces least-privilege security by restricting which first-party tools each agent may invoke.
Frequently Asked Questions
Can custom agents access external data sources?
Yes. You can attach MCP (Model Context Protocol) servers to custom agent configurations, allowing access to domain-specific data such as database schemas, internal documentation APIs, or proprietary knowledge bases. The MCP integration runs alongside the scoped tools defined in the agent's tools array.
How does the runtime decide which custom agent to use?
The Copilot SDK evaluates the description field of each configured custom agent against the incoming user prompt. If the runtime detects a match and the agent's infer parameter is not explicitly set to false, it automatically spawns that sub-agent. Alternatively, you can explicitly specify an agent by name in the request to bypass automatic inference.
Are custom agents isolated from each other?
Yes. Each custom agent runs as a sub-agent in an isolated context with its own system prompt and restricted tool set. Lifecycle events stream back to the parent session, but the execution environment remains separate, preventing tool access leakage between different agent instances within the same session.
Which programming languages support custom agent development?
The GitHub Copilot SDK supports custom agent development in Node.js/TypeScript, Python, Go, .NET, Java, and Rust. All implementations communicate with the same underlying Copilot CLI via JSON-RPC, ensuring consistent agent behavior and configuration schemas across languages. Each SDK provides equivalent CopilotClient classes and session management APIs.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →