diff --git a/CHANGELOG.md b/CHANGELOG.md
index ac5712aa5..8bb74e3e8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,6 +12,10 @@ See [GitHub Releases](https://github.com/github/copilot-sdk/releases) for the fu
SDK applications written against the v3 API now also work when connected to a v2 CLI server, with no code changes required. The SDK detects the server's protocol version and automatically adapts v2 `tool.call` and `permission.request` messages into the same user-facing handlers used by v3. ([#706](https://github.com/github/copilot-sdk/pull/706))
```ts
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
+
const session = await client.createSession({
tools: [myTool], // unchanged — works with v2 and v3 servers
onPermissionRequest: approveAll,
@@ -84,7 +88,9 @@ if result.Kind == copilot.PermissionKindApproved { /* ... */ }
Applications can now override built-in tools such as `grep`, `edit_file`, or `read_file`. To do this, register a custom tool with the same name and set the override flag. Without the flag, the runtime will return an error if the name clashes with a built-in. ([#636](https://github.com/github/copilot-sdk/pull/636))
```ts
-import { defineTool } from "@github/copilot-sdk";
+import { CopilotClient, defineTool, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const session = await client.createSession({
tools: [defineTool("grep", {
diff --git a/docs/auth/byok.md b/docs/auth/byok.md
index 8d9650280..51e858eab 100644
--- a/docs/auth/byok.md
+++ b/docs/auth/byok.md
@@ -63,7 +63,7 @@ asyncio.run(main())
Node.js / TypeScript
```typescript
-import { CopilotClient } from "@github/copilot-sdk";
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
const FOUNDRY_MODEL_URL = "https://your-resource.openai.azure.com/openai/v1/";
@@ -76,6 +76,7 @@ const session = await client.createSession({
wireApi: "responses", // Use "completions" for older models
apiKey: process.env.FOUNDRY_API_KEY,
},
+ onPermissionRequest: approveAll
});
session.on("assistant.message", (event) => {
@@ -454,15 +455,21 @@ Some Copilot features may behave differently with BYOK:
When using BYOK, the `model` parameter is **required**:
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
+
// ❌ Error: Model required with custom provider
const session = await client.createSession({
provider: { type: "openai", baseUrl: "..." },
+ onPermissionRequest: approveAll,
});
// ✅ Correct: Model specified
const session = await client.createSession({
model: "gpt-4", // Required!
provider: { type: "openai", baseUrl: "..." },
+ onPermissionRequest: approveAll,
});
```
@@ -472,7 +479,7 @@ For Azure OpenAI endpoints (`*.openai.azure.com`), use the correct type:
```typescript
-import { CopilotClient } from "@github/copilot-sdk";
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
const client = new CopilotClient();
const session = await client.createSession({
@@ -481,6 +488,7 @@ const session = await client.createSession({
type: "azure",
baseUrl: "https://my-resource.openai.azure.com",
},
+ onPermissionRequest: approveAll
});
```
@@ -503,7 +511,7 @@ However, if your Azure AI Foundry deployment provides an OpenAI-compatible endpo
```typescript
-import { CopilotClient } from "@github/copilot-sdk";
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
const client = new CopilotClient();
const session = await client.createSession({
@@ -512,6 +520,7 @@ const session = await client.createSession({
type: "openai",
baseUrl: "https://your-resource.openai.azure.com/openai/v1/",
},
+ onPermissionRequest: approveAll
});
```
diff --git a/docs/features/custom-agents.md b/docs/features/custom-agents.md
index 47712d9cf..aee06d5cb 100644
--- a/docs/features/custom-agents.md
+++ b/docs/features/custom-agents.md
@@ -31,7 +31,7 @@ Pass `customAgents` when creating a session. Each agent needs at minimum a `name
Node.js / TypeScript
```typescript
-import { CopilotClient } from "@github/copilot-sdk";
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
const client = new CopilotClient();
await client.start();
@@ -54,7 +54,7 @@ const session = await client.createSession({
prompt: "You are a code editor. Make minimal, surgical changes to files as requested.",
},
],
- onPermissionRequest: async () => ({ kind: "approved" }),
+ onPermissionRequest: approveAll,
});
```
@@ -236,6 +236,9 @@ This is equivalent to calling `session.rpc.agent.select()` after creation, but a
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const session = await client.createSession({
customAgents: [
{
@@ -248,6 +251,7 @@ const session = await client.createSession({
},
],
agent: "researcher", // Pre-select the researcher agent
+ onPermissionRequest: approveAll,
});
```
@@ -618,6 +622,9 @@ session.on((event) => {
Use the `tools` property to restrict which tools an agent can access. This is essential for security and for keeping agents focused:
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const session = await client.createSession({
customAgents: [
{
@@ -639,6 +646,7 @@ const session = await client.createSession({
prompt: "You handle complex multi-step tasks using any available tools.",
},
],
+ onPermissionRequest: approveAll,
});
```
@@ -649,6 +657,9 @@ const session = await client.createSession({
Each custom agent can have its own MCP (Model Context Protocol) servers, giving it access to specialized data sources:
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const session = await client.createSession({
customAgents: [
{
@@ -663,6 +674,7 @@ const session = await client.createSession({
},
},
],
+ onPermissionRequest: approveAll,
});
```
diff --git a/docs/features/hooks.md b/docs/features/hooks.md
index 1a01c5f1a..5af4e60f5 100644
--- a/docs/features/hooks.md
+++ b/docs/features/hooks.md
@@ -38,7 +38,7 @@ Pass a `hooks` object when you create (or resume) a session. Every example below
Node.js / TypeScript
```typescript
-import { CopilotClient } from "@github/copilot-sdk";
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
const client = new CopilotClient();
await client.start();
@@ -50,7 +50,7 @@ const session = await client.createSession({
onPostToolUse: async (input, invocation) => { /* ... */ },
// ... add only the hooks you need
},
- onPermissionRequest: async () => ({ kind: "approved" }),
+ onPermissionRequest: approveAll,
});
```
@@ -209,6 +209,9 @@ Use `onPreToolUse` to build a permission layer that decides which tools the agen
Node.js / TypeScript
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const READ_ONLY_TOOLS = ["read_file", "glob", "grep", "view"];
const session = await client.createSession({
@@ -224,7 +227,7 @@ const session = await client.createSession({
return { permissionDecision: "allow" };
},
},
- onPermissionRequest: async () => ({ kind: "approved" }),
+ onPermissionRequest: approveAll,
});
```
@@ -383,6 +386,9 @@ var session = await client.CreateSessionAsync(new SessionConfig
### Restrict file access to specific directories
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const ALLOWED_DIRS = ["/home/user/projects", "/tmp"];
const session = await client.createSession({
@@ -403,13 +409,16 @@ const session = await client.createSession({
return { permissionDecision: "allow" };
},
},
- onPermissionRequest: async () => ({ kind: "approved" }),
+ onPermissionRequest: approveAll,
});
```
### Ask the user before destructive operations
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const DESTRUCTIVE_TOOLS = ["delete_file", "shell", "bash"];
const session = await client.createSession({
@@ -421,7 +430,7 @@ const session = await client.createSession({
return { permissionDecision: "allow" };
},
},
- onPermissionRequest: async () => ({ kind: "approved" }),
+ onPermissionRequest: approveAll,
});
```
@@ -439,6 +448,8 @@ Combine `onPreToolUse`, `onPostToolUse`, and the session lifecycle hooks to buil
Node.js / TypeScript
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
interface AuditEntry {
timestamp: number;
sessionId: string;
@@ -451,6 +462,7 @@ interface AuditEntry {
const auditLog: AuditEntry[] = [];
+const client = new CopilotClient();
const session = await client.createSession({
hooks: {
onSessionStart: async (input, invocation) => {
@@ -505,7 +517,7 @@ const session = await client.createSession({
return null;
},
},
- onPermissionRequest: async () => ({ kind: "approved" }),
+ onPermissionRequest: approveAll,
});
```
@@ -584,6 +596,9 @@ session = await client.create_session(
### Redact secrets from tool results
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const SECRET_PATTERNS = [
/(?:api[_-]?key|token|secret|password)\s*[:=]\s*["']?[\w\-\.]+["']?/gi,
];
@@ -603,7 +618,7 @@ const session = await client.createSession({
: null;
},
},
- onPermissionRequest: async () => ({ kind: "approved" }),
+ onPermissionRequest: approveAll,
});
```
@@ -620,7 +635,9 @@ Hooks fire in your application's process, so you can trigger any side-effect —
```typescript
import notifier from "node-notifier"; // npm install node-notifier
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+const client = new CopilotClient();
const session = await client.createSession({
hooks: {
onSessionEnd: async (input, invocation) => {
@@ -638,7 +655,7 @@ const session = await client.createSession({
return null;
},
},
- onPermissionRequest: async () => ({ kind: "approved" }),
+ onPermissionRequest: approveAll,
});
```
@@ -681,7 +698,9 @@ session = await client.create_session(
```typescript
import { exec } from "node:child_process";
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+const client = new CopilotClient();
const session = await client.createSession({
hooks: {
onPostToolUse: async (input) => {
@@ -694,13 +713,16 @@ const session = await client.createSession({
return null;
},
},
- onPermissionRequest: async () => ({ kind: "approved" }),
+ onPermissionRequest: approveAll,
});
```
### Post to Slack on errors
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const SLACK_WEBHOOK_URL = process.env.SLACK_WEBHOOK_URL!;
const session = await client.createSession({
@@ -718,7 +740,7 @@ const session = await client.createSession({
return null;
},
},
- onPermissionRequest: async () => ({ kind: "approved" }),
+ onPermissionRequest: approveAll,
});
```
@@ -731,6 +753,9 @@ Use `onSessionStart` and `onUserPromptSubmitted` to automatically inject context
### Inject project metadata at session start
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const session = await client.createSession({
hooks: {
onSessionStart: async (input) => {
@@ -746,13 +771,16 @@ const session = await client.createSession({
};
},
},
- onPermissionRequest: async () => ({ kind: "approved" }),
+ onPermissionRequest: approveAll,
});
```
### Expand shorthand commands in prompts
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const SHORTCUTS: Record = {
"/fix": "Find and fix all errors in the current file",
"/test": "Write comprehensive unit tests for this code",
@@ -772,7 +800,7 @@ const session = await client.createSession({
return null;
},
},
- onPermissionRequest: async () => ({ kind: "approved" }),
+ onPermissionRequest: approveAll,
});
```
@@ -785,6 +813,9 @@ The `onErrorOccurred` hook gives you a chance to react to failures — whether t
### Retry transient model errors
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const session = await client.createSession({
hooks: {
onErrorOccurred: async (input) => {
@@ -798,13 +829,16 @@ const session = await client.createSession({
return null;
},
},
- onPermissionRequest: async () => ({ kind: "approved" }),
+ onPermissionRequest: approveAll,
});
```
### Friendly error messages
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const FRIENDLY_MESSAGES: Record = {
model_call: "The AI model is temporarily unavailable. Please try again.",
tool_execution: "A tool encountered an error. Check inputs and try again.",
@@ -819,7 +853,7 @@ const session = await client.createSession({
};
},
},
- onPermissionRequest: async () => ({ kind: "approved" }),
+ onPermissionRequest: approveAll,
});
```
@@ -833,6 +867,9 @@ Track how long sessions run, how many tools are invoked, and why sessions end
Node.js / TypeScript
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const metrics = new Map();
const session = await client.createSession({
@@ -867,7 +904,7 @@ const session = await client.createSession({
return null;
},
},
- onPermissionRequest: async () => ({ kind: "approved" }),
+ onPermissionRequest: approveAll,
});
```
@@ -925,6 +962,9 @@ session = await client.create_session(
Hooks compose naturally. A single `hooks` object can handle permissions **and** auditing **and** notifications — each hook does its own job.
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const session = await client.createSession({
hooks: {
onSessionStart: async (input) => {
@@ -951,7 +991,7 @@ const session = await client.createSession({
return null;
},
},
- onPermissionRequest: async () => ({ kind: "approved" }),
+ onPermissionRequest: approveAll,
});
```
diff --git a/docs/features/image-input.md b/docs/features/image-input.md
index acec80d4a..093f62f89 100644
--- a/docs/features/image-input.md
+++ b/docs/features/image-input.md
@@ -41,14 +41,14 @@ Attach an image file to any message using the file attachment type. The path mus
Node.js / TypeScript
```typescript
-import { CopilotClient } from "@github/copilot-sdk";
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
const client = new CopilotClient();
await client.start();
const session = await client.createSession({
model: "gpt-4.1",
- onPermissionRequest: async () => ({ kind: "approved" }),
+ onPermissionRequest: approveAll,
});
await session.send({
@@ -227,14 +227,14 @@ When you already have image data in memory (e.g., a screenshot captured by your
Node.js / TypeScript
```typescript
-import { CopilotClient } from "@github/copilot-sdk";
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
const client = new CopilotClient();
await client.start();
const session = await client.createSession({
model: "gpt-4.1",
- onPermissionRequest: async () => ({ kind: "approved" }),
+ onPermissionRequest: approveAll,
});
const base64ImageData = "..."; // your base64-encoded image
diff --git a/docs/features/mcp.md b/docs/features/mcp.md
index 62465c0bd..e91184a74 100644
--- a/docs/features/mcp.md
+++ b/docs/features/mcp.md
@@ -28,7 +28,7 @@ The SDK supports two types of MCP servers:
### Node.js / TypeScript
```typescript
-import { CopilotClient } from "@github/copilot-sdk";
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
const client = new CopilotClient();
const session = await client.createSession({
@@ -52,6 +52,7 @@ const session = await client.createSession({
tools: ["*"],
},
},
+ onPermissionRequest: approveAll
});
```
@@ -162,7 +163,7 @@ await using var session = await client.CreateSessionAsync(new SessionConfig
Here's a complete working example using the official [`@modelcontextprotocol/server-filesystem`](https://www.npmjs.com/package/@modelcontextprotocol/server-filesystem) MCP server:
```typescript
-import { CopilotClient } from "@github/copilot-sdk";
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
async function main() {
const client = new CopilotClient();
@@ -177,6 +178,7 @@ async function main() {
tools: ["*"],
},
},
+ onPermissionRequest: approveAll
});
console.log("Session created:", session.sessionId);
diff --git a/docs/features/session-persistence.md b/docs/features/session-persistence.md
index 3b0e9f69b..dc1fc5062 100644
--- a/docs/features/session-persistence.md
+++ b/docs/features/session-persistence.md
@@ -26,7 +26,7 @@ The key to resumable sessions is providing your own `session_id`. Without one, t
### TypeScript
```typescript
-import { CopilotClient } from "@github/copilot-sdk";
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
const client = new CopilotClient();
@@ -34,6 +34,7 @@ const client = new CopilotClient();
const session = await client.createSession({
sessionId: "user-123-task-456",
model: "gpt-5.2-codex",
+ onPermissionRequest: approveAll
});
// Do some work...
@@ -134,10 +135,10 @@ flowchart LR
subgraph Day1["Day 1"]
A1[Client A:
createSession] --> A2[Work...]
end
-
+
A2 --> S[(💾 Storage:
~/.copilot/session-state/)]
S --> B1
-
+
subgraph Day2["Day 2"]
B1[Client B:
resumeSession] --> B2[Continue]
end
@@ -265,6 +266,9 @@ const session = await client.resumeSession("user-123-task-456", {
When using your own API keys, you must re-provide the provider configuration when resuming. API keys are never persisted to disk for security reasons.
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
// Original session with BYOK
const session = await client.createSession({
sessionId: "user-123-task-456",
@@ -275,6 +279,7 @@ const session = await client.createSession({
apiKey: process.env.AZURE_OPENAI_KEY,
deploymentId: "my-gpt-deployment",
},
+ onPermissionRequest: approveAll,
});
// When resuming, you MUST re-provide the provider config
@@ -376,7 +381,7 @@ const repoSessions = await client.listSessions({ repository: "owner/repo" });
async function cleanupExpiredSessions(maxAgeMs: number) {
const sessions = await client.listSessions();
const now = Date.now();
-
+
for (const session of sessions) {
const age = now - new Date(session.createdAt).getTime();
if (age > maxAgeMs) {
@@ -398,7 +403,7 @@ When a task completes, disconnect from the session explicitly rather than waitin
try {
// Do work...
await session.sendAndWait({ prompt: "Complete the task" });
-
+
// Task complete — release in-memory resources (session can be resumed later)
await session.disconnect();
} catch (error) {
@@ -495,11 +500,11 @@ async function resumeSessionWithAuth(
): Promise {
// Parse user from session ID
const [sessionUserId] = sessionId.split("-");
-
+
if (sessionUserId !== currentUserId) {
throw new Error("Access denied: session belongs to another user");
}
-
+
return client.resumeSession(sessionId);
}
```
@@ -533,10 +538,10 @@ flowchart LR
subgraph Before["Container A"]
CLI1[CLI + Session X]
end
-
+
CLI1 --> |persist| Azure[(☁️ Azure File Share)]
Azure --> |restore| CLI2
-
+
subgraph After["Container B (restart)"]
CLI2[CLI + Session X]
end
@@ -549,6 +554,9 @@ flowchart LR
For workflows that might exceed context limits, enable infinite sessions with automatic compaction:
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const session = await client.createSession({
sessionId: "long-workflow-123",
infiniteSessions: {
@@ -556,6 +564,7 @@ const session = await client.createSession({
backgroundCompactionThreshold: 0.80, // Start compaction at 80% context
bufferExhaustionThreshold: 0.95, // Block at 95% if needed
},
+ onPermissionRequest: approveAll,
});
```
@@ -586,11 +595,11 @@ async function withSessionLock(
): Promise {
const lockKey = `session-lock:${sessionId}`;
const acquired = await redis.set(lockKey, "locked", "NX", "EX", 300);
-
+
if (!acquired) {
throw new Error("Session is in use by another client");
}
-
+
try {
return await fn();
} finally {
diff --git a/docs/features/skills.md b/docs/features/skills.md
index 466c637ff..8f2fd5895 100644
--- a/docs/features/skills.md
+++ b/docs/features/skills.md
@@ -20,7 +20,7 @@ Specify directories containing skills when creating a session:
Node.js / TypeScript
```typescript
-import { CopilotClient } from "@github/copilot-sdk";
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
const client = new CopilotClient();
const session = await client.createSession({
@@ -29,7 +29,7 @@ const session = await client.createSession({
"./skills/code-review",
"./skills/documentation",
],
- onPermissionRequest: async () => ({ kind: "approved" }),
+ onPermissionRequest: approveAll,
});
// Copilot now has access to skills in those directories
@@ -148,9 +148,13 @@ Disable specific skills while keeping others active:
Node.js / TypeScript
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const session = await client.createSession({
skillDirectories: ["./skills"],
disabledSkills: ["experimental-feature", "deprecated-tool"],
+ onPermissionRequest: approveAll,
});
```
@@ -319,6 +323,9 @@ The markdown body contains the instructions that are injected into the session c
Skills work alongside custom agents:
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const session = await client.createSession({
skillDirectories: ["./skills/security"],
customAgents: [{
@@ -326,7 +333,7 @@ const session = await client.createSession({
description: "Security-focused code reviewer",
prompt: "Focus on OWASP Top 10 vulnerabilities",
}],
- onPermissionRequest: async () => ({ kind: "approved" }),
+ onPermissionRequest: approveAll,
});
```
@@ -335,6 +342,9 @@ const session = await client.createSession({
Skills can complement MCP server capabilities:
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const session = await client.createSession({
skillDirectories: ["./skills/database"],
mcpServers: {
@@ -345,7 +355,7 @@ const session = await client.createSession({
tools: ["*"],
},
},
- onPermissionRequest: async () => ({ kind: "approved" }),
+ onPermissionRequest: approveAll,
});
```
diff --git a/docs/features/steering-and-queueing.md b/docs/features/steering-and-queueing.md
index 7da349e1c..c68e5692a 100644
--- a/docs/features/steering-and-queueing.md
+++ b/docs/features/steering-and-queueing.md
@@ -41,14 +41,14 @@ Steering sends a message that is injected directly into the agent's current turn
Node.js / TypeScript
```typescript
-import { CopilotClient } from "@github/copilot-sdk";
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
const client = new CopilotClient();
await client.start();
const session = await client.createSession({
model: "gpt-4.1",
- onPermissionRequest: async () => ({ kind: "approved" }),
+ onPermissionRequest: approveAll,
});
// Start a long-running task
@@ -195,14 +195,14 @@ Queueing buffers messages to be processed sequentially after the current turn fi
Node.js / TypeScript
```typescript
-import { CopilotClient } from "@github/copilot-sdk";
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
const client = new CopilotClient();
await client.start();
const session = await client.createSession({
model: "gpt-4.1",
- onPermissionRequest: async () => ({ kind: "approved" }),
+ onPermissionRequest: approveAll,
});
// Send an initial task
@@ -404,9 +404,12 @@ You can use both patterns together in a single session. Steering affects the cur
Node.js / TypeScript
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const session = await client.createSession({
model: "gpt-4.1",
- onPermissionRequest: async () => ({ kind: "approved" }),
+ onPermissionRequest: approveAll,
});
// Start a task
diff --git a/docs/getting-started.md b/docs/getting-started.md
index 6c0aee72e..9a25fafcf 100644
--- a/docs/getting-started.md
+++ b/docs/getting-started.md
@@ -102,10 +102,10 @@ Create a new file and add the following code. This is the simplest way to use th
Create `index.ts`:
```typescript
-import { CopilotClient } from "@github/copilot-sdk";
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
const client = new CopilotClient();
-const session = await client.createSession({ model: "gpt-4.1" });
+const session = await client.createSession({ model: "gpt-4.1", onPermissionRequest: approveAll });
const response = await session.sendAndWait({ prompt: "What is 2 + 2?" });
console.log(response?.data.content);
@@ -243,12 +243,13 @@ Right now, you wait for the complete response before seeing anything. Let's make
Update `index.ts`:
```typescript
-import { CopilotClient } from "@github/copilot-sdk";
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
const client = new CopilotClient();
const session = await client.createSession({
model: "gpt-4.1",
streaming: true,
+ onPermissionRequest: approveAll
});
// Listen for response chunks
@@ -595,7 +596,7 @@ Now for the powerful part. Let's give Copilot the ability to call your code by d
Update `index.ts`:
```typescript
-import { CopilotClient, defineTool } from "@github/copilot-sdk";
+import { CopilotClient, defineTool, approveAll } from "@github/copilot-sdk";
// Define a tool that Copilot can call
const getWeather = defineTool("get_weather", {
@@ -622,6 +623,7 @@ const session = await client.createSession({
model: "gpt-4.1",
streaming: true,
tools: [getWeather],
+ onPermissionRequest: approveAll
});
session.on("assistant.message_delta", (event) => {
@@ -845,7 +847,7 @@ Let's put it all together into a useful interactive assistant:
Node.js / TypeScript
```typescript
-import { CopilotClient, defineTool } from "@github/copilot-sdk";
+import { CopilotClient, defineTool, approveAll } from "@github/copilot-sdk";
import * as readline from "readline";
const getWeather = defineTool("get_weather", {
@@ -870,6 +872,7 @@ const session = await client.createSession({
model: "gpt-4.1",
streaming: true,
tools: [getWeather],
+ onPermissionRequest: approveAll
});
session.on("assistant.message_delta", (event) => {
@@ -1204,6 +1207,9 @@ Now that you've got the basics, here are more powerful features to explore:
MCP (Model Context Protocol) servers provide pre-built tools. Connect to GitHub's MCP server to give Copilot access to repositories, issues, and pull requests:
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const session = await client.createSession({
mcpServers: {
github: {
@@ -1211,6 +1217,7 @@ const session = await client.createSession({
url: "https://api.githubcopilot.com/mcp/",
},
},
+ onPermissionRequest: approveAll,
});
```
@@ -1221,6 +1228,9 @@ const session = await client.createSession({
Define specialized AI personas for specific tasks:
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const session = await client.createSession({
customAgents: [{
name: "pr-reviewer",
@@ -1228,6 +1238,7 @@ const session = await client.createSession({
description: "Reviews pull requests for best practices",
prompt: "You are an expert code reviewer. Focus on security, performance, and maintainability.",
}],
+ onPermissionRequest: approveAll,
});
```
@@ -1238,10 +1249,14 @@ const session = await client.createSession({
Control the AI's behavior and personality:
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const session = await client.createSession({
systemMessage: {
content: "You are a helpful assistant for our engineering team. Always be concise.",
},
+ onPermissionRequest: approveAll,
});
```
diff --git a/docs/hooks/error-handling.md b/docs/hooks/error-handling.md
index a67906ac9..3418ae0e7 100644
--- a/docs/hooks/error-handling.md
+++ b/docs/hooks/error-handling.md
@@ -128,6 +128,9 @@ Return `null` or `undefined` to use default error handling. Otherwise, return an
Node.js / TypeScript
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const session = await client.createSession({
hooks: {
onErrorOccurred: async (input, invocation) => {
@@ -137,6 +140,7 @@ const session = await client.createSession({
return null;
},
},
+ onPermissionRequest: approveAll,
});
```
@@ -255,6 +259,9 @@ var session = await client.CreateSessionAsync(new SessionConfig
```typescript
import { captureException } from "@sentry/node"; // or your monitoring service
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const session = await client.createSession({
hooks: {
@@ -270,16 +277,20 @@ const session = await client.createSession({
cwd: input.cwd,
},
});
-
+
return null;
},
},
+ onPermissionRequest: approveAll,
});
```
### User-Friendly Error Messages
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const ERROR_MESSAGES: Record = {
"model_call": "There was an issue communicating with the AI model. Please try again.",
"tool_execution": "A tool failed to execute. Please check your inputs and try again.",
@@ -291,22 +302,26 @@ const session = await client.createSession({
hooks: {
onErrorOccurred: async (input) => {
const friendlyMessage = ERROR_MESSAGES[input.errorContext];
-
+
if (friendlyMessage) {
return {
userNotification: friendlyMessage,
};
}
-
+
return null;
},
},
+ onPermissionRequest: approveAll,
});
```
### Suppress Non-Critical Errors
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const session = await client.createSession({
hooks: {
onErrorOccurred: async (input) => {
@@ -318,12 +333,16 @@ const session = await client.createSession({
return null;
},
},
+ onPermissionRequest: approveAll,
});
```
### Add Recovery Context
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const session = await client.createSession({
hooks: {
onErrorOccurred: async (input) => {
@@ -337,7 +356,7 @@ The tool failed. Here are some recovery suggestions:
`.trim(),
};
}
-
+
if (input.errorContext === "model_call" && input.error.includes("rate")) {
return {
errorHandling: "retry",
@@ -345,55 +364,63 @@ The tool failed. Here are some recovery suggestions:
userNotification: "Rate limit hit. Retrying...",
};
}
-
+
return null;
},
},
+ onPermissionRequest: approveAll,
});
```
### Track Error Patterns
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
interface ErrorStats {
count: number;
lastOccurred: number;
contexts: string[];
}
+const client = new CopilotClient();
const errorStats = new Map();
const session = await client.createSession({
hooks: {
onErrorOccurred: async (input, invocation) => {
const key = `${input.errorContext}:${input.error.substring(0, 50)}`;
-
+
const existing = errorStats.get(key) || {
count: 0,
lastOccurred: 0,
contexts: [],
};
-
+
existing.count++;
existing.lastOccurred = input.timestamp;
existing.contexts.push(invocation.sessionId);
-
+
errorStats.set(key, existing);
-
+
// Alert if error is recurring
if (existing.count >= 5) {
console.warn(`Recurring error detected: ${key} (${existing.count} times)`);
}
-
+
return null;
},
},
+ onPermissionRequest: approveAll,
});
```
### Alert on Critical Errors
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const CRITICAL_CONTEXTS = ["system", "model_call"];
const session = await client.createSession({
@@ -408,16 +435,20 @@ const session = await client.createSession({
timestamp: new Date(input.timestamp).toISOString(),
});
}
-
+
return null;
},
},
+ onPermissionRequest: approveAll,
});
```
### Combine with Other Hooks for Context
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const sessionContext = new Map();
const session = await client.createSession({
@@ -428,17 +459,17 @@ const session = await client.createSession({
sessionContext.set(invocation.sessionId, ctx);
return { permissionDecision: "allow" };
},
-
+
onUserPromptSubmitted: async (input, invocation) => {
const ctx = sessionContext.get(invocation.sessionId) || {};
ctx.lastPrompt = input.prompt.substring(0, 100);
sessionContext.set(invocation.sessionId, ctx);
return null;
},
-
+
onErrorOccurred: async (input, invocation) => {
const ctx = sessionContext.get(invocation.sessionId);
-
+
console.error(`Error in session ${invocation.sessionId}:`);
console.error(` Error: ${input.error}`);
console.error(` Context: ${input.errorContext}`);
@@ -448,10 +479,11 @@ const session = await client.createSession({
if (ctx?.lastPrompt) {
console.error(` Last prompt: ${ctx.lastPrompt}...`);
}
-
+
return null;
},
},
+ onPermissionRequest: approveAll,
});
```
diff --git a/docs/hooks/index.md b/docs/hooks/index.md
index d83b11b2f..9434b3d94 100644
--- a/docs/hooks/index.md
+++ b/docs/hooks/index.md
@@ -25,7 +25,7 @@ Hooks allow you to intercept and customize the behavior of Copilot sessions at k
Node.js / TypeScript
```typescript
-import { CopilotClient } from "@github/copilot-sdk";
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
const client = new CopilotClient();
@@ -44,6 +44,7 @@ const session = await client.createSession({
return { additionalContext: "User prefers concise answers." };
},
},
+ onPermissionRequest: approveAll
});
```
@@ -170,6 +171,9 @@ This allows hooks to maintain state or perform session-specific logic.
### Logging All Tool Calls
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const session = await client.createSession({
hooks: {
onPreToolUse: async (input) => {
@@ -181,12 +185,16 @@ const session = await client.createSession({
return null;
},
},
+ onPermissionRequest: approveAll,
});
```
### Blocking Dangerous Tools
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const BLOCKED_TOOLS = ["shell", "bash", "exec"];
const session = await client.createSession({
@@ -201,12 +209,16 @@ const session = await client.createSession({
return { permissionDecision: "allow" };
},
},
+ onPermissionRequest: approveAll,
});
```
### Adding User Context
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const session = await client.createSession({
hooks: {
onSessionStart: async () => {
@@ -216,6 +228,7 @@ const session = await client.createSession({
};
},
},
+ onPermissionRequest: approveAll,
});
```
diff --git a/docs/hooks/post-tool-use.md b/docs/hooks/post-tool-use.md
index 029e9eb2f..51cc6521f 100644
--- a/docs/hooks/post-tool-use.md
+++ b/docs/hooks/post-tool-use.md
@@ -127,6 +127,9 @@ Return `null` or `undefined` to pass through the result unchanged. Otherwise, re
Node.js / TypeScript
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const session = await client.createSession({
hooks: {
onPostToolUse: async (input, invocation) => {
@@ -136,6 +139,7 @@ const session = await client.createSession({
return null; // Pass through unchanged
},
},
+ onPermissionRequest: approveAll,
});
```
@@ -253,6 +257,9 @@ var session = await client.CreateSessionAsync(new SessionConfig
### Redact Sensitive Data
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const SENSITIVE_PATTERNS = [
/api[_-]?key["\s:=]+["']?[\w-]+["']?/gi,
/password["\s:=]+["']?[\w-]+["']?/gi,
@@ -267,7 +274,7 @@ const session = await client.createSession({
for (const pattern of SENSITIVE_PATTERNS) {
redacted = redacted.replace(pattern, "[REDACTED]");
}
-
+
if (redacted !== input.toolResult) {
return { modifiedResult: redacted };
}
@@ -275,19 +282,23 @@ const session = await client.createSession({
return null;
},
},
+ onPermissionRequest: approveAll,
});
```
### Truncate Large Results
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const MAX_RESULT_LENGTH = 10000;
const session = await client.createSession({
hooks: {
onPostToolUse: async (input) => {
const resultStr = JSON.stringify(input.toolResult);
-
+
if (resultStr.length > MAX_RESULT_LENGTH) {
return {
modifiedResult: {
@@ -301,12 +312,16 @@ const session = await client.createSession({
return null;
},
},
+ onPermissionRequest: approveAll,
});
```
### Add Context Based on Results
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const session = await client.createSession({
hooks: {
onPostToolUse: async (input) => {
@@ -316,23 +331,27 @@ const session = await client.createSession({
additionalContext: "Tip: If the file doesn't exist, consider creating it or checking the path.",
};
}
-
+
// If shell command failed, add debugging hint
if (input.toolName === "shell" && input.toolResult?.exitCode !== 0) {
return {
additionalContext: "The command failed. Check if required dependencies are installed.",
};
}
-
+
return null;
},
},
+ onPermissionRequest: approveAll,
});
```
### Filter Error Stack Traces
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const session = await client.createSession({
hooks: {
onPostToolUse: async (input) => {
@@ -349,12 +368,15 @@ const session = await client.createSession({
return null;
},
},
+ onPermissionRequest: approveAll,
});
```
### Audit Trail for Compliance
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
interface AuditEntry {
timestamp: number;
sessionId: string;
@@ -364,6 +386,7 @@ interface AuditEntry {
success: boolean;
}
+const client = new CopilotClient();
const auditLog: AuditEntry[] = [];
const session = await client.createSession({
@@ -377,19 +400,23 @@ const session = await client.createSession({
result: input.toolResult,
success: !input.toolResult?.error,
});
-
+
// Optionally persist to database/file
await saveAuditLog(auditLog);
-
+
return null;
},
},
+ onPermissionRequest: approveAll,
});
```
### Suppress Noisy Results
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const NOISY_TOOLS = ["list_directory", "search_codebase"];
const session = await client.createSession({
@@ -397,10 +424,10 @@ const session = await client.createSession({
onPostToolUse: async (input) => {
if (NOISY_TOOLS.includes(input.toolName)) {
// Summarize instead of showing full result
- const items = Array.isArray(input.toolResult)
- ? input.toolResult
+ const items = Array.isArray(input.toolResult)
+ ? input.toolResult
: input.toolResult?.items || [];
-
+
return {
modifiedResult: {
summary: `Found ${items.length} items`,
@@ -411,6 +438,7 @@ const session = await client.createSession({
return null;
},
},
+ onPermissionRequest: approveAll,
});
```
diff --git a/docs/hooks/pre-tool-use.md b/docs/hooks/pre-tool-use.md
index e1bb97495..ab0587bfe 100644
--- a/docs/hooks/pre-tool-use.md
+++ b/docs/hooks/pre-tool-use.md
@@ -136,6 +136,9 @@ Return `null` or `undefined` to allow the tool to execute with no changes. Other
Node.js / TypeScript
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const session = await client.createSession({
hooks: {
onPreToolUse: async (input, invocation) => {
@@ -144,6 +147,7 @@ const session = await client.createSession({
return { permissionDecision: "allow" };
},
},
+ onPermissionRequest: approveAll,
});
```
@@ -264,6 +268,9 @@ var session = await client.CreateSessionAsync(new SessionConfig
### Block Specific Tools
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const BLOCKED_TOOLS = ["shell", "bash", "write_file", "delete_file"];
const session = await client.createSession({
@@ -278,12 +285,16 @@ const session = await client.createSession({
return { permissionDecision: "allow" };
},
},
+ onPermissionRequest: approveAll,
});
```
### Modify Tool Arguments
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const session = await client.createSession({
hooks: {
onPreToolUse: async (input) => {
@@ -301,12 +312,16 @@ const session = await client.createSession({
return { permissionDecision: "allow" };
},
},
+ onPermissionRequest: approveAll,
});
```
### Restrict File Access to Specific Directories
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const ALLOWED_DIRECTORIES = ["/home/user/projects", "/tmp"];
const session = await client.createSession({
@@ -314,10 +329,10 @@ const session = await client.createSession({
onPreToolUse: async (input) => {
if (input.toolName === "read_file" || input.toolName === "write_file") {
const args = input.toolArgs as { path: string };
- const isAllowed = ALLOWED_DIRECTORIES.some(dir =>
+ const isAllowed = ALLOWED_DIRECTORIES.some(dir =>
args.path.startsWith(dir)
);
-
+
if (!isAllowed) {
return {
permissionDecision: "deny",
@@ -328,12 +343,16 @@ const session = await client.createSession({
return { permissionDecision: "allow" };
},
},
+ onPermissionRequest: approveAll,
});
```
### Suppress Verbose Tool Output
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const VERBOSE_TOOLS = ["list_directory", "search_files"];
const session = await client.createSession({
@@ -345,12 +364,16 @@ const session = await client.createSession({
};
},
},
+ onPermissionRequest: approveAll,
});
```
### Add Context Based on Tool
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const session = await client.createSession({
hooks: {
onPreToolUse: async (input) => {
@@ -363,6 +386,7 @@ const session = await client.createSession({
return { permissionDecision: "allow" };
},
},
+ onPermissionRequest: approveAll,
});
```
diff --git a/docs/hooks/session-lifecycle.md b/docs/hooks/session-lifecycle.md
index 4efd33ccc..006583406 100644
--- a/docs/hooks/session-lifecycle.md
+++ b/docs/hooks/session-lifecycle.md
@@ -127,13 +127,16 @@ public delegate Task SessionStartHandler(
Node.js / TypeScript
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const session = await client.createSession({
hooks: {
onSessionStart: async (input, invocation) => {
console.log(`Session ${invocation.sessionId} started (${input.source})`);
-
+
const projectInfo = await detectProjectType(input.cwd);
-
+
return {
additionalContext: `
This is a ${projectInfo.type} project.
@@ -143,6 +146,7 @@ Package manager: ${projectInfo.packageManager}
};
},
},
+ onPermissionRequest: approveAll,
});
```
@@ -156,9 +160,9 @@ from copilot import PermissionHandler
async def on_session_start(input_data, invocation):
print(f"Session {invocation['session_id']} started ({input_data['source']})")
-
+
project_info = await detect_project_type(input_data["cwd"])
-
+
return {
"additionalContext": f"""
This is a {project_info['type']} project.
@@ -175,13 +179,16 @@ session = await client.create_session(on_permission_request=PermissionHandler.ap
#### Handle Session Resume
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const session = await client.createSession({
hooks: {
onSessionStart: async (input, invocation) => {
if (input.source === "resume") {
// Load previous session state
const previousState = await loadSessionState(invocation.sessionId);
-
+
return {
additionalContext: `
Session resumed. Previous context:
@@ -193,19 +200,23 @@ Session resumed. Previous context:
return null;
},
},
+ onPermissionRequest: approveAll,
});
```
#### Load User Preferences
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const session = await client.createSession({
hooks: {
onSessionStart: async () => {
const preferences = await loadUserPreferences();
-
+
const contextParts = [];
-
+
if (preferences.language) {
contextParts.push(`Preferred language: ${preferences.language}`);
}
@@ -215,12 +226,13 @@ const session = await client.createSession({
if (preferences.verbosity === "concise") {
contextParts.push("Keep responses brief and to the point.");
}
-
+
return {
additionalContext: contextParts.join("\n"),
};
},
},
+ onPermissionRequest: approveAll,
});
```
@@ -340,6 +352,9 @@ public delegate Task SessionEndHandler(
Node.js / TypeScript
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const sessionStartTimes = new Map();
const session = await client.createSession({
@@ -351,17 +366,18 @@ const session = await client.createSession({
onSessionEnd: async (input, invocation) => {
const startTime = sessionStartTimes.get(invocation.sessionId);
const duration = startTime ? input.timestamp - startTime : 0;
-
+
await recordMetrics({
sessionId: invocation.sessionId,
duration,
endReason: input.reason,
});
-
+
sessionStartTimes.delete(invocation.sessionId);
return null;
},
},
+ onPermissionRequest: approveAll,
});
```
@@ -382,13 +398,13 @@ async def on_session_start(input_data, invocation):
async def on_session_end(input_data, invocation):
start_time = session_start_times.get(invocation["session_id"])
duration = input_data["timestamp"] - start_time if start_time else 0
-
+
await record_metrics({
"session_id": invocation["session_id"],
"duration": duration,
"end_reason": input_data["reason"],
})
-
+
session_start_times.pop(invocation["session_id"], None)
return None
@@ -403,6 +419,9 @@ session = await client.create_session(on_permission_request=PermissionHandler.ap
#### Clean Up Resources
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const sessionResources = new Map();
const session = await client.createSession({
@@ -413,7 +432,7 @@ const session = await client.createSession({
},
onSessionEnd: async (input, invocation) => {
const resources = sessionResources.get(invocation.sessionId);
-
+
if (resources) {
// Clean up temp files
for (const file of resources.tempFiles) {
@@ -421,17 +440,21 @@ const session = await client.createSession({
}
sessionResources.delete(invocation.sessionId);
}
-
+
console.log(`Session ${invocation.sessionId} ended: ${input.reason}`);
return null;
},
},
+ onPermissionRequest: approveAll,
});
```
#### Save Session State for Resume
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const session = await client.createSession({
hooks: {
onSessionEnd: async (input, invocation) => {
@@ -446,21 +469,25 @@ const session = await client.createSession({
return null;
},
},
+ onPermissionRequest: approveAll
});
```
#### Log Session Summary
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const sessionData: Record = {};
const session = await client.createSession({
hooks: {
onSessionStart: async (input, invocation) => {
- sessionData[invocation.sessionId] = {
- prompts: 0,
- tools: 0,
- startTime: input.timestamp
+ sessionData[invocation.sessionId] = {
+ prompts: 0,
+ tools: 0,
+ startTime: input.timestamp
};
return null;
},
@@ -482,11 +509,12 @@ Session Summary:
Tool calls: ${data.tools}
End reason: ${input.reason}
`.trim());
-
+
delete sessionData[invocation.sessionId];
return null;
},
},
+ onPermissionRequest: approveAll,
});
```
diff --git a/docs/hooks/user-prompt-submitted.md b/docs/hooks/user-prompt-submitted.md
index 2aca7f1ce..502d6616f 100644
--- a/docs/hooks/user-prompt-submitted.md
+++ b/docs/hooks/user-prompt-submitted.md
@@ -125,6 +125,9 @@ Return `null` or `undefined` to use the prompt unchanged. Otherwise, return an o
Node.js / TypeScript
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const session = await client.createSession({
hooks: {
onUserPromptSubmitted: async (input, invocation) => {
@@ -132,6 +135,7 @@ const session = await client.createSession({
return null; // Pass through unchanged
},
},
+ onPermissionRequest: approveAll,
});
```
@@ -239,11 +243,14 @@ var session = await client.CreateSessionAsync(new SessionConfig
### Add Project Context
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const session = await client.createSession({
hooks: {
onUserPromptSubmitted: async (input) => {
const projectInfo = await getProjectInfo();
-
+
return {
additionalContext: `
Project: ${projectInfo.name}
@@ -253,12 +260,16 @@ Framework: ${projectInfo.framework}
};
},
},
+ onPermissionRequest: approveAll,
});
```
### Expand Shorthand Commands
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const SHORTCUTS: Record = {
"/fix": "Please fix the errors in the code",
"/explain": "Please explain this code in detail",
@@ -280,12 +291,16 @@ const session = await client.createSession({
return null;
},
},
+ onPermissionRequest: approveAll,
});
```
### Content Filtering
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const BLOCKED_PATTERNS = [
/password\s*[:=]/i,
/api[_-]?key\s*[:=]/i,
@@ -307,12 +322,16 @@ const session = await client.createSession({
return null;
},
},
+ onPermissionRequest: approveAll,
});
```
### Enforce Prompt Length Limits
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const MAX_PROMPT_LENGTH = 10000;
const session = await client.createSession({
@@ -328,46 +347,54 @@ const session = await client.createSession({
return null;
},
},
+ onPermissionRequest: approveAll,
});
```
### Add User Preferences
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
interface UserPreferences {
codeStyle: "concise" | "verbose";
preferredLanguage: string;
experienceLevel: "beginner" | "intermediate" | "expert";
}
+const client = new CopilotClient();
const session = await client.createSession({
hooks: {
onUserPromptSubmitted: async (input) => {
const prefs: UserPreferences = await loadUserPreferences();
-
+
const contextParts = [];
-
+
if (prefs.codeStyle === "concise") {
contextParts.push("User prefers concise code with minimal comments.");
} else {
contextParts.push("User prefers verbose code with detailed comments.");
}
-
+
if (prefs.experienceLevel === "beginner") {
contextParts.push("Explain concepts in simple terms.");
}
-
+
return {
additionalContext: contextParts.join(" "),
};
},
},
+ onPermissionRequest: approveAll,
});
```
### Rate Limiting
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const promptTimestamps: number[] = [];
const RATE_LIMIT = 10; // prompts
const RATE_WINDOW = 60000; // 1 minute
@@ -376,29 +403,33 @@ const session = await client.createSession({
hooks: {
onUserPromptSubmitted: async (input) => {
const now = Date.now();
-
+
// Remove timestamps outside the window
while (promptTimestamps.length > 0 && promptTimestamps[0] < now - RATE_WINDOW) {
promptTimestamps.shift();
}
-
+
if (promptTimestamps.length >= RATE_LIMIT) {
return {
reject: true,
rejectReason: `Rate limit exceeded. Please wait before sending more prompts.`,
};
}
-
+
promptTimestamps.push(now);
return null;
},
},
+ onPermissionRequest: approveAll,
});
```
### Prompt Templates
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const TEMPLATES: Record string> = {
"bug:": (desc) => `I found a bug: ${desc}
@@ -429,6 +460,7 @@ const session = await client.createSession({
return null;
},
},
+ onPermissionRequest: approveAll,
});
```
diff --git a/docs/integrations/microsoft-agent-framework.md b/docs/integrations/microsoft-agent-framework.md
index 8e794759b..87fd24a09 100644
--- a/docs/integrations/microsoft-agent-framework.md
+++ b/docs/integrations/microsoft-agent-framework.md
@@ -159,8 +159,9 @@ You can also use Copilot SDK's native tool definition alongside MAF tools:
Node.js / TypeScript (standalone SDK)
```typescript
-import { CopilotClient, DefineTool } from "@github/copilot-sdk";
+import { CopilotClient, DefineTool, approveAll } from "@github/copilot-sdk";
+const client = new CopilotClient();
const getWeather = DefineTool({
name: "GetWeather",
description: "Get the current weather for a given location.",
@@ -168,11 +169,10 @@ const getWeather = DefineTool({
execute: async ({ location }) => `The weather in ${location} is sunny, 25°C.`,
});
-const client = new CopilotClient();
const session = await client.createSession({
model: "gpt-4.1",
tools: [getWeather],
- onPermissionRequest: async () => ({ kind: "approved" }),
+ onPermissionRequest: approveAll,
});
await session.sendAndWait({ prompt: "What's the weather like in Seattle?" });
@@ -351,13 +351,13 @@ You can also stream directly through the Copilot SDK without MAF:
Node.js / TypeScript (standalone SDK)
```typescript
-import { CopilotClient } from "@github/copilot-sdk";
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
const client = new CopilotClient();
const session = await client.createSession({
model: "gpt-4.1",
streaming: true,
- onPermissionRequest: async () => ({ kind: "approved" }),
+ onPermissionRequest: approveAll,
});
session.on("assistant.message_delta", (event) => {
@@ -401,12 +401,12 @@ Use the MAF wrapper when you need to compose Copilot with other providers in orc
```typescript
// Standalone SDK — full control, simpler setup
-import { CopilotClient } from "@github/copilot-sdk";
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
const client = new CopilotClient();
const session = await client.createSession({
model: "gpt-4.1",
- onPermissionRequest: async () => ({ kind: "approved" }),
+ onPermissionRequest: approveAll,
});
const response = await session.sendAndWait({ prompt: "Explain this code" });
```
diff --git a/docs/setup/azure-managed-identity.md b/docs/setup/azure-managed-identity.md
index 40d87c5ba..c3d1821c1 100644
--- a/docs/setup/azure-managed-identity.md
+++ b/docs/setup/azure-managed-identity.md
@@ -124,7 +124,7 @@ class ManagedIdentityCopilotAgent:
```typescript
import { DefaultAzureCredential } from "@azure/identity";
-import { CopilotClient } from "@github/copilot-sdk";
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
const credential = new DefaultAzureCredential();
const tokenResponse = await credential.getToken(
@@ -141,6 +141,7 @@ const session = await client.createSession({
bearerToken: tokenResponse.token,
wireApi: "responses",
},
+ onPermissionRequest: approveAll
});
const response = await session.sendAndWait({ prompt: "Hello!" });
diff --git a/docs/setup/backend-services.md b/docs/setup/backend-services.md
index 735adf4ff..b235019c7 100644
--- a/docs/setup/backend-services.md
+++ b/docs/setup/backend-services.md
@@ -90,7 +90,7 @@ Restart=always
Node.js / TypeScript
```typescript
-import { CopilotClient } from "@github/copilot-sdk";
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
const client = new CopilotClient({
cliUrl: "localhost:4321",
@@ -99,6 +99,7 @@ const client = new CopilotClient({
const session = await client.createSession({
sessionId: `user-${userId}-${Date.now()}`,
model: "gpt-4.1",
+ onPermissionRequest: approveAll
});
const response = await session.sendAndWait({ prompt: req.body.message });
@@ -254,6 +255,9 @@ copilot --headless --port 4321
Pass individual user tokens when creating sessions. See [GitHub OAuth](./github-oauth.md) for the full flow.
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
// Your API receives user tokens from your auth layer
app.post("/chat", authMiddleware, async (req, res) => {
const client = new CopilotClient({
@@ -265,6 +269,7 @@ app.post("/chat", authMiddleware, async (req, res) => {
const session = await client.createSession({
sessionId: `user-${req.user.id}-chat`,
model: "gpt-4.1",
+ onPermissionRequest: approveAll,
});
const response = await session.sendAndWait({
@@ -280,6 +285,8 @@ app.post("/chat", authMiddleware, async (req, res) => {
Use your own API keys for the model provider. See [BYOK](../auth/byok.md) for details.
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
const client = new CopilotClient({
cliUrl: "localhost:4321",
});
@@ -291,6 +298,7 @@ const session = await client.createSession({
baseUrl: "https://api.openai.com/v1",
apiKey: process.env.OPENAI_API_KEY,
},
+ onPermissionRequest: approveAll,
});
```
@@ -316,7 +324,7 @@ flowchart TB
```typescript
import express from "express";
-import { CopilotClient } from "@github/copilot-sdk";
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
const app = express();
app.use(express.json());
@@ -337,6 +345,7 @@ app.post("/api/chat", async (req, res) => {
session = await client.createSession({
sessionId,
model: "gpt-4.1",
+ onPermissionRequest: approveAll
});
}
@@ -353,7 +362,7 @@ app.listen(3000);
### Background Worker
```typescript
-import { CopilotClient } from "@github/copilot-sdk";
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
const client = new CopilotClient({
cliUrl: process.env.CLI_URL || "localhost:4321",
@@ -364,6 +373,7 @@ async function processJob(job: Job) {
const session = await client.createSession({
sessionId: `job-${job.id}`,
model: "gpt-4.1",
+ onPermissionRequest: approveAll
});
const response = await session.sendAndWait({
diff --git a/docs/setup/bundled-cli.md b/docs/setup/bundled-cli.md
index cdfe6df81..427177255 100644
--- a/docs/setup/bundled-cli.md
+++ b/docs/setup/bundled-cli.md
@@ -64,7 +64,7 @@ npm install @github/copilot
Node.js / TypeScript
```typescript
-import { CopilotClient } from "@github/copilot-sdk";
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
import path from "path";
const client = new CopilotClient({
@@ -72,7 +72,7 @@ const client = new CopilotClient({
cliPath: path.join(__dirname, "vendor", "copilot"),
});
-const session = await client.createSession({ model: "gpt-4.1" });
+const session = await client.createSession({ model: "gpt-4.1", onPermissionRequest: approveAll });
const response = await session.sendAndWait({ prompt: "Hello!" });
console.log(response?.data.content);
@@ -217,6 +217,8 @@ const client = new CopilotClient({
If you manage your own model provider keys, users don't need GitHub accounts at all:
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
const client = new CopilotClient({
cliPath: path.join(__dirname, "vendor", "copilot"),
});
@@ -228,6 +230,7 @@ const session = await client.createSession({
baseUrl: "https://api.openai.com/v1",
apiKey: process.env.OPENAI_API_KEY,
},
+ onPermissionRequest: approveAll,
});
```
@@ -238,6 +241,8 @@ See the **[BYOK guide](../auth/byok.md)** for full details.
Bundled apps typically want named sessions so users can resume conversations:
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
const client = new CopilotClient({
cliPath: path.join(__dirname, "vendor", "copilot"),
});
@@ -247,6 +252,7 @@ const sessionId = `project-${projectName}`;
const session = await client.createSession({
sessionId,
model: "gpt-4.1",
+ onPermissionRequest: approveAll,
});
// User closes app...
diff --git a/docs/setup/github-oauth.md b/docs/setup/github-oauth.md
index 81d2b25a2..1db796ec7 100644
--- a/docs/setup/github-oauth.md
+++ b/docs/setup/github-oauth.md
@@ -119,7 +119,7 @@ Create a SDK client for each authenticated user, passing their token:
Node.js / TypeScript
```typescript
-import { CopilotClient } from "@github/copilot-sdk";
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
// Create a client for an authenticated user
function createClientForUser(userToken: string): CopilotClient {
@@ -134,6 +134,7 @@ const client = createClientForUser("gho_user_access_token");
const session = await client.createSession({
sessionId: `user-${userId}-session`,
model: "gpt-4.1",
+ onPermissionRequest: approveAll
});
const response = await session.sendAndWait({ prompt: "Hello!" });
diff --git a/docs/setup/local-cli.md b/docs/setup/local-cli.md
index bb95a4d38..97ba8c700 100644
--- a/docs/setup/local-cli.md
+++ b/docs/setup/local-cli.md
@@ -34,10 +34,10 @@ The default configuration requires no options at all:
Node.js / TypeScript
```typescript
-import { CopilotClient } from "@github/copilot-sdk";
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
const client = new CopilotClient();
-const session = await client.createSession({ model: "gpt-4.1" });
+const session = await client.createSession({ model: "gpt-4.1", onPermissionRequest: approveAll });
const response = await session.sendAndWait({ prompt: "Hello!" });
console.log(response?.data.content);
@@ -192,10 +192,14 @@ The SDK picks these up automatically — no code changes needed.
With the local CLI, sessions default to ephemeral. To create resumable sessions, provide your own session ID:
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
// Create a named session
const session = await client.createSession({
sessionId: "my-project-analysis",
model: "gpt-4.1",
+ onPermissionRequest: approveAll,
});
// Later, resume it
diff --git a/docs/setup/scaling.md b/docs/setup/scaling.md
index 325d9244d..0fbb544d6 100644
--- a/docs/setup/scaling.md
+++ b/docs/setup/scaling.md
@@ -279,6 +279,8 @@ flowchart TB
```typescript
// Route sessions to CLI servers
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
class CLILoadBalancer {
private servers: string[];
private currentIndex = 0;
@@ -310,6 +312,8 @@ class CLILoadBalancer {
}
}
+const client = new CopilotClient();
+
const lb = new CLILoadBalancer([
"cli-1:4321",
"cli-2:4321",
@@ -323,6 +327,7 @@ app.post("/chat", async (req, res) => {
const session = await client.createSession({
sessionId: `user-${req.user.id}-chat`,
model: "gpt-4.1",
+ onPermissionRequest: approveAll,
});
const response = await session.sendAndWait({ prompt: req.body.message });
@@ -379,6 +384,10 @@ flowchart TB
**Session lifecycle management** is key to vertical scaling:
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
+
// Limit concurrent active sessions
class SessionManager {
private activeSessions = new Map();
@@ -403,6 +412,7 @@ class SessionManager {
const session = await client.createSession({
sessionId,
model: "gpt-4.1",
+ onPermissionRequest: approveAll,
});
this.activeSessions.set(sessionId, session);
@@ -446,9 +456,13 @@ flowchart LR
For stateless API endpoints where each request is independent:
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
app.post("/api/analyze", async (req, res) => {
const session = await client.createSession({
model: "gpt-4.1",
+ onPermissionRequest: approveAll,
});
try {
@@ -467,6 +481,9 @@ app.post("/api/analyze", async (req, res) => {
For conversational interfaces or long-running workflows:
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
// Create a resumable session
app.post("/api/chat/start", async (req, res) => {
const sessionId = `user-${req.user.id}-${Date.now()}`;
@@ -478,6 +495,7 @@ app.post("/api/chat/start", async (req, res) => {
enabled: true,
backgroundCompactionThreshold: 0.80,
},
+ onPermissionRequest: approveAll,
});
res.json({ sessionId });
diff --git a/docs/troubleshooting/compatibility.md b/docs/troubleshooting/compatibility.md
index 1a322b88c..3dfc38e28 100644
--- a/docs/troubleshooting/compatibility.md
+++ b/docs/troubleshooting/compatibility.md
@@ -189,6 +189,9 @@ The SDK uses a **deny-by-default** permission model. All permission requests (fi
Instead of `--allow-all-paths` or `--yolo`, use the permission handler:
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const session = await client.createSession({
onPermissionRequest: approveAll,
});
@@ -213,12 +216,16 @@ Instead of `/compact`, configure automatic compaction or trigger it manually:
```typescript
// Automatic compaction via config
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const session = await client.createSession({
infiniteSessions: {
enabled: true,
backgroundCompactionThreshold: 0.80, // Start background compaction at 80% context utilization
bufferExhaustionThreshold: 0.95, // Block and compact at 95% context utilization
},
+ onPermissionRequest: approveAll,
});
// Manual compaction (experimental)
diff --git a/docs/troubleshooting/debugging.md b/docs/troubleshooting/debugging.md
index 146d3fd5a..ec877709c 100644
--- a/docs/troubleshooting/debugging.md
+++ b/docs/troubleshooting/debugging.md
@@ -393,10 +393,14 @@ const client = new CopilotClient({
1. **Verify tool registration:**
```typescript
+ import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+ const client = new CopilotClient();
const session = await client.createSession({
tools: [myTool],
+ onPermissionRequest: approveAll,
});
-
+
// Check registered tools
console.log("Registered tools:", session.getTools?.());
```
@@ -424,7 +428,7 @@ const client = new CopilotClient({
handler: async (args) => {
// Must return something JSON-serializable
return { success: true, data: "result" };
-
+
// Don't return undefined or non-serializable objects
}
```
diff --git a/nodejs/README.md b/nodejs/README.md
index e9d23c529..df2435531 100644
--- a/nodejs/README.md
+++ b/nodejs/README.md
@@ -60,6 +60,9 @@ await client.stop();
Sessions also support `Symbol.asyncDispose` for use with [`await using`](https://github.com/tc39/proposal-explicit-resource-management) (TypeScript 5.2+/Node.js 18.0+):
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
await using session = await client.createSession({ model: "gpt-5", onPermissionRequest: approveAll });
// session is automatically disconnected when leaving scope
```
@@ -338,9 +341,13 @@ await session.send({ prompt: "What does the most recent jpg in this directory po
Enable streaming to receive assistant response chunks as they're generated:
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const session = await client.createSession({
model: "gpt-5",
streaming: true,
+ onPermissionRequest: approveAll,
});
// Wait for completion using typed event handlers
@@ -408,7 +415,7 @@ You can let the CLI call back into your process when the model needs capabilitie
```ts
import { z } from "zod";
-import { CopilotClient, defineTool } from "@github/copilot-sdk";
+import { CopilotClient, defineTool, approveAll } from "@github/copilot-sdk";
const session = await client.createSession({
model: "gpt-5",
@@ -424,6 +431,7 @@ const session = await client.createSession({
},
}),
],
+ onPermissionRequest: approveAll
});
```
@@ -460,6 +468,9 @@ defineTool("safe_lookup", {
Control the system prompt using `systemMessage` in session config:
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const session = await client.createSession({
model: "gpt-5",
systemMessage: {
@@ -470,6 +481,7 @@ const session = await client.createSession({
`,
},
+ onPermissionRequest: approveAll,
});
```
@@ -478,12 +490,16 @@ The SDK auto-injects environment context, tool instructions, and security guardr
For full control (removes all guardrails), use `mode: "replace"`:
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const session = await client.createSession({
model: "gpt-5",
systemMessage: {
mode: "replace",
content: "You are a helpful assistant.",
},
+ onPermissionRequest: approveAll,
});
```
@@ -492,8 +508,12 @@ const session = await client.createSession({
By default, sessions use **infinite sessions** which automatically manage context window limits through background compaction and persist state to a workspace directory.
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
+
// Default: infinite sessions enabled with default thresholds
-const session = await client.createSession({ model: "gpt-5" });
+const session = await client.createSession({ model: "gpt-5",onPermissionRequest: approveAll, });
// Access the workspace path for checkpoints and files
console.log(session.workspacePath);
@@ -507,12 +527,14 @@ const session = await client.createSession({
backgroundCompactionThreshold: 0.80, // Start compacting at 80% context usage
bufferExhaustionThreshold: 0.95, // Block at 95% until compaction completes
},
+ onPermissionRequest: approveAll,
});
// Disable infinite sessions
const session = await client.createSession({
model: "gpt-5",
infiniteSessions: { enabled: false },
+ onPermissionRequest: approveAll
});
```
@@ -524,8 +546,11 @@ When enabled, sessions emit compaction events:
### Multiple Sessions
```typescript
-const session1 = await client.createSession({ model: "gpt-5" });
-const session2 = await client.createSession({ model: "claude-sonnet-4.5" });
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
+const session1 = await client.createSession({ model: "gpt-5", onPermissionRequest: approveAll, });
+const session2 = await client.createSession({ model: "claude-sonnet-4.5", onPermissionRequest: approveAll, });
// Both sessions are independent
await session1.sendAndWait({ prompt: "Hello from session 1" });
@@ -535,9 +560,13 @@ await session2.sendAndWait({ prompt: "Hello from session 2" });
### Custom Session IDs
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const session = await client.createSession({
sessionId: "my-custom-session-id",
model: "gpt-5",
+ onPermissionRequest: approveAll,
});
```
@@ -572,6 +601,9 @@ The SDK supports custom OpenAI-compatible API providers (BYOK - Bring Your Own K
**Example with Ollama:**
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const session = await client.createSession({
model: "deepseek-coder-v2:16b", // Required when using custom provider
provider: {
@@ -579,6 +611,7 @@ const session = await client.createSession({
baseUrl: "http://localhost:11434/v1", // Ollama endpoint
// apiKey not required for Ollama
},
+ onPermissionRequest: approveAll,
});
await session.sendAndWait({ prompt: "Hello!" });
@@ -587,6 +620,9 @@ await session.sendAndWait({ prompt: "Hello!" });
**Example with custom OpenAI-compatible API:**
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const session = await client.createSession({
model: "gpt-4",
provider: {
@@ -594,12 +630,16 @@ const session = await client.createSession({
baseUrl: "https://my-api.example.com/v1",
apiKey: process.env.MY_API_KEY,
},
+ onPermissionRequest: approveAll,
});
```
**Example with Azure OpenAI:**
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const session = await client.createSession({
model: "gpt-4",
provider: {
@@ -610,6 +650,7 @@ const session = await client.createSession({
apiVersion: "2024-10-21",
},
},
+ onPermissionRequest: approveAll,
});
```
@@ -674,6 +715,7 @@ Use the built-in `approveAll` helper to allow every tool call without any checks
```typescript
import { CopilotClient, approveAll } from "@github/copilot-sdk";
+const client = new CopilotClient();
const session = await client.createSession({
model: "gpt-5",
onPermissionRequest: approveAll,
@@ -685,8 +727,9 @@ const session = await client.createSession({
Provide your own function to inspect each request and apply custom logic:
```typescript
-import type { PermissionRequest, PermissionRequestResult } from "@github/copilot-sdk";
+import type { CopilotClient, PermissionRequest, PermissionRequestResult } from "@github/copilot-sdk";
+const client = new CopilotClient();
const session = await client.createSession({
model: "gpt-5",
onPermissionRequest: (request: PermissionRequest, invocation): PermissionRequestResult => {
@@ -711,7 +754,7 @@ const session = await client.createSession({
}
return { kind: "approved" };
- },
+ }
});
```
@@ -730,6 +773,9 @@ const session = await client.createSession({
Pass `onPermissionRequest` when resuming a session too — it is required:
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const session = await client.resumeSession("session-id", {
onPermissionRequest: approveAll,
});
@@ -744,6 +790,9 @@ To let a specific custom tool bypass the permission prompt entirely, set `skipPe
Enable the agent to ask questions to the user using the `ask_user` tool by providing an `onUserInputRequest` handler:
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const session = await client.createSession({
model: "gpt-5",
onUserInputRequest: async (request, invocation) => {
@@ -762,6 +811,7 @@ const session = await client.createSession({
wasFreeform: true, // Whether the answer was freeform (not from choices)
};
},
+ onPermissionRequest: approveAll,
});
```
@@ -770,6 +820,9 @@ const session = await client.createSession({
Hook into session lifecycle events by providing handlers in the `hooks` configuration:
```typescript
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
+
+const client = new CopilotClient();
const session = await client.createSession({
model: "gpt-5",
hooks: {
@@ -822,6 +875,7 @@ const session = await client.createSession({
};
},
},
+ onPermissionRequest: approveAll,
});
```
diff --git a/nodejs/examples/basic-example.ts b/nodejs/examples/basic-example.ts
index c20a85af0..dc4d002c3 100644
--- a/nodejs/examples/basic-example.ts
+++ b/nodejs/examples/basic-example.ts
@@ -3,7 +3,7 @@
*--------------------------------------------------------------------------------------------*/
import { z } from "zod";
-import { CopilotClient, defineTool } from "../src/index.js";
+import { CopilotClient, defineTool, approveAll } from "../src/index.js";
console.log("🚀 Starting Copilot SDK Example\n");
@@ -22,7 +22,7 @@ const lookupFactTool = defineTool("lookup_fact", {
// Create client - will auto-start CLI server (searches PATH for "copilot")
const client = new CopilotClient({ logLevel: "info" });
-const session = await client.createSession({ tools: [lookupFactTool] });
+const session = await client.createSession({ tools: [lookupFactTool], onPermissionRequest: approveAll });
console.log(`✅ Session created: ${session.sessionId}\n`);
// Listen to events