diff --git a/docs/auth/byok.md b/docs/auth/byok.md index f08ee450c..af9c8e5f8 100644 --- a/docs/auth/byok.md +++ b/docs/auth/byok.md @@ -1,8 +1,8 @@ -# BYOK (Bring Your Own Key) +# BYOK (bring your own key) BYOK allows you to use the Copilot SDK with your own API keys from model providers, bypassing GitHub Copilot authentication. This is useful for enterprise deployments, custom model hosting, or when you want direct billing with your model provider. -## Supported Providers +## Supported providers | Provider | Type Value | Notes | |----------|------------|-------| @@ -13,7 +13,7 @@ BYOK allows you to use the Copilot SDK with your own API keys from model provide | Microsoft Foundry Local | `"openai"` | Run AI models locally on your device via OpenAI-compatible API | | Other OpenAI-compatible | `"openai"` | vLLM, LiteLLM, etc. | -## Quick Start: Azure AI Foundry +## Quick start: Azure AI Foundry Azure AI Foundry (formerly Azure OpenAI) is a common BYOK deployment target for enterprises. Here's a complete example: @@ -196,9 +196,9 @@ client.stop().get(); -## Provider Configuration Reference +## Provider configuration reference -### ProviderConfig Fields +### ProviderConfig fields | Field | Type | Description | |-------|------|-------------| @@ -209,14 +209,14 @@ client.stop().get(); | `wireApi` / `wire_api` | `"completions"` \| `"responses"` | API format (default: `"completions"`) | | `azure.apiVersion` / `azure.api_version` | string | Azure API version (default: `"2024-10-21"`) | -### Wire API Format +### Wire API format The `wireApi` setting determines which OpenAI API format to use: - **`"completions"`** (default) - Chat Completions API (`/chat/completions`). Use for most models. - **`"responses"`** - Responses API. Use for GPT-5 series models that support the newer responses format. -### Type-Specific Notes +### Type-specific notes **OpenAI (`type: "openai"`)** - Works with OpenAI API and any OpenAI-compatible endpoint @@ -231,9 +231,9 @@ The `wireApi` setting determines which OpenAI API format to use: - For direct Anthropic API access - Uses Claude-specific API format -## Example Configurations +## Example configurations -### OpenAI Direct +### OpenAI direct ```typescript provider: { @@ -243,7 +243,7 @@ provider: { } ``` -### Azure OpenAI (Native Azure Endpoint) +### Azure OpenAI (native Azure endpoint) Use `type: "azure"` for endpoints at `*.openai.azure.com`: @@ -258,7 +258,7 @@ provider: { } ``` -### Azure AI Foundry (OpenAI-Compatible Endpoint) +### Azure AI Foundry (OpenAI-compatible endpoint) For Azure AI Foundry deployments with `/openai/v1/` endpoints, use `type: "openai"`: @@ -271,7 +271,7 @@ provider: { } ``` -### Ollama (Local) +### Ollama (local) ```typescript provider: { @@ -322,7 +322,7 @@ provider: { } ``` -### Bearer Token Authentication +### Bearer token authentication Some providers require bearer token authentication instead of API keys: @@ -336,7 +336,7 @@ provider: { > **Note:** The `bearerToken` option accepts a **static token string** only. The SDK does not refresh this token automatically. If your token expires, requests will fail and you'll need to create a new session with a fresh token. -## Custom Model Listing +## Custom model listing When using BYOK, the CLI server may not know which models your provider supports. You can supply a custom `onListModels` handler at the client level so that `client.listModels()` returns your provider's models in the standard `ModelInfo` format. This lets downstream consumers discover available models without querying the CLI. @@ -473,13 +473,13 @@ Results are cached after the first call, just like the default behavior. The han When using BYOK, be aware of these limitations: -### Identity Limitations +### Identity limitations BYOK authentication uses **static credentials only**. You must use an API key or static bearer token that you manage yourself. -### Feature Limitations +### Feature limitations Some Copilot features may behave differently with BYOK: @@ -488,7 +488,7 @@ Some Copilot features may behave differently with BYOK: - **Usage tracking** - Usage is tracked by your provider, not GitHub Copilot - **Premium requests** - Do not count against Copilot premium request quotas -### Provider-Specific Limitations +### Provider-specific limitations | Provider | Limitations | |----------|-------------| @@ -499,7 +499,7 @@ Some Copilot features may behave differently with BYOK: ## Troubleshooting -### "Model not specified" Error +### "Model not specified" error When using BYOK, the `model` parameter is **required**: @@ -516,7 +516,7 @@ const session = await client.createSession({ }); ``` -### Azure Endpoint Type Confusion +### Azure endpoint type confusion For Azure OpenAI endpoints (`*.openai.azure.com`), use the correct type: @@ -574,7 +574,7 @@ provider: { } ``` -### Connection Refused (Ollama) +### Connection refused (Ollama) Ensure Ollama is running and accessible: @@ -586,7 +586,7 @@ curl http://localhost:11434/v1/models ollama serve ``` -### Connection Refused (Foundry Local) +### Connection refused (Foundry Local) Foundry Local uses a dynamic port that may change between restarts. Confirm the active port: @@ -601,13 +601,13 @@ Update your `baseUrl` to match the port shown in the output. If the service is n foundry model run phi-4-mini ``` -### Authentication Failed +### Authentication failed 1. Verify your API key is correct and not expired 2. Check the `baseUrl` matches your provider's expected format 3. For bearer tokens, ensure the full token is provided (not just a prefix) -## Next Steps +## Next steps - [Authentication Overview](./index.md) - Learn about all authentication methods - [Getting Started Guide](../getting-started.md) - Build your first Copilot-powered app diff --git a/docs/auth/index.md b/docs/auth/index.md index 5b2f667da..9c9a34126 100644 --- a/docs/auth/index.md +++ b/docs/auth/index.md @@ -2,7 +2,7 @@ The GitHub Copilot SDK supports multiple authentication methods to fit different use cases. Choose the method that best matches your deployment scenario. -## Authentication Methods +## Authentication methods | Method | Use Case | Copilot Subscription Required | |--------|----------|-------------------------------| @@ -11,7 +11,7 @@ The GitHub Copilot SDK supports multiple authentication methods to fit different | [Environment Variables](#environment-variables) | CI/CD, automation, server-to-server | Yes | | [BYOK (Bring Your Own Key)](./byok.md) | Using your own API keys (Azure AI Foundry, OpenAI, etc.) | No | -## GitHub Signed-in User +## GitHub signed-in user This is the default authentication method when running the Copilot CLI interactively. Users authenticate via GitHub OAuth device flow, and the SDK uses their stored credentials. @@ -231,7 +231,7 @@ client.start().get(); - SaaS applications building on top of Copilot - Any multi-user application where you need to make requests on behalf of different users -## Environment Variables +## Environment variables For automation, CI/CD pipelines, and server-to-server scenarios, you can authenticate using environment variables. @@ -279,7 +279,7 @@ await client.start() - Server-side applications with service accounts - Development when you don't want to use interactive login -## BYOK (Bring Your Own Key) +## BYOK (bring your own key) BYOK allows you to use your own API keys from model providers like Azure AI Foundry, OpenAI, or Anthropic. This bypasses GitHub Copilot authentication entirely. @@ -295,7 +295,7 @@ BYOK allows you to use your own API keys from model providers like Azure AI Foun - Limitations and considerations - Complete code examples -## Authentication Priority +## Authentication priority When multiple authentication methods are available, the SDK uses them in this priority order: @@ -306,7 +306,7 @@ When multiple authentication methods are available, the SDK uses them in this pr 5. **Stored OAuth credentials** - From previous `copilot` CLI login 6. **GitHub CLI** - `gh auth` credentials -## Disabling Auto-Login +## Disabling auto-login To prevent the SDK from automatically using stored credentials or `gh` CLI auth, use the `useLoggedInUser: false` option: @@ -395,7 +395,7 @@ client.start().get(); -## Next Steps +## Next steps - [BYOK Documentation](./byok.md) - Learn how to use your own API keys - [Getting Started Guide](../getting-started.md) - Build your first Copilot-powered app diff --git a/docs/features/agent-loop.md b/docs/features/agent-loop.md index 0f0c2bbd0..b4f0eccaa 100644 --- a/docs/features/agent-loop.md +++ b/docs/features/agent-loop.md @@ -1,188 +1,188 @@ -# The Agent Loop - -How the Copilot CLI processes a user message end-to-end: from prompt to `session.idle`. - -## Architecture - -```mermaid -graph LR - App["Your App"] -->|send prompt| SDK["SDK Session"] - SDK -->|JSON-RPC| CLI["Copilot CLI"] - CLI -->|API calls| LLM["LLM"] - LLM -->|response| CLI - CLI -->|events| SDK - SDK -->|events| App -``` - -The **SDK** is a transport layer — it sends your prompt to the **Copilot CLI** over JSON-RPC and surfaces events back to your app. The **CLI** is the orchestrator that runs the agentic tool-use loop, making one or more LLM API calls until the task is done. - -## The Tool-Use Loop - -When you call `session.send({ prompt })`, the CLI enters a loop: - -```mermaid -flowchart TD - A["User prompt"] --> B["LLM API call\n(= one turn)"] - B --> C{"toolRequests\nin response?"} - C -->|Yes| D["Execute tools\nCollect results"] - D -->|"Results fed back\nas next turn input"| B - C -->|No| E["Final text\nresponse"] - E --> F(["session.idle"]) - - style B fill:#1a1a2e,stroke:#58a6ff,color:#c9d1d9 - style D fill:#1a1a2e,stroke:#3fb950,color:#c9d1d9 - style F fill:#0d1117,stroke:#f0883e,color:#f0883e -``` - -The model sees the **full conversation history** on each call — system prompt, user message, and all prior tool calls and results. - -**Key insight:** Each iteration of this loop is exactly one LLM API call, visible as one `assistant.turn_start` / `assistant.turn_end` pair in the event log. There are no hidden calls. - -## Turns — What They Are - -A **turn** is a single LLM API call and its consequences: - -1. The CLI sends the conversation history to the LLM -2. The LLM responds (possibly with tool requests) -3. If tools were requested, the CLI executes them -4. `assistant.turn_end` is emitted - -A single user message typically results in **multiple turns**. For example, a question like "how does X work in this codebase?" might produce: - -| Turn | What the model does | toolRequests? | -|------|-------------------|---------------| -| 1 | Calls `grep` and `glob` to search the codebase | ✅ Yes | -| 2 | Reads specific files based on search results | ✅ Yes | -| 3 | Reads more files for deeper context | ✅ Yes | -| 4 | Produces the final text answer | ❌ No → loop ends | - -The model decides on each turn whether to request more tools or produce a final answer. Each call sees the **full accumulated context** (all prior tool calls and results), so it can make an informed decision about whether it has enough information. - -## Event Flow for a Multi-Turn Interaction - -```mermaid -flowchart TD - send["session.send({ prompt: "Fix the bug in auth.ts" })"] - - subgraph Turn1 ["Turn 1"] - t1s["assistant.turn_start"] - t1m["assistant.message (toolRequests)"] - t1ts["tool.execution_start (read_file)"] - t1tc["tool.execution_complete"] - t1e["assistant.turn_end"] - t1s --> t1m --> t1ts --> t1tc --> t1e - end - - subgraph Turn2 ["Turn 2 — auto-triggered by CLI"] - t2s["assistant.turn_start"] - t2m["assistant.message (toolRequests)"] - t2ts["tool.execution_start (edit_file)"] - t2tc["tool.execution_complete"] - t2e["assistant.turn_end"] - t2s --> t2m --> t2ts --> t2tc --> t2e - end - - subgraph Turn3 ["Turn 3"] - t3s["assistant.turn_start"] - t3m["assistant.message (no toolRequests)\n"Done, here's what I changed""] - t3e["assistant.turn_end"] - t3s --> t3m --> t3e - end - - idle(["session.idle — ready for next message"]) - - send --> Turn1 --> Turn2 --> Turn3 --> idle -``` - -## Who Triggers Each Turn? - -| Actor | Responsibility | -|-------|---------------| -| **Your app** | Sends the initial prompt via `session.send()` | -| **Copilot CLI** | Runs the tool-use loop — executes tools and feeds results back to the LLM for the next turn | -| **LLM** | Decides whether to request tools (continue looping) or produce a final response (stop) | -| **SDK** | Passes events through; does not control the loop | - -The CLI is purely mechanical: "model asked for tools → execute → call model again." The **model** is the decision-maker for when to stop. - -## `session.idle` vs `session.task_complete` - -These are two different completion signals with very different guarantees: - -### `session.idle` - -- **Always emitted** when the tool-use loop ends -- **Ephemeral** — not persisted to disk, not replayed on session resume -- Means: "the agent has stopped processing and is ready for the next message" -- **Use this** as your reliable "done" signal - -The SDK's `sendAndWait()` method waits for this event: - -```typescript -// Blocks until session.idle fires -const response = await session.sendAndWait({ prompt: "Fix the bug" }); -``` - -### `session.task_complete` - -- **Optionally emitted** — requires the model to explicitly signal it -- **Persisted** — saved to the session event log on disk -- Means: "the agent considers the overall task fulfilled" -- Carries an optional `summary` field - -```typescript -session.on("session.task_complete", (event) => { - console.log("Task done:", event.data.summary); -}); -``` - -### Autopilot mode: the CLI nudges for `task_complete` - -In **autopilot mode** (headless/autonomous operation), the CLI actively tracks whether the model has called `task_complete`. If the tool-use loop ends without it, the CLI injects a synthetic user message nudging the model: - -> *"You have not yet marked the task as complete using the task_complete tool. If you were planning, stop planning and start implementing. You aren't done until you have fully completed the task."* - -This effectively restarts the tool-use loop — the model sees the nudge as a new user message and continues working. The nudge also instructs the model **not** to call `task_complete` prematurely: - -- Don't call it if you have open questions — make decisions and keep working -- Don't call it if you hit an error — try to resolve it -- Don't call it if there are remaining steps — complete them first - -This creates a **two-level completion mechanism** in autopilot: -1. The model calls `task_complete` with a summary → CLI emits `session.task_complete` → done -2. The model stops without calling it → CLI nudges → model continues or calls `task_complete` - -### Why `task_complete` might not appear - -In **interactive mode** (normal chat), the CLI does not nudge for `task_complete`. The model may skip it entirely. Common reasons: - -- **Conversational Q&A**: The model answers a question and simply stops — there's no discrete "task" to complete -- **Model discretion**: The model produces a final text response without calling the task-complete signal -- **Interrupted sessions**: The session ends before the model reaches a completion point - -The CLI emits `session.idle` regardless, because it's a mechanical signal (the loop ended), not a semantic one (the model thinks it's done). - -### Which should you use? - -| Use case | Signal | -|----------|--------| -| "Wait for the agent to finish processing" | `session.idle` ✅ | -| "Know when a coding task is done" | `session.task_complete` (best-effort) | -| "Timeout/error handling" | `session.idle` + `session.error` ✅ | - -## Counting LLM Calls - -The number of `assistant.turn_start` / `assistant.turn_end` pairs in the event log equals the total number of LLM API calls made. There are no hidden calls for planning, evaluation, or completion checking. - -To inspect turn count for a session: - -```bash -# Count turns in a session's event log -grep -c "assistant.turn_start" ~/.copilot/session-state//events.jsonl -``` - -## Further Reading - -- [Streaming Events Reference](./streaming-events.md) — Full field-level reference for every event type -- [Session Persistence](./session-persistence.md) — How sessions are saved and resumed -- [Hooks](./hooks.md) — Intercepting events in the loop (permissions, tools) +# The agent loop + +How the Copilot CLI processes a user message end-to-end: from prompt to `session.idle`. + +## Architecture + +```mermaid +graph LR + App["Your App"] -->|send prompt| SDK["SDK Session"] + SDK -->|JSON-RPC| CLI["Copilot CLI"] + CLI -->|API calls| LLM["LLM"] + LLM -->|response| CLI + CLI -->|events| SDK + SDK -->|events| App +``` + +The **SDK** is a transport layer — it sends your prompt to the **Copilot CLI** over JSON-RPC and surfaces events back to your app. The **CLI** is the orchestrator that runs the agentic tool-use loop, making one or more LLM API calls until the task is done. + +## The tool-use loop + +When you call `session.send({ prompt })`, the CLI enters a loop: + +```mermaid +flowchart TD + A["User prompt"] --> B["LLM API call\n(= one turn)"] + B --> C{"toolRequests\nin response?"} + C -->|Yes| D["Execute tools\nCollect results"] + D -->|"Results fed back\nas next turn input"| B + C -->|No| E["Final text\nresponse"] + E --> F(["session.idle"]) + + style B fill:#1a1a2e,stroke:#58a6ff,color:#c9d1d9 + style D fill:#1a1a2e,stroke:#3fb950,color:#c9d1d9 + style F fill:#0d1117,stroke:#f0883e,color:#f0883e +``` + +The model sees the **full conversation history** on each call — system prompt, user message, and all prior tool calls and results. + +**Key insight:** Each iteration of this loop is exactly one LLM API call, visible as one `assistant.turn_start` / `assistant.turn_end` pair in the event log. There are no hidden calls. + +## Turns — what they are + +A **turn** is a single LLM API call and its consequences: + +1. The CLI sends the conversation history to the LLM +2. The LLM responds (possibly with tool requests) +3. If tools were requested, the CLI executes them +4. `assistant.turn_end` is emitted + +A single user message typically results in **multiple turns**. For example, a question like "how does X work in this codebase?" might produce: + +| Turn | What the model does | toolRequests? | +|------|-------------------|---------------| +| 1 | Calls `grep` and `glob` to search the codebase | ✅ Yes | +| 2 | Reads specific files based on search results | ✅ Yes | +| 3 | Reads more files for deeper context | ✅ Yes | +| 4 | Produces the final text answer | ❌ No → loop ends | + +The model decides on each turn whether to request more tools or produce a final answer. Each call sees the **full accumulated context** (all prior tool calls and results), so it can make an informed decision about whether it has enough information. + +## Event flow for a multi-turn interaction + +```mermaid +flowchart TD + send["session.send({ prompt: "Fix the bug in auth.ts" })"] + + subgraph Turn1 ["Turn 1"] + t1s["assistant.turn_start"] + t1m["assistant.message (toolRequests)"] + t1ts["tool.execution_start (read_file)"] + t1tc["tool.execution_complete"] + t1e["assistant.turn_end"] + t1s --> t1m --> t1ts --> t1tc --> t1e + end + + subgraph Turn2 ["Turn 2 — auto-triggered by CLI"] + t2s["assistant.turn_start"] + t2m["assistant.message (toolRequests)"] + t2ts["tool.execution_start (edit_file)"] + t2tc["tool.execution_complete"] + t2e["assistant.turn_end"] + t2s --> t2m --> t2ts --> t2tc --> t2e + end + + subgraph Turn3 ["Turn 3"] + t3s["assistant.turn_start"] + t3m["assistant.message (no toolRequests)\n"Done, here's what I changed""] + t3e["assistant.turn_end"] + t3s --> t3m --> t3e + end + + idle(["session.idle — ready for next message"]) + + send --> Turn1 --> Turn2 --> Turn3 --> idle +``` + +## Who triggers each turn? + +| Actor | Responsibility | +|-------|---------------| +| **Your app** | Sends the initial prompt via `session.send()` | +| **Copilot CLI** | Runs the tool-use loop — executes tools and feeds results back to the LLM for the next turn | +| **LLM** | Decides whether to request tools (continue looping) or produce a final response (stop) | +| **SDK** | Passes events through; does not control the loop | + +The CLI is purely mechanical: "model asked for tools → execute → call model again." The **model** is the decision-maker for when to stop. + +## `session.idle` vs `session.task_complete` + +These are two different completion signals with very different guarantees: + +### `session.idle` + +- **Always emitted** when the tool-use loop ends +- **Ephemeral** — not persisted to disk, not replayed on session resume +- Means: "the agent has stopped processing and is ready for the next message" +- **Use this** as your reliable "done" signal + +The SDK's `sendAndWait()` method waits for this event: + +```typescript +// Blocks until session.idle fires +const response = await session.sendAndWait({ prompt: "Fix the bug" }); +``` + +### `session.task_complete` + +- **Optionally emitted** — requires the model to explicitly signal it +- **Persisted** — saved to the session event log on disk +- Means: "the agent considers the overall task fulfilled" +- Carries an optional `summary` field + +```typescript +session.on("session.task_complete", (event) => { + console.log("Task done:", event.data.summary); +}); +``` + +### Autopilot mode: the CLI nudges for `task_complete` + +In **autopilot mode** (headless/autonomous operation), the CLI actively tracks whether the model has called `task_complete`. If the tool-use loop ends without it, the CLI injects a synthetic user message nudging the model: + +> *"You have not yet marked the task as complete using the task_complete tool. If you were planning, stop planning and start implementing. You aren't done until you have fully completed the task."* + +This effectively restarts the tool-use loop — the model sees the nudge as a new user message and continues working. The nudge also instructs the model **not** to call `task_complete` prematurely: + +- Don't call it if you have open questions — make decisions and keep working +- Don't call it if you hit an error — try to resolve it +- Don't call it if there are remaining steps — complete them first + +This creates a **two-level completion mechanism** in autopilot: +1. The model calls `task_complete` with a summary → CLI emits `session.task_complete` → done +2. The model stops without calling it → CLI nudges → model continues or calls `task_complete` + +### Why `task_complete` might not appear + +In **interactive mode** (normal chat), the CLI does not nudge for `task_complete`. The model may skip it entirely. Common reasons: + +- **Conversational Q&A**: The model answers a question and simply stops — there's no discrete "task" to complete +- **Model discretion**: The model produces a final text response without calling the task-complete signal +- **Interrupted sessions**: The session ends before the model reaches a completion point + +The CLI emits `session.idle` regardless, because it's a mechanical signal (the loop ended), not a semantic one (the model thinks it's done). + +### Which should you use? + +| Use case | Signal | +|----------|--------| +| "Wait for the agent to finish processing" | `session.idle` ✅ | +| "Know when a coding task is done" | `session.task_complete` (best-effort) | +| "Timeout/error handling" | `session.idle` + `session.error` ✅ | + +## Counting LLM calls + +The number of `assistant.turn_start` / `assistant.turn_end` pairs in the event log equals the total number of LLM API calls made. There are no hidden calls for planning, evaluation, or completion checking. + +To inspect turn count for a session: + +```bash +# Count turns in a session's event log +grep -c "assistant.turn_start" ~/.copilot/session-state//events.jsonl +``` + +## Further reading + +- [Streaming Events Reference](./streaming-events.md) — Full field-level reference for every event type +- [Session Persistence](./session-persistence.md) — How sessions are saved and resumed +- [Hooks](./hooks.md) — Intercepting events in the loop (permissions, tools) diff --git a/docs/features/custom-agents.md b/docs/features/custom-agents.md index 0d27fe873..8bd5d5418 100644 --- a/docs/features/custom-agents.md +++ b/docs/features/custom-agents.md @@ -1,4 +1,4 @@ -# Custom Agents & Sub-Agent Orchestration +# Custom agents and sub-agent orchestration Define specialized agents with scoped tools and prompts, then let Copilot orchestrate them as sub-agents within a single session. @@ -23,7 +23,7 @@ flowchart TD | **Inference** | The runtime's ability to auto-select an agent based on the user's intent | | **Parent session** | The session that spawned the sub-agent; receives all lifecycle events | -## Defining Custom Agents +## Defining custom agents Pass `customAgents` when creating a session. Each agent needs at minimum a `name` and `prompt`. @@ -241,7 +241,7 @@ try (var client = new CopilotClient()) { -## Configuration Reference +## Configuration reference | Property | Type | Required | Description | |----------|------|----------|-------------| @@ -262,7 +262,7 @@ In addition to per-agent configuration above, you can set `agent` on the **sessi |-------------------------|------|-------------| | `agent` | `string` | Name of the custom agent to pre-select at session creation. Must match a `name` in `customAgents`. | -## Per-Agent Skills +## Per-agent skills You can preload skills into an agent's context using the `skills` property. When specified, the **full content** of each listed skill is eagerly injected into the agent's context at startup — the agent doesn't need to invoke a skill tool; the instructions are already present. Skills are **opt-in**: agents receive no skills by default, and sub-agents do not inherit skills from the parent. Skill names are resolved from the session-level `skillDirectories`. @@ -289,7 +289,7 @@ const session = await client.createSession({ In this example, `security-auditor` starts with `security-scan` and `dependency-check` already injected into its context, while `docs-writer` starts with `markdown-lint`. An agent without a `skills` field receives no skill content. -## Selecting an Agent at Session Creation +## Selecting an agent at session creation You can pass `agent` in the session config to pre-select which custom agent should be active when the session starts. The value must match the `name` of one of the agents defined in `customAgents`. @@ -405,7 +405,7 @@ var session = client.createSession( -## How Sub-Agent Delegation Works +## How sub-agent delegation works When you send a prompt to a session with custom agents, the runtime evaluates whether to delegate to a sub-agent: @@ -415,7 +415,7 @@ When you send a prompt to a session with custom agents, the runtime evaluates wh 4. **Event streaming** — Lifecycle events (`subagent.started`, `subagent.completed`, etc.) stream back to the parent session 5. **Result integration** — The sub-agent's output is incorporated into the parent agent's response -### Controlling Inference +### Controlling inference By default, all custom agents are available for automatic selection (`infer: true`). Set `infer: false` to prevent the runtime from auto-selecting an agent — useful for agents you only want invoked through explicit user requests: @@ -429,11 +429,11 @@ By default, all custom agents are available for automatic selection (`infer: tru } ``` -## Listening to Sub-Agent Events +## Listening to sub-agent events When a sub-agent runs, the parent session emits lifecycle events. Subscribe to these events to build UIs that visualize agent activity. -### Event Types +### Event types | Event | Emitted when | Data | |-------|-------------|------| @@ -443,7 +443,7 @@ When a sub-agent runs, the parent session emits lifecycle events. Subscribe to t | `subagent.failed` | Sub-agent encounters an error | `toolCallId`, `agentName`, `agentDisplayName`, `error` | | `subagent.deselected` | Runtime switches away from the sub-agent | — | -### Subscribing to Events +### Subscribing to events
Node.js / TypeScript @@ -678,7 +678,7 @@ var response = session.sendAndWait(
-## Building an Agent Tree UI +## Building an agent tree UI Sub-agent events include `toolCallId` fields that let you reconstruct the execution tree. Here's a pattern for tracking agent activity: @@ -728,7 +728,7 @@ session.on((event) => { }); ``` -## Scoping Tools per Agent +## Scoping tools per agent Use the `tools` property to restrict which tools an agent can access. This is essential for security and for keeping agents focused: @@ -759,7 +759,7 @@ const session = await client.createSession({ > **Note:** When `tools` is `null` or omitted, the agent inherits access to all tools configured on the session. Use explicit tool lists to enforce the principle of least privilege. -## Agent-Exclusive Tools +## Agent-exclusive tools Use the `defaultAgent` property on the session configuration to hide specific tools from the default agent (the built-in agent that handles turns when no custom agent is selected). This forces the main agent to delegate to sub-agents when those tools' capabilities are needed, keeping the main agent's context clean. @@ -883,7 +883,7 @@ var session = await client.CreateSessionAsync(new SessionConfig -### How It Works +### How it works Tools listed in `defaultAgent.excludedTools`: @@ -891,7 +891,7 @@ Tools listed in `defaultAgent.excludedTools`: 2. **Are hidden** from the main agent's tool list — the LLM won't see or call them directly 3. **Remain available** to any custom sub-agent that includes them in its `tools` array -### Interaction with Other Tool Filters +### Interaction with other tool filters `defaultAgent.excludedTools` is orthogonal to the session-level `availableTools` and `excludedTools`: @@ -907,7 +907,7 @@ Precedence: > **Note:** If a tool is in both `excludedTools` (session-level) and `defaultAgent.excludedTools`, the session-level exclusion takes precedence — the tool is unavailable to everyone. -## Attaching MCP Servers to Agents +## Attaching MCP servers to agents Each custom agent can have its own MCP (Model Context Protocol) servers, giving it access to specialized data sources: @@ -929,7 +929,7 @@ const session = await client.createSession({ }); ``` -## Patterns & Best Practices +## Patterns and best practices ### Pair a researcher with an editor diff --git a/docs/features/hooks.md b/docs/features/hooks.md index 826ee5efd..d6b9720d1 100644 --- a/docs/features/hooks.md +++ b/docs/features/hooks.md @@ -1,4 +1,4 @@ -# Working with Hooks +# Working with hooks Hooks let you plug custom logic into every stage of a Copilot session — from the moment it starts, through each user prompt and tool call, to the moment it ends. This guide walks through practical use cases so you can ship permissions, auditing, notifications, and more without modifying the core agent behavior. @@ -30,7 +30,7 @@ flowchart LR All hooks are **optional** — register only the ones you need. Returning `null` (or the language equivalent) from any hook tells the SDK to continue with default behavior. -## Registering Hooks +## Registering hooks Pass a `hooks` object when you create (or resume) a session. Every example below follows this pattern. @@ -227,7 +227,7 @@ try (var client = new CopilotClient()) { --- -## Use Case: Permission Control +## Use case: permission control Use `onPreToolUse` to build a permission layer that decides which tools the agent may run, what arguments are allowed, and whether the user should be prompted before execution. @@ -490,7 +490,7 @@ Returning `"ask"` delegates the decision to the user at runtime — useful for d --- -## Use Case: Auditing & Compliance +## Use case: auditing and compliance Combine `onPreToolUse`, `onPostToolUse`, and the session lifecycle hooks to build a complete audit trail that records every action the agent takes. @@ -670,7 +670,7 @@ const session = await client.createSession({ --- -## Use Case: Notifications & Sounds +## Use case: notifications and sounds Hooks fire in your application's process, so you can trigger any side-effect — desktop notifications, sounds, Slack messages, or webhook calls. @@ -785,7 +785,7 @@ const session = await client.createSession({ --- -## Use Case: Prompt Enrichment +## Use case: prompt enrichment Use `onSessionStart` and `onUserPromptSubmitted` to automatically inject context so users don't have to repeat themselves. @@ -839,7 +839,7 @@ const session = await client.createSession({ --- -## Use Case: Error Handling & Recovery +## Use case: error handling and recovery The `onErrorOccurred` hook gives you a chance to react to failures — whether that means retrying, notifying a human, or gracefully shutting down. @@ -886,7 +886,7 @@ const session = await client.createSession({ --- -## Use Case: Session Metrics +## Use case: session metrics Track how long sessions run, how many tools are invoked, and why sessions end — useful for dashboards and cost monitoring. @@ -981,7 +981,7 @@ session = await client.create_session( --- -## Combining Hooks +## Combining hooks Hooks compose naturally. A single `hooks` object can handle permissions **and** auditing **and** notifications — each hook does its own job. @@ -1016,7 +1016,7 @@ const session = await client.createSession({ }); ``` -## Best Practices +## Best practices 1. **Keep hooks fast.** Every hook runs inline — slow hooks delay the conversation. Offload heavy work (database writes, HTTP calls) to a background queue when possible. @@ -1041,7 +1041,7 @@ For full type definitions, input/output field tables, and additional examples fo - [Session Lifecycle](../hooks/session-lifecycle.md) - [Error Handling](../hooks/error-handling.md) -## See Also +## See also - [Getting Started](../getting-started.md) - [Custom Agents & Sub-Agent Orchestration](./custom-agents.md) diff --git a/docs/features/image-input.md b/docs/features/image-input.md index 409130bbd..ae154c2d8 100644 --- a/docs/features/image-input.md +++ b/docs/features/image-input.md @@ -1,4 +1,4 @@ -# Image Input +# Image input Send images to Copilot sessions as attachments. There are two ways to attach images: @@ -33,7 +33,7 @@ sequenceDiagram | **Auto-resize** | The runtime automatically resizes or quality-reduces images that exceed model-specific limits | | **Vision capability** | The model must have `capabilities.supports.vision = true` to process images | -## Quick Start — File Attachment +## Quick start — file attachment Attach an image file to any message using the file attachment type. The path must be an absolute path to an image on disk. @@ -248,7 +248,7 @@ try (var client = new CopilotClient()) { -## Quick Start — Blob Attachment +## Quick start — blob attachment When you already have image data in memory (e.g., a screenshot captured by your app, or an image fetched from an API), use a blob attachment to send it directly without writing to disk. @@ -462,13 +462,13 @@ try (var client = new CopilotClient()) { -## Supported Formats +## Supported formats Supported image formats include JPG, PNG, GIF, and other common image types. For file attachments, the runtime reads the image from disk and converts it as needed. For blob attachments, you provide the base64 data and MIME type directly. Use PNG or JPEG for best results, as these are the most widely supported formats. The model's `capabilities.limits.vision.supported_media_types` field lists the exact MIME types it accepts. -## Automatic Processing +## Automatic processing The runtime automatically processes images to fit within the model's constraints. No manual resizing is required. @@ -478,7 +478,7 @@ The runtime automatically processes images to fit within the model's constraints You can check these limits at runtime via the model capabilities object. For the best experience, use reasonably-sized PNG or JPEG images. -## Vision Model Capabilities +## Vision model capabilities Not all models support vision. Check the model's capabilities before sending images. @@ -512,7 +512,7 @@ vision?: { }; ``` -## Receiving Image Results +## Receiving image results When tools return images (e.g., screenshots or generated charts), the result contains `"image"` content blocks with base64-encoded data. @@ -524,7 +524,7 @@ When tools return images (e.g., screenshots or generated charts), the result con These image blocks appear in `tool.execution_complete` event results. See the [Streaming Events](./streaming-events.md) guide for the full event lifecycle. -## Tips & Limitations +## Tips and limitations | Tip | Details | |-----|---------| @@ -536,7 +536,7 @@ These image blocks appear in `tool.execution_complete` event results. See the [S | **Multiple images are supported** | Attach several attachments in one message, up to the model's `max_prompt_images` limit | | **SVG is not supported** | SVG files are text-based and excluded from image processing | -## See Also +## See also - [Streaming Events](./streaming-events.md) — event lifecycle including tool result content blocks - [Steering & Queueing](./steering-and-queueing.md) — sending follow-up messages with attachments diff --git a/docs/features/mcp.md b/docs/features/mcp.md index d8af04533..e970f5f1d 100644 --- a/docs/features/mcp.md +++ b/docs/features/mcp.md @@ -1,4 +1,4 @@ -# Using MCP Servers with the GitHub Copilot SDK +# Using MCP servers with the GitHub Copilot SDK The Copilot SDK can integrate with **MCP servers** (Model Context Protocol) to extend the assistant's capabilities with external tools. MCP servers run as separate processes and expose tools (functions) that Copilot can invoke during conversations. @@ -14,7 +14,7 @@ The Copilot SDK can integrate with **MCP servers** (Model Context Protocol) to e - Call external APIs - And much more -## Server Types +## Server types The SDK supports two types of MCP servers: @@ -153,7 +153,7 @@ await using var session = await client.CreateSessionAsync(new SessionConfig }); ``` -## Tool Configuration +## Tool configuration You can control which tools are available to an MCP server using the `tools` field. @@ -194,7 +194,7 @@ tools: [] - The `tools` field defines which tools are allowed. - There is no separate `allow` or `disallow` configuration — tool access is controlled directly through this list. -## Quick Start: Filesystem MCP Server +## Quick start: filesystem MCP server Here's a complete working example using the official [`@modelcontextprotocol/server-filesystem`](https://www.npmjs.com/package/@modelcontextprotocol/server-filesystem) MCP server: @@ -242,9 +242,9 @@ directories for different applications. > **Tip:** You can use any MCP server from the [MCP Servers Directory](https://github.com/modelcontextprotocol/servers). Popular options include `@modelcontextprotocol/server-github`, `@modelcontextprotocol/server-sqlite`, and `@modelcontextprotocol/server-puppeteer`. -## Configuration Options +## Configuration options -### Local/Stdio Server +### Local/stdio server | Property | Type | Required | Description | |----------|------|----------|-------------| @@ -256,7 +256,7 @@ directories for different applications. | `tools` | `string[]` | No | Tools to enable (`["*"]` for all, `[]` for none) | | `timeout` | `number` | No | Timeout in milliseconds | -### Remote Server (HTTP/SSE) +### Remote server (HTTP/SSE) | Property | Type | Required | Description | |----------|------|----------|-------------| @@ -294,7 +294,7 @@ directories for different applications. For detailed debugging guidance, see the **[MCP Debugging Guide](../troubleshooting/mcp-debugging.md)**. -## Related Resources +## Related resources - [Model Context Protocol Specification](https://modelcontextprotocol.io/) - [MCP Servers Directory](https://github.com/modelcontextprotocol/servers) - Community MCP servers @@ -302,7 +302,7 @@ For detailed debugging guidance, see the **[MCP Debugging Guide](../troubleshoot - [Getting Started Guide](../getting-started.md) - SDK basics and custom tools - [General Debugging Guide](.../troubleshooting/mcp-debugging.md) - SDK-wide debugging -## See Also +## See also - [MCP Debugging Guide](../troubleshooting/mcp-debugging.md) - Detailed MCP troubleshooting - [Issue #9](https://github.com/github/copilot-sdk/issues/9) - Original MCP tools usage question diff --git a/docs/features/session-persistence.md b/docs/features/session-persistence.md index 53caaff11..1cda64bc1 100644 --- a/docs/features/session-persistence.md +++ b/docs/features/session-persistence.md @@ -1,8 +1,8 @@ -# Session Resume & Persistence +# Session resume and persistence This guide walks you through the SDK's session persistence capabilities—how to pause work, resume it later, and manage sessions in production environments. -## How Sessions Work +## How sessions work When you create a session, the Copilot CLI maintains conversation history, tool state, and planning context. By default, this state lives in memory and disappears when the session ends. With persistence enabled, you can resume sessions across restarts, container migrations, or even different client instances. @@ -19,7 +19,7 @@ flowchart LR | **Paused** | State saved to disk | | **Resume** | State loaded from disk | -## Quick Start: Creating a Resumable Session +## Quick start: creating a resumable session The key to resumable sessions is providing your own `session_id`. Without one, the SDK generates a random ID and the session can't be resumed later. @@ -126,7 +126,7 @@ await session.SendAndWaitAsync(new MessageOptions { Prompt = "Analyze my codebas // Session state is automatically persisted ``` -## Resuming a Session +## Resuming a session Later—minutes, hours, or even days—you can resume the session from where you left off. @@ -229,7 +229,7 @@ var session = await client.ResumeSessionAsync("user-123-task-456"); await session.SendAndWaitAsync(new MessageOptions { Prompt = "What did we discuss earlier?" }); ``` -## Resume Options +## Resume options When resuming a session, you can optionally reconfigure many settings. This is useful when you need to change the model, update tool configurations, or modify behavior. @@ -251,7 +251,7 @@ When resuming a session, you can optionally reconfigure many settings. This is u | `disabledSkills` | Skills to disable | | `infiniteSessions` | Configure infinite session behavior | -### Example: Changing Model on Resume +### Example: changing model on resume ```typescript // Resume with a different model @@ -261,7 +261,7 @@ const session = await client.resumeSession("user-123-task-456", { }); ``` -## Using BYOK (Bring Your Own Key) with Resumed Sessions +## Using BYOK (bring your own key) with resumed sessions 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. @@ -289,7 +289,7 @@ const resumed = await client.resumeSession("user-123-task-456", { }); ``` -## What Gets Persisted? +## What gets persisted? Session state is saved to `~/.copilot/session-state/{sessionId}/`: @@ -315,7 +315,7 @@ Session state is saved to `~/.copilot/session-state/{sessionId}/`: | Provider/API keys | ❌ No | Security: must re-provide | | In-memory tool state | ❌ No | Tools should be stateless | -## Session ID Best Practices +## Session ID best practices Choose session IDs that encode ownership and purpose. This makes auditing and cleanup much easier. @@ -331,7 +331,7 @@ Choose session IDs that encode ownership and purpose. This makes auditing and cl - Easy to clean up: "Delete all sessions older than X" - Natural access control: Parse user ID from session ID -### Example: Generating Session IDs +### Example: generating session IDs ```typescript function createSessionId(userId: string, taskType: string): string { @@ -354,9 +354,9 @@ session_id = create_session_id("alice", "code-review") # → "alice-code-review-1706932800" ``` -## Managing Session Lifecycle +## Managing session lifecycle -### Listing Active Sessions +### Listing active sessions ```typescript // List all sessions @@ -371,7 +371,7 @@ for (const session of sessions) { const repoSessions = await client.listSessions({ repository: "owner/repo" }); ``` -### Cleaning Up Old Sessions +### Cleaning up old sessions ```typescript async function cleanupExpiredSessions(maxAgeMs: number) { @@ -391,7 +391,7 @@ async function cleanupExpiredSessions(maxAgeMs: number) { await cleanupExpiredSessions(24 * 60 * 60 * 1000); ``` -### Disconnecting from a Session (`disconnect`) +### Disconnecting from a session (`disconnect`) When a task completes, disconnect from the session explicitly rather than waiting for timeouts. This releases in-memory resources but **preserves session data on disk**, so the session can still be resumed later: @@ -420,7 +420,7 @@ Each SDK also provides idiomatic automatic cleanup patterns: > **Note:** `destroy()` is deprecated in favor of `disconnect()`. Existing code using `destroy()` will continue to work but should be migrated. -### Permanently Deleting a Session (`deleteSession`) +### Permanently deleting a session (`deleteSession`) To permanently remove a session and all its data from disk (conversation history, planning state, artifacts), use `deleteSession`. This is irreversible — the session **cannot** be resumed after deletion: @@ -431,7 +431,7 @@ await client.deleteSession("user-123-task-456"); > **`disconnect()` vs `deleteSession()`:** `disconnect()` releases in-memory resources but keeps session data on disk for later resumption. `deleteSession()` permanently removes everything, including files on disk. -## Automatic Cleanup: Idle Timeout +## Automatic cleanup: idle timeout By default, sessions have **no idle timeout** and live indefinitely until explicitly disconnected or deleted. You can optionally configure a server-wide idle timeout via `CopilotClientOptions.sessionIdleTimeoutSeconds`: @@ -460,9 +460,9 @@ session.on("session.idle", (event) => { }); ``` -## Deployment Patterns +## Deployment patterns -### Pattern 1: One CLI Server Per User (Recommended) +### Pattern 1: one CLI server per user (recommended) Best for: Strong isolation, multi-tenant environments, Azure Dynamic Sessions. @@ -480,7 +480,7 @@ flowchart LR **Benefits:** ✅ Complete isolation | ✅ Simple security | ✅ Easy scaling -### Pattern 2: Shared CLI Server (Resource Efficient) +### Pattern 2: shared CLI server (resource efficient) Best for: Internal tools, trusted environments, resource-constrained setups. @@ -517,11 +517,11 @@ async function resumeSessionWithAuth( } ``` -## Azure Dynamic Sessions +## Azure dynamic sessions For serverless/container deployments where containers can restart or migrate: -### Mount Persistent Storage +### Mount persistent storage The session state directory must be mounted to persistent storage: @@ -557,7 +557,7 @@ flowchart LR **Session survives container restarts!** -## Infinite Sessions for Long-Running Workflows +## Infinite sessions for long-running workflows For workflows that might exceed context limits, enable infinite sessions with automatic compaction: @@ -574,7 +574,7 @@ const session = await client.createSession({ > **Note:** Thresholds are context utilization ratios (0.0-1.0), not absolute token counts. See the [Compatibility Guide](../troubleshooting/compatibility.md) for details. -## Limitations & Considerations +## Limitations and considerations | Limitation | Description | Mitigation | |------------|-------------|------------| @@ -583,7 +583,7 @@ const session = await client.createSession({ | **No session locking** | Concurrent access to same session is undefined | Implement application-level locking or queue | | **Tool state not persisted** | In-memory tool state is lost | Design tools to be stateless or persist their own state | -### Handling Concurrent Access +### Handling concurrent access The SDK doesn't provide built-in session locking. If multiple clients might access the same session: @@ -630,7 +630,7 @@ await withSessionLock("user-123-task-456", async () => { | **Delete session permanently** | `client.deleteSession(sessionId)` — permanently removes all session data from disk; cannot be resumed | | **Containerized deployment** | Mount `~/.copilot/session-state/` to persistent storage | -## Next Steps +## Next steps - [Hooks Overview](../hooks/index.md) - Customize session behavior with hooks - [Compatibility Guide](../troubleshooting/compatibility.md) - SDK vs CLI feature comparison diff --git a/docs/features/skills.md b/docs/features/skills.md index 6c3888eb8..062186287 100644 --- a/docs/features/skills.md +++ b/docs/features/skills.md @@ -1,4 +1,4 @@ -# Custom Skills +# Custom skills Skills are reusable prompt modules that extend Copilot's capabilities. Load skills from directories to give Copilot specialized abilities for specific domains or workflows. @@ -12,7 +12,7 @@ Skills allow you to: - Organize complex agent configurations - Enable/disable capabilities per session -## Loading Skills +## Loading skills Specify directories containing skills when creating a session: @@ -171,7 +171,7 @@ try (var client = new CopilotClient()) { -## Disabling Skills +## Disabling skills Disable specific skills while keeping others active: @@ -291,7 +291,7 @@ var session = client.createSession( -## Skill Directory Structure +## Skill directory structure Each skill is a named subdirectory containing a `SKILL.md` file: @@ -305,7 +305,7 @@ skills/ The `skillDirectories` option points to the parent directory (e.g., `./skills`). The CLI discovers all `SKILL.md` files in immediate subdirectories. -### SKILL.md Format +### Skill.md format A `SKILL.md` file is a markdown document with optional YAML frontmatter: @@ -333,9 +333,9 @@ The frontmatter fields: The markdown body contains the instructions that are injected into the session context when the skill is loaded. -## Configuration Options +## Configuration options -### SessionConfig Skill Fields +### SessionConfig skill fields | Language | Field | Type | Description | |----------|-------|------|-------------| @@ -348,7 +348,7 @@ The markdown body contains the instructions that are injected into the session c | .NET | `SkillDirectories` | `List` | Directories to load skills from | | .NET | `DisabledSkills` | `List` | Skills to disable | -## Best Practices +## Best practices 1. **Organize by domain** - Group related skills together (e.g., `skills/security/`, `skills/testing/`) @@ -360,9 +360,9 @@ The markdown body contains the instructions that are injected into the session c 5. **Use relative paths** - Keep skills portable across environments -## Combining with Other Features +## Combining with other features -### Skills + Custom Agents +### Skills + custom agents Skills listed in an agent's `skills` field are **eagerly preloaded** — their full content is injected into the agent's context at startup, so the agent has access to the skill instructions immediately without needing to invoke a skill tool. Skill names are resolved from the session-level `skillDirectories`. @@ -380,7 +380,7 @@ const session = await client.createSession({ ``` > **Note:** Skills are opt-in — when `skills` is omitted, no skill content is injected. Sub-agents do not inherit skills from the parent; you must list them explicitly per agent. -### Skills + MCP Servers +### Skills + MCP servers Skills can complement MCP server capabilities: @@ -401,20 +401,20 @@ const session = await client.createSession({ ## Troubleshooting -### Skills Not Loading +### Skills not loading 1. **Check path exists** - Verify the skill directory path is correct and contains subdirectories with `SKILL.md` files 2. **Check permissions** - Ensure the SDK can read the directory 3. **Check SKILL.md format** - Verify the markdown is well-formed and any YAML frontmatter uses valid syntax 4. **Enable debug logging** - Set `logLevel: "debug"` to see skill loading logs -### Skill Conflicts +### Skill conflicts If multiple skills provide conflicting instructions: - Use `disabledSkills` to exclude conflicting skills - Reorganize skill directories to avoid overlaps -## See Also +## See also - [Custom Agents](../getting-started.md#create-custom-agents) - Define specialized AI personas - [Custom Tools](../getting-started.md#step-4-add-a-custom-tool) - Build your own tools diff --git a/docs/features/steering-and-queueing.md b/docs/features/steering-and-queueing.md index f4acd0006..4e4d925bf 100644 --- a/docs/features/steering-and-queueing.md +++ b/docs/features/steering-and-queueing.md @@ -1,4 +1,4 @@ -# Steering & Queueing +# Steering and queueing Two interaction patterns let users send messages while the agent is already working: **steering** redirects the agent mid-turn, and **queueing** buffers messages for sequential processing after the current turn completes. @@ -33,7 +33,7 @@ sequenceDiagram LLM->>S: Turn completes ``` -## Steering (Immediate Mode) +## Steering (immediate mode) Steering sends a message that is injected directly into the agent's current turn. The agent sees the message in real time and adjusts its response accordingly — useful for course-correcting without aborting the turn. @@ -210,7 +210,7 @@ try (var client = new CopilotClient()) { -### How Steering Works Internally +### How steering works internally 1. The message is added to the runtime's `ImmediatePromptProcessor` queue 2. Before the next LLM request within the current turn, the processor injects the message into the conversation @@ -219,7 +219,7 @@ try (var client = new CopilotClient()) { > **Note:** Steering messages are best-effort within the current turn. If the agent has already committed to a tool call, the steering takes effect after that call completes but still within the same turn. -## Queueing (Enqueue Mode) +## Queueing (enqueue mode) Queueing buffers messages to be processed sequentially after the current turn finishes. Each queued message starts its own full turn. This is the default mode — if you omit `mode`, the SDK uses `"enqueue"`. @@ -457,7 +457,7 @@ try (var client = new CopilotClient()) { -### How Queueing Works Internally +### How queueing works internally 1. The message is added to the session's `itemQueue` as a `QueuedItem` 2. When the current turn completes and the session becomes idle, `processQueuedItems()` runs @@ -465,7 +465,7 @@ try (var client = new CopilotClient()) { 4. If a steering message was pending when the turn ended, it is moved to the front of the queue 5. Processing continues until the queue is empty, then the session emits an idle event -## Combining Steering and Queueing +## Combining steering and queueing You can use both patterns together in a single session. Steering affects the current turn while queued messages wait for their own turns: @@ -523,7 +523,7 @@ await session.send({ -## Choosing Between Steering and Queueing +## Choosing between steering and queueing | Scenario | Pattern | Why | |----------|---------|-----| @@ -534,7 +534,7 @@ await session.send({ | You want to add context to the current task | **Steering** | Agent incorporates it into its current reasoning | | You want to batch unrelated requests | **Queueing** | Each gets its own full turn with clean context | -## Building a UI with Steering & Queueing +## Building a UI with steering and queueing Here's a pattern for building an interactive UI that supports both modes: @@ -606,7 +606,7 @@ class InteractiveChat { } ``` -## API Reference +## API reference ### MessageOptions @@ -617,7 +617,7 @@ class InteractiveChat { | Go | `Mode` | `string` | `"enqueue"` | Message delivery mode | | .NET | `Mode` | `string?` | `"enqueue"` | Message delivery mode | -### Delivery Modes +### Delivery modes | Mode | Effect | During active turn | During idle | |------|--------|-------------------|-------------| @@ -626,7 +626,7 @@ class InteractiveChat { > **Note:** When the session is idle (not processing), both modes behave identically — the message starts a new turn immediately. -## Best Practices +## Best practices 1. **Default to queueing** — Use `"enqueue"` (or omit `mode`) for most messages. It's predictable and doesn't risk disrupting in-progress work. @@ -640,7 +640,7 @@ class InteractiveChat { 6. **Handle the steering-to-queue fallback** — If a steering message arrives after the turn completes, it's automatically moved to the queue. Design your UI to reflect this transition. -## See Also +## See also - [Getting Started](../getting-started.md) — Set up a session and send messages - [Custom Agents](./custom-agents.md) — Define specialized agents with scoped tools diff --git a/docs/features/streaming-events.md b/docs/features/streaming-events.md index 9dde8f21b..d3c46a10d 100644 --- a/docs/features/streaming-events.md +++ b/docs/features/streaming-events.md @@ -1,4 +1,4 @@ -# Streaming Session Events +# Streaming session events Every action the Copilot agent takes — thinking, writing code, running tools — is emitted as a **session event** you can subscribe to. This guide is a field-level reference for each event type so you know exactly what data to expect without reading the SDK source. @@ -47,7 +47,7 @@ sequenceDiagram | **Delta event** | An ephemeral streaming chunk (text or reasoning). Accumulate deltas to build the complete content. | | **`parentId` chain** | Each event's `parentId` points to the previous event, forming a linked list you can walk. | -## Event Envelope +## Event envelope Every session event, regardless of type, includes these fields: @@ -60,7 +60,7 @@ Every session event, regardless of type, includes these fields: | `type` | `string` | Event type discriminator (see tables below) | | `data` | `object` | Event-specific payload | -## Subscribing to Events +## Subscribing to events
Node.js / TypeScript @@ -214,7 +214,7 @@ session.on(AssistantMessageDeltaEvent.class, event -> --- -## Assistant Events +## Assistant events These events track the agent's response lifecycle — from turn start through streaming chunks to the final message. @@ -327,7 +327,7 @@ Ephemeral. Low-level network progress indicator — total bytes received from th --- -## Tool Execution Events +## Tool execution events These events track the full lifecycle of each tool invocation — from the model requesting a tool call through execution to completion. @@ -398,7 +398,7 @@ Emitted when the user explicitly requests a tool invocation (rather than the mod --- -## Session Lifecycle Events +## Session lifecycle events ### `session.idle` @@ -497,7 +497,7 @@ The session has ended. --- -## Permission & User Input Events +## Permission and user input events These events are emitted when the agent needs approval or input from the user before continuing. @@ -573,7 +573,7 @@ Ephemeral. An elicitation request was resolved. --- -## Sub-Agent & Skill Events +## Sub-agent and skill events ### `subagent.started` @@ -636,7 +636,7 @@ A skill was activated for the current conversation. --- -## Other Events +## Other events ### `abort` @@ -729,7 +729,7 @@ Ephemeral. A queued command was resolved. --- -## Quick Reference: Agentic Turn Flow +## Quick reference: agentic turn flow A typical agentic turn emits events in this order: @@ -756,7 +756,7 @@ assistant.turn_end → Turn complete session.idle → Ready for next message (ephemeral) ``` -## All Event Types at a Glance +## All event types at a glance | Event Type | Ephemeral | Category | Key Data Fields | |------------|-----------|----------|-----------------| diff --git a/docs/getting-started.md b/docs/getting-started.md index 4335ac61b..0f2d31a22 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -1,4 +1,4 @@ -# Build Your First Copilot-Powered App +# Build your first Copilot-powered app In this tutorial, you'll use the Copilot SDK to build a command-line assistant. You'll start with the basics, add streaming responses, then add custom tools - giving Copilot the ability to call your code. @@ -28,7 +28,7 @@ Verify the CLI is working: copilot --version ``` -## Step 1: Install the SDK +## Step 1: install the SDK
Node.js / TypeScript @@ -115,7 +115,7 @@ implementation 'com.github:copilot-sdk-java:${copilotSdkVersion}'
-## Step 2: Send Your First Message +## Step 2: send your first message Create a new file and add the following code. This is the simplest way to use the SDK—about 5 lines of code. @@ -302,7 +302,7 @@ javac -cp copilot-sdk.jar HelloCopilot.java && java -cp .:copilot-sdk.jar HelloC Congratulations! You just built your first Copilot-powered app. -## Step 3: Add Streaming Responses +## Step 3: add streaming responses Right now, you wait for the complete response before seeing anything. Let's make it interactive by streaming the response as it's generated. @@ -505,7 +505,7 @@ public class HelloCopilot { Run the code again. You'll see the response appear word by word. -### Event Subscription Methods +### Event subscription methods The SDK provides methods for subscribing to session events: @@ -728,7 +728,7 @@ unsubscribe.close();
-## Step 4: Add a Custom Tool +## Step 4: add a custom tool Now for the powerful part. Let's give Copilot the ability to call your code by defining a custom tool. We'll create a simple weather lookup tool. @@ -1054,7 +1054,7 @@ public class HelloCopilot { Run it and you'll see Copilot call your tool to get weather data, then respond with the results! -## Step 5: Build an Interactive Assistant +## Step 5: build an interactive assistant Let's put it all together into a useful interactive assistant: @@ -1492,7 +1492,7 @@ You've built an assistant with a custom tool that Copilot can call! --- -## How Tools Work +## How tools work When you define a tool, you're telling Copilot: 1. **What the tool does** (description) @@ -1507,11 +1507,11 @@ Copilot decides when to call your tool based on the user's question. When it doe --- -## What's Next? +## What's next? Now that you've got the basics, here are more powerful features to explore: -### Connect to MCP Servers +### Connect to MCP servers 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: @@ -1528,7 +1528,7 @@ const session = await client.createSession({ 📖 **[Full MCP documentation →](./features/mcp.md)** - Learn about local vs remote servers, all configuration options, and troubleshooting. -### Create Custom Agents +### Create custom agents Define specialized AI personas for specific tasks: @@ -1545,7 +1545,7 @@ const session = await client.createSession({ > **Tip:** You can also set `agent: "pr-reviewer"` in the session config to pre-select this agent from the start. See the [Custom Agents guide](./features/custom-agents.md#selecting-an-agent-at-session-creation) for details. -### Customize the System Message +### Customize the system message Control the AI's behavior and personality by appending instructions: @@ -1581,7 +1581,7 @@ See the language-specific SDK READMEs for examples in [TypeScript](../nodejs/REA --- -## Connecting to an External CLI Server +## Connecting to an external CLI server By default, the SDK automatically manages the Copilot CLI process lifecycle, starting and stopping the CLI as needed. However, you can also run the CLI in server mode separately and have the SDK connect to it. This can be useful for: @@ -1589,7 +1589,7 @@ By default, the SDK automatically manages the Copilot CLI process lifecycle, sta - **Resource sharing**: Multiple SDK clients can connect to the same CLI server - **Development**: Run the CLI with custom settings or in a different environment -### Running the CLI in Server Mode +### Running the CLI in server mode Start the CLI in server mode using the `--headless` flag and optionally specify a port: @@ -1608,7 +1608,7 @@ copilot --headless --host 0.0.0.0 --port 4321 > **Warning:** Exposing the headless server on a non-loopback address makes it reachable by anyone who can route to that address. Pair it with network controls (firewall, private network, reverse proxy) and authentication appropriate for your environment. -### Connecting the SDK to the External Server +### Connecting the SDK to the external server Once the CLI is running in server mode, configure your SDK client to connect to it using the "cli url" option: @@ -1750,11 +1750,11 @@ var session = client.createSession( --- -## Telemetry & Observability +## Telemetry and observability The Copilot SDK supports [OpenTelemetry](https://opentelemetry.io/) for distributed tracing. Provide a `telemetry` configuration to the client to enable trace export from the CLI process and automatic [W3C Trace Context](https://www.w3.org/TR/trace-context/) propagation between the SDK and CLI. -### Enabling Telemetry +### Enabling telemetry Pass a `telemetry` (or `Telemetry`) config when creating the client. This is the opt-in — no separate "enabled" flag is needed. @@ -1845,7 +1845,7 @@ Dependency: `io.opentelemetry:opentelemetry-api` -### TelemetryConfig Options +### TelemetryConfig options | Option | Node.js | Python | Go | Java | .NET | Description | |---|---|---|---|---|---|---| @@ -1855,7 +1855,7 @@ Dependency: `io.opentelemetry:opentelemetry-api` | Source name | `sourceName` | `source_name` | `SourceName` | `sourceName` | `SourceName` | Instrumentation scope name | | Capture content | `captureContent` | `capture_content` | `CaptureContent` | `captureContent` | `CaptureContent` | Whether to capture message content | -### File Export +### File export To write traces to a local file instead of an OTLP endpoint: @@ -1869,7 +1869,7 @@ const client = new CopilotClient({ }); ``` -### Trace Context Propagation +### Trace context propagation Trace context is propagated automatically — no manual instrumentation is needed: @@ -1880,7 +1880,7 @@ Trace context is propagated automatically — no manual instrumentation is neede --- -## Learn More +## Learn more - [Authentication Guide](./auth/index.md) - GitHub OAuth, environment variables, and BYOK - [BYOK (Bring Your Own Key)](./auth/byok.md) - Use your own API keys from Azure AI Foundry, OpenAI, etc. diff --git a/docs/hooks/error-handling.md b/docs/hooks/error-handling.md index b721a3b91..6e623d36a 100644 --- a/docs/hooks/error-handling.md +++ b/docs/hooks/error-handling.md @@ -1,4 +1,4 @@ -# Error Handling Hook +# Error handling hook The `onErrorOccurred` hook is called when errors occur during session execution. Use it to: @@ -7,7 +7,7 @@ The `onErrorOccurred` hook is called when errors occur during session execution. - Provide user-friendly error messages - Trigger alerts for critical errors -## Hook Signature +## Hook signature
Node.js / TypeScript @@ -139,7 +139,7 @@ Return `null` or `undefined` to use default error handling. Otherwise, return an ## Examples -### Basic Error Logging +### Basic error logging
Node.js / TypeScript @@ -292,7 +292,7 @@ session.setEventErrorHandler((event, ex) -> {
-### Send Errors to Monitoring Service +### Send errors to monitoring service ```typescript import { captureException } from "@sentry/node"; // or your monitoring service @@ -318,7 +318,7 @@ const session = await client.createSession({ }); ``` -### User-Friendly Error Messages +### User-friendly error messages ```typescript const ERROR_MESSAGES: Record = { @@ -345,7 +345,7 @@ const session = await client.createSession({ }); ``` -### Suppress Non-Critical Errors +### Suppress non-critical errors ```typescript const session = await client.createSession({ @@ -362,7 +362,7 @@ const session = await client.createSession({ }); ``` -### Add Recovery Context +### Add recovery context ```typescript const session = await client.createSession({ @@ -393,7 +393,7 @@ The tool failed. Here are some recovery suggestions: }); ``` -### Track Error Patterns +### Track error patterns ```typescript interface ErrorStats { @@ -432,7 +432,7 @@ const session = await client.createSession({ }); ``` -### Alert on Critical Errors +### Alert on critical errors ```typescript const CRITICAL_CONTEXTS = ["system", "model_call"]; @@ -456,7 +456,7 @@ const session = await client.createSession({ }); ``` -### Combine with Other Hooks for Context +### Combine with other hooks for context ```typescript const sessionContext = new Map(); @@ -496,7 +496,7 @@ const session = await client.createSession({ }); ``` -## Best Practices +## Best practices 1. **Always log errors** - Even if you suppress them from users, keep logs for debugging. @@ -510,7 +510,7 @@ const session = await client.createSession({ 6. **Monitor error patterns** - Track recurring errors to identify systemic issues. -## See Also +## See also - [Hooks Overview](./index.md) - [Session Lifecycle Hooks](./session-lifecycle.md) diff --git a/docs/hooks/index.md b/docs/hooks/index.md index 3373602c4..ed670b448 100644 --- a/docs/hooks/index.md +++ b/docs/hooks/index.md @@ -1,4 +1,4 @@ -# Session Hooks +# Session hooks Hooks allow you to intercept and customize the behavior of Copilot sessions at key points in the conversation lifecycle. Use hooks to: @@ -8,7 +8,7 @@ Hooks allow you to intercept and customize the behavior of Copilot sessions at k - **Handle errors** - implement custom error handling - **Audit and log** - track all interactions for compliance -## Available Hooks +## Available hooks | Hook | Trigger | Use Case | |------|---------|----------| @@ -19,7 +19,7 @@ Hooks allow you to intercept and customize the behavior of Copilot sessions at k | [`onSessionEnd`](./session-lifecycle.md#session-end) | Session ends | Cleanup, analytics | | [`onErrorOccurred`](./error-handling.md) | Error happens | Custom error handling | -## Quick Start +## Quick start
Node.js / TypeScript @@ -192,7 +192,7 @@ try (var client = new CopilotClient()) {
-## Hook Invocation Context +## Hook invocation context Every hook receives an `invocation` parameter with context about the current session: @@ -202,9 +202,9 @@ Every hook receives an `invocation` parameter with context about the current ses This allows hooks to maintain state or perform session-specific logic. -## Common Patterns +## Common patterns -### Logging All Tool Calls +### Logging all tool calls ```typescript const session = await client.createSession({ @@ -221,7 +221,7 @@ const session = await client.createSession({ }); ``` -### Blocking Dangerous Tools +### Blocking dangerous tools ```typescript const BLOCKED_TOOLS = ["shell", "bash", "exec"]; @@ -241,7 +241,7 @@ const session = await client.createSession({ }); ``` -### Adding User Context +### Adding user context ```typescript const session = await client.createSession({ @@ -256,7 +256,7 @@ const session = await client.createSession({ }); ``` -## Hook Guides +## Hook guides - **[Pre-Tool Use Hook](./pre-tool-use.md)** - Control tool execution permissions - **[Post-Tool Use Hook](./post-tool-use.md)** - Transform tool results @@ -264,7 +264,7 @@ const session = await client.createSession({ - **[Session Lifecycle Hooks](./session-lifecycle.md)** - Session start and end - **[Error Handling Hook](./error-handling.md)** - Custom error handling -## See Also +## See also - [Getting Started Guide](../getting-started.md) - [Custom Tools](../getting-started.md#step-4-add-a-custom-tool) diff --git a/docs/hooks/post-tool-use.md b/docs/hooks/post-tool-use.md index f7c4089c9..4578f67e7 100644 --- a/docs/hooks/post-tool-use.md +++ b/docs/hooks/post-tool-use.md @@ -1,4 +1,4 @@ -# Post-Tool Use Hook +# Post-tool use hook The `onPostToolUse` hook is called **after** a tool executes. Use it to: @@ -7,7 +7,7 @@ The `onPostToolUse` hook is called **after** a tool executes. Use it to: - Add context based on results - Suppress results from the conversation -## Hook Signature +## Hook signature
Node.js / TypeScript @@ -132,7 +132,7 @@ Return `null` or `undefined` to pass through the result unchanged. Otherwise, re ## Examples -### Log All Tool Results +### Log all tool results
Node.js / TypeScript @@ -286,7 +286,7 @@ var session = client.createSession(
-### Redact Sensitive Data +### Redact sensitive data ```typescript const SENSITIVE_PATTERNS = [ @@ -314,7 +314,7 @@ const session = await client.createSession({ }); ``` -### Truncate Large Results +### Truncate large results ```typescript const MAX_RESULT_LENGTH = 10000; @@ -340,7 +340,7 @@ const session = await client.createSession({ }); ``` -### Add Context Based on Results +### Add context based on results ```typescript const session = await client.createSession({ @@ -366,7 +366,7 @@ const session = await client.createSession({ }); ``` -### Filter Error Stack Traces +### Filter error stack traces ```typescript const session = await client.createSession({ @@ -388,7 +388,7 @@ const session = await client.createSession({ }); ``` -### Audit Trail for Compliance +### Audit trail for compliance ```typescript interface AuditEntry { @@ -423,7 +423,7 @@ const session = await client.createSession({ }); ``` -### Suppress Noisy Results +### Suppress noisy results ```typescript const NOISY_TOOLS = ["list_directory", "search_codebase"]; @@ -450,7 +450,7 @@ const session = await client.createSession({ }); ``` -## Best Practices +## Best practices 1. **Return `null` when no changes needed** - This is more efficient than returning an empty object or the same result. @@ -462,7 +462,7 @@ const session = await client.createSession({ 5. **Keep hooks fast** - Post-tool hooks run synchronously. Heavy processing should be done asynchronously or batched. -## See Also +## See also - [Hooks Overview](./index.md) - [Pre-Tool Use Hook](./pre-tool-use.md) diff --git a/docs/hooks/pre-tool-use.md b/docs/hooks/pre-tool-use.md index c8e8504f0..a0563096f 100644 --- a/docs/hooks/pre-tool-use.md +++ b/docs/hooks/pre-tool-use.md @@ -1,4 +1,4 @@ -# Pre-Tool Use Hook +# Pre-tool use hook The `onPreToolUse` hook is called **before** a tool executes. Use it to: @@ -7,7 +7,7 @@ The `onPreToolUse` hook is called **before** a tool executes. Use it to: - Add context for the tool - Suppress tool output from the conversation -## Hook Signature +## Hook signature
Node.js / TypeScript @@ -131,7 +131,7 @@ Return `null` or `undefined` to allow the tool to execute with no changes. Other | `additionalContext` | string | Extra context injected into the conversation | | `suppressOutput` | boolean | If true, tool output won't appear in conversation | -### Permission Decisions +### Permission decisions | Decision | Behavior | |----------|----------| @@ -141,7 +141,7 @@ Return `null` or `undefined` to allow the tool to execute with no changes. Other ## Examples -### Allow All Tools (Logging Only) +### Allow all tools (logging only)
Node.js / TypeScript @@ -296,7 +296,7 @@ var session = client.createSession(
-### Block Specific Tools +### Block specific tools ```typescript const BLOCKED_TOOLS = ["shell", "bash", "write_file", "delete_file"]; @@ -316,7 +316,7 @@ const session = await client.createSession({ }); ``` -### Modify Tool Arguments +### Modify tool arguments ```typescript const session = await client.createSession({ @@ -339,7 +339,7 @@ const session = await client.createSession({ }); ``` -### Restrict File Access to Specific Directories +### Restrict file access to specific directories ```typescript const ALLOWED_DIRECTORIES = ["/home/user/projects", "/tmp"]; @@ -366,7 +366,7 @@ const session = await client.createSession({ }); ``` -### Suppress Verbose Tool Output +### Suppress verbose tool output ```typescript const VERBOSE_TOOLS = ["list_directory", "search_files"]; @@ -383,7 +383,7 @@ const session = await client.createSession({ }); ``` -### Add Context Based on Tool +### Add context based on tool ```typescript const session = await client.createSession({ @@ -401,7 +401,7 @@ const session = await client.createSession({ }); ``` -## Best Practices +## Best practices 1. **Always return a decision** - Returning `null` allows the tool, but being explicit with `{ permissionDecision: "allow" }` is clearer. @@ -419,7 +419,7 @@ const session = await client.createSession({ 5. **Use `suppressOutput` judiciously** - Suppressing output means the model won't see the result, which may affect conversation quality. -## See Also +## See also - [Hooks Overview](./index.md) - [Post-Tool Use Hook](./post-tool-use.md) diff --git a/docs/hooks/session-lifecycle.md b/docs/hooks/session-lifecycle.md index 1c8723854..5adbb2cf0 100644 --- a/docs/hooks/session-lifecycle.md +++ b/docs/hooks/session-lifecycle.md @@ -1,4 +1,4 @@ -# Session Lifecycle Hooks +# Session lifecycle hooks Session lifecycle hooks let you respond to session start and end events. Use them to: @@ -7,11 +7,11 @@ Session lifecycle hooks let you respond to session start and end events. Use the - Track session metrics and analytics - Configure session behavior dynamically -## Session Start Hook {#session-start} +## Session start hook {#session-start} The `onSessionStart` hook is called when a session begins (new or resumed). -### Hook Signature +### Hook signature
Node.js / TypeScript @@ -132,7 +132,7 @@ SessionStartHandler sessionStartHandler; ### Examples -#### Add Project Context at Start +#### Add project context at start
Node.js / TypeScript @@ -183,7 +183,7 @@ session = await client.create_session(on_permission_request=PermissionHandler.ap
-#### Handle Session Resume +#### Handle session resume ```typescript const session = await client.createSession({ @@ -207,7 +207,7 @@ Session resumed. Previous context: }); ``` -#### Load User Preferences +#### Load user preferences ```typescript const session = await client.createSession({ @@ -237,11 +237,11 @@ const session = await client.createSession({ --- -## Session End Hook {#session-end} +## Session end hook {#session-end} The `onSessionEnd` hook is called when a session ends. -### Hook Signature +### Hook signature
Node.js / TypeScript @@ -336,7 +336,7 @@ SessionEndHandler sessionEndHandler; | `finalMessage` | string \| undefined | The last message from the session | | `error` | string \| undefined | Error message if session ended due to error | -#### End Reasons +#### End reasons | Reason | Description | |--------|-------------| @@ -356,7 +356,7 @@ SessionEndHandler sessionEndHandler; ### Examples -#### Track Session Metrics +#### Track session metrics
Node.js / TypeScript @@ -422,7 +422,7 @@ session = await client.create_session(on_permission_request=PermissionHandler.ap
-#### Clean Up Resources +#### Clean up resources ```typescript const sessionResources = new Map(); @@ -451,7 +451,7 @@ const session = await client.createSession({ }); ``` -#### Save Session State for Resume +#### Save session state for resume ```typescript const session = await client.createSession({ @@ -471,7 +471,7 @@ const session = await client.createSession({ }); ``` -#### Log Session Summary +#### Log session summary ```typescript const sessionData: Record = {}; @@ -512,7 +512,7 @@ Session Summary: }); ``` -## Best Practices +## Best practices 1. **Keep `onSessionStart` fast** - Users are waiting for the session to be ready. @@ -524,7 +524,7 @@ Session Summary: 5. **Make cleanup idempotent** - `onSessionEnd` might not be called if the process crashes. -## See Also +## See also - [Hooks Overview](./index.md) - [Error Handling Hook](./error-handling.md) diff --git a/docs/hooks/user-prompt-submitted.md b/docs/hooks/user-prompt-submitted.md index 0c0751980..8528ac8b0 100644 --- a/docs/hooks/user-prompt-submitted.md +++ b/docs/hooks/user-prompt-submitted.md @@ -1,4 +1,4 @@ -# User Prompt Submitted Hook +# User prompt submitted hook The `onUserPromptSubmitted` hook is called when a user submits a message. Use it to: @@ -7,7 +7,7 @@ The `onUserPromptSubmitted` hook is called when a user submits a message. Use it - Filter or validate user input - Implement prompt templates -## Hook Signature +## Hook signature
Node.js / TypeScript @@ -130,7 +130,7 @@ Return `null` or `undefined` to use the prompt unchanged. Otherwise, return an o ## Examples -### Log All User Prompts +### Log all user prompts
Node.js / TypeScript @@ -270,7 +270,7 @@ var session = client.createSession(
-### Add Project Context +### Add project context ```typescript const session = await client.createSession({ @@ -290,7 +290,7 @@ Framework: ${projectInfo.framework} }); ``` -### Expand Shorthand Commands +### Expand shorthand commands ```typescript const SHORTCUTS: Record = { @@ -317,7 +317,7 @@ const session = await client.createSession({ }); ``` -### Content Filtering +### Content filtering ```typescript const BLOCKED_PATTERNS = [ @@ -344,7 +344,7 @@ const session = await client.createSession({ }); ``` -### Enforce Prompt Length Limits +### Enforce prompt length limits ```typescript const MAX_PROMPT_LENGTH = 10000; @@ -365,7 +365,7 @@ const session = await client.createSession({ }); ``` -### Add User Preferences +### Add user preferences ```typescript interface UserPreferences { @@ -399,7 +399,7 @@ const session = await client.createSession({ }); ``` -### Rate Limiting +### Rate limiting ```typescript const promptTimestamps: number[] = []; @@ -430,7 +430,7 @@ const session = await client.createSession({ }); ``` -### Prompt Templates +### Prompt templates ```typescript const TEMPLATES: Record string> = { @@ -466,7 +466,7 @@ const session = await client.createSession({ }); ``` -## Best Practices +## Best practices 1. **Preserve user intent** - When modifying prompts, ensure the core intent remains clear. @@ -478,7 +478,7 @@ const session = await client.createSession({ 5. **Keep processing fast** - This hook runs on every user message. Avoid slow operations. -## See Also +## See also - [Hooks Overview](./index.md) - [Session Lifecycle Hooks](./session-lifecycle.md) diff --git a/docs/index.md b/docs/index.md index 1b89439ae..50d973f17 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,8 +1,8 @@ -# GitHub Copilot SDK Documentation +# GitHub Copilot SDK documentation Welcome to the GitHub Copilot SDK docs. Whether you're building your first Copilot-powered app or deploying to production, you'll find what you need here. -## Where to Start +## Where to start | I want to... | Go to | |---|---| @@ -12,7 +12,7 @@ Welcome to the GitHub Copilot SDK docs. Whether you're building your first Copil | **Add features to my app** | [Features](./features/index.md) — hooks, custom agents, MCP, skills, and more | | **Debug an issue** | [Troubleshooting](./troubleshooting/debugging.md) — common problems and solutions | -## Documentation Map +## Documentation map ### [Getting Started](./getting-started.md) diff --git a/docs/integrations/microsoft-agent-framework.md b/docs/integrations/microsoft-agent-framework.md index dc37051d2..54d9c7347 100644 --- a/docs/integrations/microsoft-agent-framework.md +++ b/docs/integrations/microsoft-agent-framework.md @@ -1,4 +1,4 @@ -# Microsoft Agent Framework Integration +# Microsoft agent framework integration Use the Copilot SDK as an agent provider inside the [Microsoft Agent Framework](https://devblogs.microsoft.com/semantic-kernel/build-ai-agents-with-github-copilot-sdk-and-microsoft-agent-framework/) (MAF) to compose multi-agent workflows alongside Azure OpenAI, Anthropic, and other providers. @@ -63,7 +63,7 @@ pip install copilot-sdk agent-framework-github-copilot
-## Basic Usage +## Basic usage Wrap the Copilot SDK client as a MAF agent with a single method call. The resulting agent conforms to the framework's standard interface and can be used anywhere a MAF agent is expected. @@ -135,7 +135,7 @@ client.stop().get();
-## Adding Custom Tools +## Adding custom tools Extend your Copilot agent with custom function tools. Tools defined through the standard Copilot SDK are automatically available when the agent runs inside MAF. @@ -264,11 +264,11 @@ try (var client = new CopilotClient()) {
-## Multi-Agent Workflows +## Multi-agent workflows The primary benefit of MAF integration is composing Copilot alongside other agent providers in orchestrated workflows. Use the framework's built-in orchestrators to create pipelines where different agents handle different steps. -### Sequential Workflow +### Sequential workflow Run agents one after another, passing output from one to the next: @@ -381,7 +381,7 @@ client.stop().get();
-### Concurrent Workflow +### Concurrent workflow Run multiple agents in parallel and aggregate their results: @@ -458,7 +458,7 @@ client.stop().get();
-## Streaming Responses +## Streaming responses When building interactive applications, stream agent responses to show real-time output. The MAF integration preserves the Copilot SDK's streaming capabilities. @@ -561,9 +561,9 @@ client.stop().get();
-## Configuration Reference +## Configuration reference -### MAF Agent Options +### MAF agent options | Property | Type | Description | |----------|------|-------------| @@ -572,7 +572,7 @@ client.stop().get(); | `Streaming` / `streaming` | `bool` | Enable streaming responses | | `Model` / `model` | `string` | Override the default model | -### Copilot SDK Options (Passed Through) +### Copilot SDK options (passed through) All standard [SessionConfig](../getting-started.md) options are still available when creating the underlying Copilot client. The MAF wrapper delegates to the SDK under the hood: @@ -585,7 +585,7 @@ All standard [SessionConfig](../getting-started.md) options are still available | Model selection | ✅ Overridable per agent or per call | | Streaming | ✅ Full delta event support | -## Best Practices +## Best practices ### Choose the right level of integration @@ -639,7 +639,7 @@ catch (AgentException ex) } ``` -## See Also +## See also - [Getting Started](../getting-started.md) — initial Copilot SDK setup - [Custom Agents](../features/custom-agents.md) — define specialized sub-agents within the SDK diff --git a/docs/observability/opentelemetry.md b/docs/observability/opentelemetry.md index 3ac1bca9c..7fa4918db 100644 --- a/docs/observability/opentelemetry.md +++ b/docs/observability/opentelemetry.md @@ -1,8 +1,8 @@ -# OpenTelemetry Instrumentation for Copilot SDK +# OpenTelemetry instrumentation for Copilot SDK This guide shows how to add OpenTelemetry tracing to your Copilot SDK applications. -## Built-in Telemetry Support +## Built-in telemetry support The SDK has built-in support for configuring OpenTelemetry on the CLI process and propagating W3C Trace Context between the SDK and CLI. Provide a `TelemetryConfig` when creating the client to opt in: @@ -84,7 +84,7 @@ var client = new CopilotClient(new CopilotClientOptions() -### TelemetryConfig Options +### TelemetryConfig options | Option | Node.js | Python | Go | .NET | Java | Description | |---|---|---|---|---|---|---| @@ -94,7 +94,7 @@ var client = new CopilotClient(new CopilotClientOptions() | Source name | `sourceName` | `source_name` | `SourceName` | `SourceName` | `sourceName` | Instrumentation scope name | | Capture content | `captureContent` | `capture_content` | `CaptureContent` | `CaptureContent` | `captureContent` | Whether to capture message content | -### Trace Context Propagation +### Trace context propagation > **Most users don't need this.** The `TelemetryConfig` above is all you need to collect traces from the CLI. The trace context propagation described in this section is an **advanced feature** for applications that create their own OpenTelemetry spans and want them to appear in the **same distributed trace** as the CLI's spans. @@ -157,7 +157,7 @@ session.registerTool(myTool, async (args, invocation) => { }); ``` -### Per-Language Dependencies +### Per-language dependencies | Language | Dependency | Notes | |---|---|---| diff --git a/docs/setup/azure-managed-identity.md b/docs/setup/azure-managed-identity.md index a3dfddab4..c708fa1ef 100644 --- a/docs/setup/azure-managed-identity.md +++ b/docs/setup/azure-managed-identity.md @@ -1,10 +1,10 @@ -# Azure Managed Identity with BYOK +# Azure managed identity with BYOK The Copilot SDK's [BYOK mode](../auth/byok.md) accepts static API keys, but Azure deployments often use **Managed Identity** (Entra ID) instead of long-lived keys. Since the SDK doesn't natively support Entra ID authentication, you can use a short-lived bearer token via the `bearer_token` provider config field. This guide shows how to use `DefaultAzureCredential` from the [Azure Identity](https://learn.microsoft.com/python/api/azure-identity/azure.identity.defaultazurecredential) library to authenticate with Azure AI Foundry models through the Copilot SDK. -## How It Works +## How it works Azure AI Foundry's OpenAI-compatible endpoint accepts bearer tokens from Entra ID in place of static API keys. The pattern is: @@ -27,7 +27,7 @@ sequenceDiagram SDK-->>App: Session events ``` -## Python Example +## Python example ### Prerequisites @@ -35,7 +35,7 @@ sequenceDiagram pip install github-copilot-sdk azure-identity ``` -### Basic Usage +### Basic usage ```python import asyncio @@ -78,7 +78,7 @@ async def main(): asyncio.run(main()) ``` -### Token Refresh for Long-Running Applications +### Token refresh for long-running applications Bearer tokens expire (typically after ~1 hour). For servers or long-running agents, refresh the token before creating each session: @@ -124,7 +124,7 @@ class ManagedIdentityCopilotAgent: return response.data.content if response else "" ``` -## Node.js / TypeScript Example +## Node.js / TypeScript example ```typescript @@ -154,7 +154,7 @@ console.log(response?.data.content); await client.stop(); ``` -## .NET Example +## .NET example ```csharp @@ -186,7 +186,7 @@ var response = await session.SendAndWaitAsync( Console.WriteLine(response?.Data.Content); ``` -## Environment Configuration +## Environment configuration | Variable | Description | Example | |----------|-------------|---------| @@ -201,7 +201,7 @@ No API key environment variable is needed — authentication is handled by `Defa See the [DefaultAzureCredential documentation](https://learn.microsoft.com/python/api/azure-identity/azure.identity.defaultazurecredential) for the full credential chain. -## When to Use This Pattern +## When to use this pattern | Scenario | Recommendation | |----------|----------------| @@ -211,7 +211,7 @@ See the [DefaultAzureCredential documentation](https://learn.microsoft.com/pytho | Non-Azure environment with static API key | Use [standard BYOK](../auth/byok.md) | | GitHub Copilot subscription available | Use [GitHub OAuth](./github-oauth.md) | -## See Also +## See also - [BYOK Setup Guide](../auth/byok.md) — Static API key configuration - [Backend Services](./backend-services.md) — Server-side deployment diff --git a/docs/setup/backend-services.md b/docs/setup/backend-services.md index 35197eeb4..9a30e0e4a 100644 --- a/docs/setup/backend-services.md +++ b/docs/setup/backend-services.md @@ -1,10 +1,10 @@ -# Backend Services Setup +# Backend services setup Run the Copilot SDK in server-side applications — APIs, web backends, microservices, and background workers. The CLI runs as a headless server that your backend code connects to over the network. **Best for:** Web app backends, API services, internal tools, CI/CD integrations, any server-side workload. -## How It Works +## How it works Instead of the SDK spawning a CLI child process, you run the CLI independently in **headless server mode**. Your backend connects to it over TCP using the `cliUrl` option. @@ -36,7 +36,7 @@ flowchart TB - Multiple SDK clients can share one CLI server - Works with any auth method (GitHub tokens, env vars, BYOK) -## Architecture: Auto-Managed vs. External CLI +## Architecture: auto-managed vs. external CLI ```mermaid flowchart LR @@ -54,7 +54,7 @@ flowchart LR style External fill:#0d1117,stroke:#3fb950,color:#c9d1d9 ``` -## Step 1: Start the CLI in Headless Mode +## Step 1: start the CLI in headless mode Run the CLI as a background server: @@ -116,7 +116,7 @@ Environment=COPILOT_GITHUB_TOKEN=your-token Restart=always ``` -## Step 2: Connect the SDK +## Step 2: connect the SDK
Node.js / TypeScript @@ -288,9 +288,9 @@ try {
-## Authentication for Backend Services +## Authentication for backend services -### Environment Variable Tokens +### Environment variable tokens The simplest approach — set a token on the CLI server: @@ -313,7 +313,7 @@ export COPILOT_GITHUB_TOKEN="gho_service_account_token" copilot --headless --port 4321 ``` -### Per-User Tokens (OAuth) +### Per-user tokens (OAuth) Pass individual user tokens when creating sessions. See [GitHub OAuth](./github-oauth.md) for the full flow. @@ -339,7 +339,7 @@ app.post("/chat", authMiddleware, async (req, res) => { }); ``` -### BYOK (No GitHub Auth) +### BYOK (no GitHub auth) Use your own API keys for the model provider. See [BYOK](../auth/byok.md) for details. @@ -358,7 +358,7 @@ const session = await client.createSession({ }); ``` -## Common Backend Patterns +## Common backend patterns ### Web API with Express @@ -414,7 +414,7 @@ app.post("/api/chat", async (req, res) => { app.listen(3000); ``` -### Background Worker +### Background worker ```typescript import { CopilotClient } from "@github/copilot-sdk"; @@ -439,7 +439,7 @@ async function processJob(job: Job) { } ``` -### Docker Compose Deployment +### Docker compose deployment ```yaml version: "3.8" @@ -486,7 +486,7 @@ flowchart TB style Docker fill:#0d1117,stroke:#58a6ff,color:#c9d1d9 ``` -## Health Checks +## Health checks Monitor the CLI server's health: @@ -502,7 +502,7 @@ async function checkCLIHealth(): Promise { } ``` -## Session Cleanup +## Session cleanup Backend services should actively clean up sessions to avoid resource leaks: @@ -533,7 +533,7 @@ setInterval(() => cleanupSessions(24 * 60 * 60 * 1000), 60 * 60 * 1000); | **Session state on local disk** | Mount persistent storage for container restarts | | **30-minute idle timeout** | Sessions without activity are auto-cleaned | -## When to Move On +## When to move on | Need | Next Guide | |------|-----------| @@ -541,7 +541,7 @@ setInterval(() => cleanupSessions(24 * 60 * 60 * 1000), 60 * 60 * 1000); | GitHub account auth for users | [GitHub OAuth](./github-oauth.md) | | Your own model keys | [BYOK](../auth/byok.md) | -## Next Steps +## Next steps - **[Scaling & Multi-Tenancy](./scaling.md)** — Handle more users, add redundancy - **[Session Persistence](../features/session-persistence.md)** — Resume sessions across restarts diff --git a/docs/setup/bundled-cli.md b/docs/setup/bundled-cli.md index 7419d4c18..dfa6e8c04 100644 --- a/docs/setup/bundled-cli.md +++ b/docs/setup/bundled-cli.md @@ -1,10 +1,10 @@ -# Default Setup (Bundled CLI) +# Default setup (bundled CLI) The Node.js, Python, and .NET SDKs include the Copilot CLI as a dependency — your app ships with everything it needs, with no extra installation or configuration required. **Best for:** Most applications — desktop apps, standalone tools, CLI utilities, prototypes, and more. -## How It Works +## How it works When you install the SDK, the Copilot CLI binary is included automatically. The SDK starts it as a child process and communicates over stdio. There's nothing extra to configure. @@ -29,7 +29,7 @@ flowchart TB - Users authenticate through your app (or use env vars / BYOK) - Sessions are managed per-user on their machine -## Quick Start +## Quick start
Node.js / TypeScript @@ -162,7 +162,7 @@ client.stop().get();
-## Authentication Strategies +## Authentication strategies You need to decide how your users will authenticate. Here are the common patterns: @@ -181,7 +181,7 @@ flowchart TB style App fill:#0d1117,stroke:#58a6ff,color:#c9d1d9 ``` -### Option A: User's Signed-In Credentials (Simplest) +### Option A: user's signed-in credentials (simplest) The user signs in to the CLI once, and your app uses those credentials. No extra code needed — this is the default behavior. @@ -190,7 +190,7 @@ const client = new CopilotClient(); // Default: uses signed-in user credentials ``` -### Option B: Token via Environment Variable +### Option B: token via environment variable Ship your app with instructions to set a token, or set it programmatically: @@ -202,7 +202,7 @@ const client = new CopilotClient({ }); ``` -### Option C: BYOK (No GitHub Auth Needed) +### Option C: BYOK (no GitHub auth needed) If you manage your own model provider keys, users don't need GitHub accounts at all: @@ -221,7 +221,7 @@ const session = await client.createSession({ See the **[BYOK guide](../auth/byok.md)** for full details. -## Session Management +## Session management Apps typically want named sessions so users can resume conversations: @@ -242,7 +242,7 @@ const resumed = await client.resumeSession(sessionId); Session state persists at `~/.copilot/session-state/{sessionId}/`. -## When to Move On +## When to move on | Need | Next Guide | |------|-----------| @@ -250,7 +250,7 @@ Session state persists at `~/.copilot/session-state/{sessionId}/`. | Run on a server instead of user machines | [Backend Services](./backend-services.md) | | Use your own model keys | [BYOK](../auth/byok.md) | -## Next Steps +## Next steps - **[BYOK guide](../auth/byok.md)** — Use your own model provider keys - **[Session Persistence](../features/session-persistence.md)** — Advanced session management diff --git a/docs/setup/github-oauth.md b/docs/setup/github-oauth.md index 0f2be236e..bb637feca 100644 --- a/docs/setup/github-oauth.md +++ b/docs/setup/github-oauth.md @@ -1,10 +1,10 @@ -# GitHub OAuth Setup +# GitHub OAuth setup Let users authenticate with their GitHub accounts to use Copilot through your application. This supports individual accounts, organization memberships, and enterprise identities. **Best for:** Multi-user apps, internal tools with org access control, SaaS products, apps where users have GitHub accounts. -## How It Works +## How it works You create a GitHub OAuth App (or GitHub App), users authorize it, and you pass their access token to the SDK. Copilot requests are made on behalf of each authenticated user, using their Copilot subscription. @@ -72,7 +72,7 @@ flowchart TB style CLI fill:#0d1117,stroke:#3fb950,color:#c9d1d9 ``` -## Step 1: Create a GitHub OAuth App +## Step 1: create a GitHub OAuth app 1. Go to **GitHub Settings → Developer Settings → OAuth Apps → New OAuth App** (or for organizations: **Organization Settings → Developer Settings**) @@ -86,7 +86,7 @@ flowchart TB > **GitHub App vs OAuth App:** Both work. GitHub Apps offer finer-grained permissions and are recommended for new projects. OAuth Apps are simpler to set up. The token flow is the same from the SDK's perspective. -## Step 2: Implement the OAuth Flow +## Step 2: implement the OAuth flow Your application handles the standard GitHub OAuth flow. Here's the server-side token exchange: @@ -111,7 +111,7 @@ async function handleOAuthCallback(code: string): Promise { } ``` -## Step 3: Pass the Token to the SDK +## Step 3: pass the token to the SDK Create a SDK client for each authenticated user, passing their token: @@ -308,7 +308,7 @@ try (var client = createClientForUser("gho_user_access_token")) { -## Enterprise & Organization Access +## Enterprise and organization access GitHub OAuth naturally supports enterprise scenarios. When users authenticate with GitHub, their org memberships and enterprise associations come along. @@ -341,7 +341,7 @@ flowchart TB style App fill:#0d1117,stroke:#58a6ff,color:#c9d1d9 ``` -### Verify Organization Membership +### Verify organization membership After OAuth, check that the user belongs to your organization: @@ -365,7 +365,7 @@ if (!await verifyOrgMembership(token, "my-company")) { const client = createClientForUser(token); ``` -### Enterprise Managed Users (EMU) +### Enterprise managed users (EMU) For GitHub Enterprise Managed Users, the flow is identical — EMU users authenticate through GitHub OAuth like any other user. Their enterprise policies (IP restrictions, SAML SSO) are enforced by GitHub automatically. @@ -378,7 +378,7 @@ const client = new CopilotClient({ }); ``` -## Supported Token Types +## Supported token types | Token Prefix | Source | Works? | |-------------|--------|--------| @@ -387,7 +387,7 @@ const client = new CopilotClient({ | `github_pat_` | Fine-grained personal access token | ✅ | | `ghp_` | Classic personal access token | ❌ (deprecated) | -## Token Lifecycle +## Token lifecycle ```mermaid flowchart LR @@ -406,7 +406,7 @@ flowchart LR **Important:** Your application is responsible for token storage, refresh, and expiration handling. The SDK uses whatever token you provide — it doesn't manage the OAuth lifecycle. -### Token Refresh Pattern +### Token refresh pattern ```typescript async function getOrRefreshToken(userId: string): Promise { @@ -426,9 +426,9 @@ async function getOrRefreshToken(userId: string): Promise { } ``` -## Multi-User Patterns +## Multi-user patterns -### One Client Per User (Recommended) +### One client per user (recommended) Each user gets their own SDK client with their own token. This provides the strongest isolation. @@ -446,7 +446,7 @@ function getClientForUser(userId: string, token: string): CopilotClient { } ``` -### Shared CLI with Per-Request Tokens +### Shared CLI with per-request tokens For a lighter resource footprint, you can run a single external CLI server and pass tokens per session. See [Backend Services](./backend-services.md) for this pattern. @@ -459,7 +459,7 @@ For a lighter resource footprint, you can run a single external CLI server and p | **GitHub account required** | Users must have GitHub accounts | | **Rate limits per user** | Subject to each user's Copilot rate limits | -## When to Move On +## When to move on | Need | Next Guide | |------|-----------| @@ -467,7 +467,7 @@ For a lighter resource footprint, you can run a single external CLI server and p | Run the SDK on servers | [Backend Services](./backend-services.md) | | Handle many concurrent users | [Scaling & Multi-Tenancy](./scaling.md) | -## Next Steps +## Next steps - **[Authentication docs](../auth/index.md)** — Full auth method reference - **[Backend Services](./backend-services.md)** — Run the SDK server-side diff --git a/docs/setup/index.md b/docs/setup/index.md index 68daaa008..22c5ad1aa 100644 --- a/docs/setup/index.md +++ b/docs/setup/index.md @@ -1,8 +1,8 @@ -# Setup Guides +# Setup guides These guides walk you through configuring the Copilot SDK for your specific use case — from personal side projects to production platforms serving thousands of users. -## Architecture at a Glance +## Architecture at a glance Every Copilot SDK integration follows the same core pattern: your application talks to the SDK, which communicates with the Copilot CLI over JSON-RPC. What changes across setups is **where the CLI runs**, **how users authenticate**, and **how sessions are managed**. @@ -31,7 +31,7 @@ flowchart TB The setup guides below help you configure each layer for your scenario. -## Who Are You? +## Who are you? ### 🧑‍💻 Hobbyist @@ -41,7 +41,7 @@ You're building a personal assistant, side project, or experimental app. You wan 1. **[Default Setup](./bundled-cli.md)** — The SDK includes the CLI automatically — just install and go 2. **[Local CLI](./local-cli.md)** — Use your own CLI binary or running instance (advanced) -### 🏢 Internal App Developer +### 🏢 Internal app developer You're building tools for your team or company. Users are employees who need to authenticate with their enterprise GitHub accounts or org memberships. @@ -52,7 +52,7 @@ You're building tools for your team or company. Users are employees who need to **If scaling beyond a single server:** 3. **[Scaling & Multi-Tenancy](./scaling.md)** — Handle multiple users and services -### 🚀 App Developer (ISV) +### 🚀 App developer (ISV) You're building a product for customers. You need to handle authentication for your users — either through GitHub or by managing identity yourself. @@ -64,7 +64,7 @@ You're building a product for customers. You need to handle authentication for y **For production:** 4. **[Scaling & Multi-Tenancy](./scaling.md)** — Serve many customers reliably -### 🏗️ Platform Developer +### 🏗️ Platform developer You're embedding Copilot into a platform — APIs, developer tools, or infrastructure that other developers build on. You need fine-grained control over sessions, scaling, and multi-tenancy. @@ -76,7 +76,7 @@ You're embedding Copilot into a platform — APIs, developer tools, or infrastru 3. **[GitHub OAuth](./github-oauth.md)** — For GitHub-authenticated users 4. **[BYOK](../auth/byok.md)** — For self-managed identity and model access -## Decision Matrix +## Decision matrix Use this table to find the right guides based on what you need to do: @@ -90,7 +90,7 @@ Use this table to find the right guides based on what you need to do: | Run the SDK on a server | [Backend Services](./backend-services.md) | | Serve multiple users / scale horizontally | [Scaling & Multi-Tenancy](./scaling.md) | -## Configuration Comparison +## Configuration comparison ```mermaid flowchart LR @@ -137,6 +137,6 @@ All guides assume you have: If you're brand new, start with the **[Getting Started tutorial](../getting-started.md)** first, then come back here for production configuration. -## Next Steps +## Next steps Pick the guide that matches your situation from the [decision matrix](#decision-matrix) above, or start with the persona description closest to your role. diff --git a/docs/setup/local-cli.md b/docs/setup/local-cli.md index 0e2d11020..6ab6c12be 100644 --- a/docs/setup/local-cli.md +++ b/docs/setup/local-cli.md @@ -1,10 +1,10 @@ -# Local CLI Setup +# Local CLI setup Use a specific CLI binary instead of the SDK's bundled CLI. This is an advanced option — you supply the CLI path explicitly, and you are responsible for ensuring version compatibility with the SDK. **Use when:** You need to pin a specific CLI version, or work with the Go SDK (which does not bundle a CLI). -## How It Works +## How it works By default, the Node.js, Python, and .NET SDKs include their own CLI dependency (see [Default Setup](./bundled-cli.md)). If you need to override this — for example, to use a system-installed CLI — you can use the `cliPath` option. @@ -151,7 +151,7 @@ Console.WriteLine(response?.Data.Content); -## Additional Options +## Additional options ```typescript const client = new CopilotClient({ @@ -168,7 +168,7 @@ const client = new CopilotClient({ }); ``` -## Using Environment Variables +## Using environment variables Instead of the keychain, you can authenticate via environment variables. This is useful for CI or when you don't want interactive login. @@ -181,7 +181,7 @@ export GITHUB_TOKEN="gho_xxxx" # GitHub Actions compatible The SDK picks these up automatically — no code changes needed. -## Managing Sessions +## Managing sessions Sessions default to ephemeral. To create resumable sessions, provide your own session ID: @@ -207,7 +207,7 @@ Session state is stored locally at `~/.copilot/session-state/{sessionId}/`. | **Local only** | The CLI runs on the same machine as your app | | **No multi-tenant** | Can't serve multiple users from one CLI instance | -## Next Steps +## Next steps - **[Default Setup](./bundled-cli.md)** — Use the SDK's built-in CLI (recommended for most use cases) - **[Getting Started tutorial](../getting-started.md)** — Build a complete interactive app diff --git a/docs/setup/scaling.md b/docs/setup/scaling.md index bc294980d..5c2c85e55 100644 --- a/docs/setup/scaling.md +++ b/docs/setup/scaling.md @@ -1,10 +1,10 @@ -# Scaling & Multi-Tenancy +# Scaling and multi-tenancy Design your Copilot SDK deployment to serve multiple users, handle concurrent sessions, and scale horizontally across infrastructure. This guide covers session isolation patterns, scaling topologies, and production best practices. **Best for:** Platform developers, SaaS builders, any deployment serving more than a handful of concurrent users. -## Core Concepts +## Core concepts Before choosing a pattern, understand three dimensions of scaling: @@ -24,9 +24,9 @@ flowchart TB style Dimensions fill:#0d1117,stroke:#58a6ff,color:#c9d1d9 ``` -## Session Isolation Patterns +## Session isolation patterns -### Pattern 1: Isolated CLI Per User +### Pattern 1: isolated CLI per user Each user gets their own CLI server instance. Strongest isolation — a user's sessions, memory, and processes are completely separated. @@ -97,7 +97,7 @@ class CLIPool { } ``` -### Pattern 2: Shared CLI with Session Isolation +### Pattern 2: shared CLI with session isolation Multiple users share one CLI server but have isolated sessions via unique session IDs. Lighter on resources, but weaker isolation. @@ -157,7 +157,7 @@ async function resumeSessionWithAuth( } ``` -### Pattern 3: Shared Sessions (Collaborative) +### Pattern 3: shared sessions (collaborative) Multiple users interact with the same session — like a shared chat room with Copilot. @@ -235,7 +235,7 @@ app.post("/team-chat", authMiddleware, async (req, res) => { }); ``` -## Comparison of Isolation Patterns +## Comparison of isolation patterns | | Isolated CLI Per User | Shared CLI + Session Isolation | Shared Sessions | |---|---|---|---| @@ -245,9 +245,9 @@ app.post("/team-chat", authMiddleware, async (req, res) => { | **Auth flexibility** | ✅ Per-user tokens | ⚠️ Service token | ⚠️ Service token | | **Best for** | Multi-tenant SaaS | Internal tools | Collaboration | -## Horizontal Scaling +## Horizontal scaling -### Multiple CLI Servers Behind a Load Balancer +### Multiple CLI servers behind a load balancer ```mermaid flowchart TB @@ -330,7 +330,7 @@ app.post("/chat", async (req, res) => { }); ``` -### Sticky Sessions vs. Shared Storage +### Sticky sessions vs. shared storage ```mermaid flowchart LR @@ -358,9 +358,9 @@ flowchart LR **Shared storage** enables any CLI to handle any session. Better load distribution, but requires networked storage for `~/.copilot/session-state/`. -## Vertical Scaling +## Vertical scaling -### Tuning a Single CLI Server +### Tuning a single CLI server A single CLI server can handle many concurrent sessions. Key considerations: @@ -419,7 +419,7 @@ class SessionManager { } ``` -## Ephemeral vs. Persistent Sessions +## Ephemeral vs. persistent sessions ```mermaid flowchart LR @@ -441,7 +441,7 @@ flowchart LR style Persistent fill:#0d1117,stroke:#3fb950,color:#c9d1d9 ``` -### Ephemeral Sessions +### Ephemeral sessions For stateless API endpoints where each request is independent: @@ -462,7 +462,7 @@ app.post("/api/analyze", async (req, res) => { }); ``` -### Persistent Sessions +### Persistent sessions For conversational interfaces or long-running workflows: @@ -498,9 +498,9 @@ app.post("/api/chat/end", async (req, res) => { }); ``` -## Container Deployments +## Container deployments -### Kubernetes with Persistent Storage +### Kubernetes with persistent storage ```yaml apiVersion: apps/v1 @@ -589,7 +589,7 @@ volumes: storageAccountName: myaccount ``` -## Production Checklist +## Production checklist ```mermaid flowchart TB @@ -627,7 +627,7 @@ flowchart TB | **30-minute idle timeout** | Sessions without activity are auto-cleaned by the CLI | | **CLI is single-process** | Scale by adding more CLI server instances, not threads | -## Next Steps +## Next steps - **[Session Persistence](../features/session-persistence.md)** — Deep dive on resumable sessions - **[Backend Services](./backend-services.md)** — Core server-side setup diff --git a/docs/troubleshooting/compatibility.md b/docs/troubleshooting/compatibility.md index aed5286bf..1c9148c2a 100644 --- a/docs/troubleshooting/compatibility.md +++ b/docs/troubleshooting/compatibility.md @@ -1,4 +1,4 @@ -# SDK and CLI Compatibility +# SDK and CLI compatibility This document outlines which Copilot CLI features are available through the SDK and which are CLI-only. @@ -6,7 +6,7 @@ This document outlines which Copilot CLI features are available through the SDK The Copilot SDK communicates with the CLI via JSON-RPC protocol. Features must be explicitly exposed through this protocol to be available in the SDK. Many interactive CLI features are terminal-specific and not available programmatically. -## Feature Comparison +## Feature comparison ### ✅ Available in SDK @@ -90,7 +90,7 @@ The Copilot SDK communicates with the CLI via JSON-RPC protocol. Features must b | History truncation | `session.rpc.history.truncate()` | Remove events from a point onward | | Session forking | `server.rpc.sessions.fork()` | Fork a session at a point in history | -### ❌ Not Available in SDK (CLI-Only) +### ❌ Not available in SDK (CLI-only) | Feature | CLI Command/Option | Reason | |---------|-------------------|--------| @@ -169,7 +169,7 @@ The Copilot SDK communicates with the CLI via JSON-RPC protocol. Features must b ## Workarounds -### Session Export +### Session export The `--share` option is not available via SDK. Workarounds: @@ -184,7 +184,7 @@ The `--share` option is not available via SDK. Workarounds: 2. **Use CLI directly for export** - Run the CLI with `--share` for one-off exports. -### Permission Control +### Permission control The SDK uses a **deny-by-default** permission model. All permission requests (file writes, shell commands, URL fetches, etc.) are denied unless your app provides an `onPermissionRequest` handler. @@ -196,7 +196,7 @@ const session = await client.createSession({ }); ``` -### Token Usage Tracking +### Token usage tracking Instead of `/usage`, subscribe to usage events: @@ -209,7 +209,7 @@ session.on("assistant.usage", (event) => { }); ``` -### Context Compaction +### Context compaction Instead of `/compact`, configure automatic compaction or trigger it manually: @@ -230,7 +230,7 @@ console.log(`Removed ${result.tokensRemoved} tokens, ${result.messagesRemoved} m > **Note:** Thresholds are context utilization ratios (0.0-1.0), not absolute token counts. -### Plan Management +### Plan management Read and write session plans programmatically: @@ -248,7 +248,7 @@ await session.rpc.plan.update({ content: "# My Plan\n- Step 1\n- Step 2" }); await session.rpc.plan.delete(); ``` -### Message Steering +### Message steering Inject a message into the current LLM turn without aborting: @@ -260,7 +260,7 @@ await session.send({ prompt: "Focus on error handling first", mode: "immediate" await session.send({ prompt: "Next, add tests" }); ``` -## Protocol Limitations +## Protocol limitations The SDK can only access features exposed through the CLI's JSON-RPC protocol. If you need a CLI feature that's not available: @@ -268,7 +268,7 @@ The SDK can only access features exposed through the CLI's JSON-RPC protocol. If 2. **Use the CLI directly** - For one-off operations, invoke the CLI 3. **Request the feature** - Open an issue to request protocol support -## Version Compatibility +## Version compatibility | SDK Protocol Range | CLI Protocol Version | Compatibility | |--------------------|---------------------|---------------| @@ -284,7 +284,7 @@ const status = await client.getStatus(); console.log("Protocol version:", status.protocolVersion); ``` -## See Also +## See also - [Getting Started Guide](../getting-started.md) - [Hooks Documentation](../hooks/index.md) diff --git a/docs/troubleshooting/debugging.md b/docs/troubleshooting/debugging.md index 4d060cdd3..acc0a0f7f 100644 --- a/docs/troubleshooting/debugging.md +++ b/docs/troubleshooting/debugging.md @@ -1,8 +1,8 @@ -# Debugging Guide +# Debugging guide This guide covers common issues and debugging techniques for the Copilot SDK across all supported languages. -## Table of Contents +## Table of contents - [Enable Debug Logging](#enable-debug-logging) - [Common Issues](#common-issues) @@ -13,7 +13,7 @@ This guide covers common issues and debugging techniques for the Copilot SDK acr --- -## Enable Debug Logging +## Enable debug logging The first step in debugging is enabling verbose logging to see what's happening under the hood. @@ -108,7 +108,7 @@ var client = new CopilotClient(new CopilotClientOptions() -### Log Directory +### Log directory The CLI writes logs to a directory. You can specify a custom location: @@ -184,9 +184,9 @@ var client = new CopilotClient(new CopilotClientOptions --- -## Common Issues +## Common issues -### "CLI not found" / "copilot: command not found" +### "CLI not found" / "Copilot: command not found" **Cause:** The Copilot CLI is not installed or not in PATH. @@ -352,11 +352,11 @@ var client = new CopilotClient(new CopilotClientOptions --- -## MCP Server Debugging +## MCP server debugging MCP (Model Context Protocol) servers can be tricky to debug. For comprehensive MCP debugging guidance, see the dedicated **[MCP Debugging Guide](./mcp-debugging.md)**. -### Quick MCP Checklist +### Quick MCP checklist - [ ] MCP server executable exists and runs independently - [ ] Command path is correct (use absolute paths) @@ -364,7 +364,7 @@ MCP (Model Context Protocol) servers can be tricky to debug. For comprehensive M - [ ] Server responds to `initialize` request correctly - [ ] Working directory (`cwd`) is set if needed -### Test Your MCP Server +### Test your MCP server Before integrating with the SDK, verify your MCP server works: @@ -376,9 +376,9 @@ See [MCP Debugging Guide](./mcp-debugging.md) for detailed troubleshooting. --- -## Connection Issues +## Connection issues -### Stdio vs TCP Mode +### stdio vs TCP mode The SDK supports two transport modes: @@ -409,7 +409,7 @@ const client = new CopilotClient({ }); ``` -### Diagnosing Connection Failures +### Diagnosing connection failures 1. **Check client state:** ```typescript @@ -432,9 +432,9 @@ const client = new CopilotClient({ --- -## Tool Execution Issues +## Tool execution issues -### Custom Tool Not Being Called +### Custom tool not being called 1. **Verify tool registration:** ```typescript @@ -474,7 +474,7 @@ const client = new CopilotClient({ } ``` -### Tool Errors Not Surfacing +### Tool errors not surfacing Subscribe to error events: @@ -490,7 +490,7 @@ session.on("error", (event) => { --- -## Platform-Specific Issues +## Platform-specific issues ### Windows @@ -540,7 +540,7 @@ session.on("error", (event) => { --- -## Getting Help +## Getting help If you're still stuck: @@ -555,7 +555,7 @@ If you're still stuck: 3. **Open a new issue** with the collected information -## See Also +## See also - [Getting Started Guide](../getting-started.md) - [MCP Overview](../features/mcp.md) - MCP configuration and setup diff --git a/docs/troubleshooting/mcp-debugging.md b/docs/troubleshooting/mcp-debugging.md index d7b455ecf..4570638fe 100644 --- a/docs/troubleshooting/mcp-debugging.md +++ b/docs/troubleshooting/mcp-debugging.md @@ -1,8 +1,8 @@ -# MCP Server Debugging Guide +# MCP server debugging guide This guide covers debugging techniques specific to MCP (Model Context Protocol) servers when using the Copilot SDK. -## Table of Contents +## Table of contents - [Quick Diagnostics](#quick-diagnostics) - [Testing MCP Servers Independently](#testing-mcp-servers-independently) @@ -12,7 +12,7 @@ This guide covers debugging techniques specific to MCP (Model Context Protocol) --- -## Quick Diagnostics +## Quick diagnostics ### Checklist @@ -24,7 +24,7 @@ Before diving deep, verify these basics: - [ ] Server implements MCP protocol correctly (responds to `initialize`) - [ ] No firewall/antivirus blocking the process (Windows) -### Enable MCP Debug Logging +### Enable MCP debug logging Add environment variables to your MCP server config: @@ -45,11 +45,11 @@ mcpServers: { --- -## Testing MCP Servers Independently +## Testing MCP servers independently Always test your MCP server outside the SDK first. -### Manual Protocol Test +### Manual protocol test Send an `initialize` request via stdin: @@ -66,7 +66,7 @@ echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion": {"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"2024-11-05","capabilities":{"tools":{}},"serverInfo":{"name":"your-server","version":"1.0"}}} ``` -### Test Tool Listing +### Test tool listing After initialization, request the tools list: @@ -79,7 +79,7 @@ echo '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}' | /path/to/you {"jsonrpc":"2.0","id":2,"result":{"tools":[{"name":"my_tool","description":"Does something","inputSchema":{...}}]}} ``` -### Interactive Testing Script +### Interactive testing script Create a test script to interactively debug your MCP server: @@ -109,9 +109,9 @@ Usage: --- -## Common Issues +## Common issues -### Server Not Starting +### Server not starting **Symptoms:** No tools appear, no errors in logs. @@ -131,7 +131,7 @@ cd /expected/working/dir /path/to/command arg1 arg2 ``` -### Server Starts But Tools Don't Appear +### Server starts but tools don't appear **Symptoms:** Server process runs but no tools are available. @@ -155,7 +155,7 @@ cd /expected/working/dir - Server must respond to `initialize` correctly - Server must handle `notifications/initialized` -### Tools Listed But Never Called +### Tools listed but never called **Symptoms:** Tools appear in debug logs but model doesn't use them. @@ -185,7 +185,7 @@ cd /expected/working/dir - Ensure `inputSchema` is valid JSON Schema - Required fields must be in `required` array -### Timeout Errors +### Timeout errors **Symptoms:** `MCP tool call timed out` errors. @@ -208,7 +208,7 @@ cd /expected/working/dir 3. **For long-running tools**, consider streaming responses if supported. -### JSON-RPC Errors +### JSON-RPC errors **Symptoms:** Parse errors, invalid request errors. @@ -236,11 +236,11 @@ cd /expected/working/dir --- -## Platform-Specific Issues +## Platform-specific issues ### Windows -#### .NET Console Apps / Tools +#### .NET console apps / tools ```csharp @@ -291,7 +291,7 @@ public static class McpDotnetConfigExample } ``` -#### NPX Commands +#### npx commands ```csharp @@ -324,13 +324,13 @@ public static class McpNpxConfigExample } ``` -#### Path Issues +#### Path issues - Use raw strings (`@"C:\path"`) or forward slashes (`"C:/path"`) - Avoid spaces in paths when possible - If spaces required, ensure proper quoting -#### Antivirus/Firewall +#### Antivirus/firewall Windows Defender or other AV may block: - New executables @@ -340,14 +340,14 @@ Windows Defender or other AV may block: ### macOS -#### Gatekeeper Blocking +#### Gatekeeper blocking ```bash # If server is blocked xattr -d com.apple.quarantine /path/to/mcp-server ``` -#### Homebrew Paths +#### Homebrew paths ```typescript @@ -374,13 +374,13 @@ mcpServers: { ### Linux -#### Permission Issues +#### Permission issues ```bash chmod +x /path/to/mcp-server ``` -#### Missing Shared Libraries +#### Missing shared libraries ```bash # Check dependencies @@ -393,9 +393,9 @@ yum install libfoo # RHEL/CentOS --- -## Advanced Debugging +## Advanced debugging -### Capture All MCP Traffic +### Capture all MCP traffic Create a wrapper script to log all communication: @@ -426,7 +426,7 @@ mcpServers: { } ``` -### Inspect with MCP Inspector +### Inspect with MCP inspector Use the official MCP Inspector tool: @@ -439,7 +439,7 @@ This provides a web UI to: - View responses - Inspect tool schemas -### Protocol Version Mismatches +### Protocol version mismatches Check your server supports the protocol version the SDK uses: @@ -452,7 +452,7 @@ If versions don't match, update your MCP server library. --- -## Debugging Checklist +## Debugging checklist When opening an issue or asking for help, collect: @@ -465,7 +465,7 @@ When opening an issue or asking for help, collect: - [ ] Debug logs from SDK - [ ] Any error messages -## See Also +## See also - [MCP Overview](../features/mcp.md) - Configuration and setup - [General Debugging Guide](./debugging.md) - SDK-wide debugging