Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 84 additions & 2 deletions dotnet/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,11 @@ using GitHub.Copilot.SDK;
await using var client = new CopilotClient();
await client.StartAsync();

// Create a session
// Create a session (OnPermissionRequest is required)
await using var session = await client.CreateSessionAsync(new SessionConfig
{
Model = "gpt-5"
Model = "gpt-5",
OnPermissionRequest = PermissionHandler.ApproveAll,
});

// Wait for response using session.idle event
Expand Down Expand Up @@ -110,13 +111,18 @@ Create a new conversation session.
- `Provider` - Custom API provider configuration (BYOK)
- `Streaming` - Enable streaming of response chunks (default: false)
- `InfiniteSessions` - Configure automatic context compaction (see below)
- `OnPermissionRequest` - **Required.** Handler called before each tool execution to approve or deny it. Use `PermissionHandler.ApproveAll` to allow everything, or provide a custom function for fine-grained control. See [Permission Handling](#permission-handling) section.
- `OnUserInputRequest` - Handler for user input requests from the agent (enables ask_user tool). See [User Input Requests](#user-input-requests) section.
- `Hooks` - Hook handlers for session lifecycle events. See [Session Hooks](#session-hooks) section.

##### `ResumeSessionAsync(string sessionId, ResumeSessionConfig? config = null): Task<CopilotSession>`

Resume an existing session. Returns the session with `WorkspacePath` populated if infinite sessions were enabled.

**ResumeSessionConfig:**

- `OnPermissionRequest` - **Required.** Handler called before each tool execution to approve or deny it. See [Permission Handling](#permission-handling) section.

##### `PingAsync(string? message = null): Task<PingResponse>`

Ping the server to check connectivity.
Expand Down Expand Up @@ -573,6 +579,82 @@ Trace context (`traceparent`/`tracestate`) is automatically propagated between t

No extra dependencies — uses built-in `System.Diagnostics.Activity`.

## Permission Handling

An `OnPermissionRequest` handler is **required** whenever you create or resume a session. The handler is called before the agent executes each tool (file writes, shell commands, custom tools, etc.) and must return a decision.

### Approve All (simplest)

Use the built-in `PermissionHandler.ApproveAll` helper to allow every tool call without any checks:

```csharp
using GitHub.Copilot.SDK;

var session = await client.CreateSessionAsync(new SessionConfig
{
Model = "gpt-5",
OnPermissionRequest = PermissionHandler.ApproveAll,
});
```

### Custom Permission Handler

Provide your own `PermissionRequestHandler` delegate to inspect each request and apply custom logic:

```csharp
var session = await client.CreateSessionAsync(new SessionConfig
{
Model = "gpt-5",
OnPermissionRequest = async (request, invocation) =>
{
// request.Kind — what type of operation is being requested:
// PermissionRequestKind.Shell — executing a shell command
// PermissionRequestKind.Write — writing or editing a file
// PermissionRequestKind.Read — reading a file
// PermissionRequestKind.Mcp — calling an MCP tool
// PermissionRequestKind.CustomTool — calling one of your registered tools
// PermissionRequestKind.Url — fetching a URL
// request.ToolCallId — the tool call that triggered this request
// request.ToolName — name of the tool (for custom-tool / mcp)
// request.FileName — file being written (for write)
// request.FullCommandText — full shell command text (for shell)

if (request.Kind == PermissionRequestKind.Shell)
Comment thread
jamesmontemagno marked this conversation as resolved.
Outdated
{
// Deny shell commands
return new PermissionRequestResult { Kind = PermissionRequestResultKind.DeniedInteractivelyByUser };
}

return new PermissionRequestResult { Kind = PermissionRequestResultKind.Approved };
}
});
```

### Permission Result Kinds

| Value | Meaning |
|-------|---------|
| `PermissionRequestResultKind.Approved` | Allow the tool to run |
| `PermissionRequestResultKind.DeniedInteractivelyByUser` | User explicitly denied the request |
| `PermissionRequestResultKind.DeniedCouldNotRequestFromUser` | No approval rule matched and user could not be asked |
| `PermissionRequestResultKind.DeniedByRules` | Denied by a policy rule |
| `PermissionRequestResultKind.NoResult` | No decision (treated as denied) |
Comment thread
jamesmontemagno marked this conversation as resolved.
Outdated

### Resuming Sessions

Pass `OnPermissionRequest` when resuming a session too — it is required:

```csharp
var session = await client.ResumeSessionAsync("session-id", new ResumeSessionConfig
{
OnPermissionRequest = PermissionHandler.ApproveAll,
});
```

### Per-Tool Skip Permission

To let a specific custom tool bypass the permission prompt entirely, set `skip_permission = true` in the tool's `AdditionalProperties`. See [Skipping Permission Prompts](#skipping-permission-prompts) under Tools.

## User Input Requests

Enable the agent to ask questions to the user using the `ask_user` tool by providing an `OnUserInputRequest` handler:
Expand Down
76 changes: 74 additions & 2 deletions go/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,10 @@ func main() {
}
defer client.Stop()

// Create a session
// Create a session (OnPermissionRequest is required)
session, err := client.CreateSession(context.Background(), &copilot.SessionConfig{
Model: "gpt-5",
Model: "gpt-5",
OnPermissionRequest: copilot.PermissionHandler.ApproveAll,
})
if err != nil {
log.Fatal(err)
Expand Down Expand Up @@ -153,11 +154,13 @@ Event types: `SessionLifecycleCreated`, `SessionLifecycleDeleted`, `SessionLifec
- `Provider` (\*ProviderConfig): Custom API provider configuration (BYOK). See [Custom Providers](#custom-providers) section.
- `Streaming` (bool): Enable streaming delta events
- `InfiniteSessions` (\*InfiniteSessionConfig): Automatic context compaction configuration
- `OnPermissionRequest` (PermissionHandlerFunc): **Required.** Handler called before each tool execution to approve or deny it. Use `copilot.PermissionHandler.ApproveAll` to allow everything, or provide a custom function for fine-grained control. See [Permission Handling](#permission-handling) section.
- `OnUserInputRequest` (UserInputHandler): Handler for user input requests from the agent (enables ask_user tool). See [User Input Requests](#user-input-requests) section.
- `Hooks` (\*SessionHooks): Hook handlers for session lifecycle events. See [Session Hooks](#session-hooks) section.

**ResumeSessionConfig:**

- `OnPermissionRequest` (PermissionHandlerFunc): **Required.** Handler called before each tool execution to approve or deny it. See [Permission Handling](#permission-handling) section.
- `Tools` ([]Tool): Tools to expose when resuming
- `ReasoningEffort` (string): Reasoning effort level for models that support it
- `Provider` (\*ProviderConfig): Custom API provider configuration (BYOK). See [Custom Providers](#custom-providers) section.
Expand Down Expand Up @@ -499,6 +502,75 @@ Trace context (`traceparent`/`tracestate`) is automatically propagated between t

Dependency: `go.opentelemetry.io/otel`

## Permission Handling

An `OnPermissionRequest` handler is **required** whenever you create or resume a session. The handler is called before the agent executes each tool (file writes, shell commands, custom tools, etc.) and must return a decision.

### Approve All (simplest)

Use the built-in `PermissionHandler.ApproveAll` helper to allow every tool call without any checks:

```go
session, err := client.CreateSession(context.Background(), &copilot.SessionConfig{
Model: "gpt-5",
OnPermissionRequest: copilot.PermissionHandler.ApproveAll,
})
```

### Custom Permission Handler

Provide your own `PermissionHandlerFunc` to inspect each request and apply custom logic:

```go
session, err := client.CreateSession(context.Background(), &copilot.SessionConfig{
Model: "gpt-5",
OnPermissionRequest: func(request copilot.PermissionRequest, invocation copilot.PermissionInvocation) (copilot.PermissionRequestResult, error) {
// request.Kind — what type of operation is being requested:
// copilot.KindShell — executing a shell command
// copilot.Write — writing or editing a file
// copilot.Read — reading a file
// copilot.MCP — calling an MCP tool
// copilot.CustomTool — calling one of your registered tools
// copilot.URL — fetching a URL
Comment thread
jamesmontemagno marked this conversation as resolved.
// request.ToolCallID — pointer to the tool call that triggered this request
// request.ToolName — pointer to the name of the tool (for custom-tool / mcp)
// request.FileName — pointer to the file being written (for write)
// request.FullCommandText — pointer to the full shell command (for shell)

if request.Kind == copilot.KindShell {
// Deny shell commands
return copilot.PermissionRequestResult{Kind: copilot.PermissionRequestResultKindDeniedInteractivelyByUser}, nil
}

return copilot.PermissionRequestResult{Kind: copilot.PermissionRequestResultKindApproved}, nil
},
})
```

### Permission Result Kinds

| Constant | Meaning |
|----------|---------|
| `PermissionRequestResultKindApproved` | Allow the tool to run |
| `PermissionRequestResultKindDeniedInteractivelyByUser` | User explicitly denied the request |
| `PermissionRequestResultKindDeniedCouldNotRequestFromUser` | No approval rule matched and user could not be asked |
| `PermissionRequestResultKindDeniedByRules` | Denied by a policy rule |
| `PermissionRequestResultKindNoResult` | No decision (treated as denied) |
Comment thread
jamesmontemagno marked this conversation as resolved.
Outdated

### Resuming Sessions

Pass `OnPermissionRequest` when resuming a session too — it is required:

```go
session, err := client.ResumeSession(context.Background(), sessionID, &copilot.ResumeSessionConfig{
OnPermissionRequest: copilot.PermissionHandler.ApproveAll,
})
```

### Per-Tool Skip Permission

To let a specific custom tool bypass the permission prompt entirely, set `SkipPermission = true` on the tool. See [Skipping Permission Prompts](#skipping-permission-prompts) under Tools.

## User Input Requests

Enable the agent to ask questions to the user using the `ask_user` tool by providing an `OnUserInputRequest` handler:
Expand Down
81 changes: 78 additions & 3 deletions nodejs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,16 @@ npm start
## Quick Start

```typescript
import { CopilotClient } from "@github/copilot-sdk";
import { CopilotClient, approveAll } from "@github/copilot-sdk";

// Create and start client
const client = new CopilotClient();
await client.start();

// Create a session
// Create a session (onPermissionRequest is required)
const session = await client.createSession({
model: "gpt-5",
onPermissionRequest: approveAll,
});

// Wait for response using typed event handlers
Expand All @@ -59,7 +60,7 @@ 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
await using session = await client.createSession({ model: "gpt-5" });
await using session = await client.createSession({ model: "gpt-5", onPermissionRequest: approveAll });
// session is automatically disconnected when leaving scope
```

Expand Down Expand Up @@ -114,6 +115,7 @@ Create a new conversation session.
- `systemMessage?: SystemMessageConfig` - System message customization (see below)
- `infiniteSessions?: InfiniteSessionConfig` - Configure automatic context compaction (see below)
- `provider?: ProviderConfig` - Custom API provider configuration (BYOK - Bring Your Own Key). See [Custom Providers](#custom-providers) section.
- `onPermissionRequest: PermissionHandler` - **Required.** Handler called before each tool execution to approve or deny it. Use `approveAll` to allow everything, or provide a custom function for fine-grained control. See [Permission Handling](#permission-handling) section.
- `onUserInputRequest?: UserInputHandler` - Handler for user input requests from the agent. Enables the `ask_user` tool. See [User Input Requests](#user-input-requests) section.
- `hooks?: SessionHooks` - Hook handlers for session lifecycle events. See [Session Hooks](#session-hooks) section.

Expand Down Expand Up @@ -648,6 +650,79 @@ const client = new CopilotClient({

Inbound trace context from the CLI is available on the `ToolInvocation` object passed to tool handlers as `traceparent` and `tracestate` fields. See the [OpenTelemetry guide](../docs/observability/opentelemetry.md) for a full wire-up example.

## Permission Handling

An `onPermissionRequest` handler is **required** whenever you create or resume a session. The handler is called before the agent executes each tool (file writes, shell commands, custom tools, etc.) and must return a decision.

### Approve All (simplest)

Use the built-in `approveAll` helper to allow every tool call without any checks:

```typescript
import { CopilotClient, approveAll } from "@github/copilot-sdk";

const session = await client.createSession({
model: "gpt-5",
onPermissionRequest: approveAll,
});
```

### Custom Permission Handler

Provide your own function to inspect each request and apply custom logic:

```typescript
import type { PermissionRequest, PermissionRequestResult } from "@github/copilot-sdk";

const session = await client.createSession({
model: "gpt-5",
onPermissionRequest: (request: PermissionRequest, invocation): PermissionRequestResult => {
// request.kind — what type of operation is being requested:
// "shell" — executing a shell command
// "write" — writing or editing a file
// "read" — reading a file
// "mcp" — calling an MCP tool
// "custom-tool" — calling one of your registered tools
// "url" — fetching a URL
Comment thread
jamesmontemagno marked this conversation as resolved.
// request.toolCallId — the tool call that triggered this request
// request.toolName — name of the tool (for custom-tool / mcp)
// request.fileName — file being written (for write)
// request.fullCommandText — full shell command (for shell)

if (request.kind === "shell") {
// Deny shell commands
return { kind: "denied-interactively-by-user" };
}

return { kind: "approved" };
},
});
```

### Permission Result Kinds

| Kind | Meaning |
|------|---------|
| `"approved"` | Allow the tool to run |
| `"denied-interactively-by-user"` | User explicitly denied the request |
| `"denied-no-approval-rule-and-could-not-request-from-user"` | No approval rule matched and user could not be asked |
| `"denied-by-rules"` | Denied by a policy rule |
| `"denied-by-content-exclusion-policy"` | Denied due to a content exclusion policy |

Comment thread
jamesmontemagno marked this conversation as resolved.
Outdated
### Resuming Sessions

Pass `onPermissionRequest` when resuming a session too — it is required:

```typescript
const session = await client.resumeSession("session-id", {
onPermissionRequest: approveAll,
});
```

### Per-Tool Skip Permission

To let a specific custom tool bypass the permission prompt entirely, set `skipPermission: true` on the tool definition. See [Skipping Permission Prompts](#skipping-permission-prompts) under Tools.

## User Input Requests

Enable the agent to ask questions to the user using the `ask_user` tool by providing an `onUserInputRequest` handler:
Expand Down
Loading
Loading